diff --git a/huffman_code.h b/huffman_code.h new file mode 100644 index 0000000..0cddb15 --- /dev/null +++ b/huffman_code.h @@ -0,0 +1,110 @@ +// +// Created by dongl on 22-11-13. +// + +#ifndef CPP_DATA_STRUCT_HUFFMAN_CODE_H +#define CPP_DATA_STRUCT_HUFFMAN_CODE_H +#include + +/// 解压缩 业务逻辑操作的类 +class HTCode { +private: + char data_char{}; // 待编码的字符 + std::byte code[10]{}; // 字符的解压缩编码 + std::fstream file; // 文件流 + //Huffman huffman; // 哈夫曼结构 + Alphabet* alphabet; // 字符权重映射表 + +public: + + HTCode* Open(const std::string& file_path, Alphabet* alpha = new Alphabet[27]){ // 记录字符与字符出现次数 + + // 记录字符数组的 初始化 + // 初始化字符 出现次数 映射表 只支持中文 + for (int i = 1; i <= 26; ++i) { + alpha[i].count = 0; + alpha[i].data = i + 97 - 1; + } + + // 打开文件 + file.open(file_path, std::ios::in); + if(!file.is_open()){ + std::cerr << "open '" << file_path << "' fail" <> c; + count++; + ascii = (int) c; + + // 小写 小写区间 + if (ascii >= 65 && ascii <= 90){ + // 65 - 65 + 1 下标 alpha[1] + alpha[ascii - 65 + 1].count++; + c_count++; + } + // 大写 + if (ascii >= 97 && ascii <= 122){ + alpha[ascii - 97 + 1].count++; + c_count++; + } + + std::cout << c; + } + + std::cout << std::endl; + std::cout << "总字符数" << count << "\n"; + std::cout << "字母字符数" << c_count << "\n"; + std::cout << "其他字符数" << count - c_count << std::endl; + file.close(); + + for (int i = 1; i <= 26; ++i) { + printf("[%d] : %c - %d \n", i, (char)alpha[i].data, alpha[i].count); + } + + alphabet = alpha; + return this; + } + + + /// 建立哈夫曼表码表 利用哈夫曼树 将各个字符对应的编码表 保存在文件 {file}.txt.hmz + void CreateHuffmanCode(){ + HuffmanTree ht = this->CreateHuffmanTree(); + // 从叶子节点到根 逆向求每个字符的哈夫曼编码, 存在编码表中 + char *cd = new char[26]; + new char* [26 + 1]; + cd[26-1] = '\0'; + +// for (int i = 1; i <= 26; ++i) { +// int start = 26 - 1; +// int c = i; +// auto f = ht[i].parent; +// while (f != 0){ +// --start; +// if(f != 0){ +// +// } +// } +// } + } + +private: + HuffmanTree CreateHuffmanTree(){ + HuffmanTree ht = (new Huffman(26, alphabet))->getHuffmanTree(); + + for (int i = 1; i <= 2 * 26 - 1; ++i) { + printf("下标%d,值%c, 权重%d, ", i, ht[i].info, ht[i].weight); + std::cout << "双亲" << ht[i].parent <<", 左叶子" << ht[i].left << ", 右叶子" << ht[i].right << std::endl; + } + return ht; + } +}; + +#endif //CPP_DATA_STRUCT_HUFFMAN_CODE_H diff --git a/huffman_tree.h b/huffman_tree.h new file mode 100644 index 0000000..86eeb0f --- /dev/null +++ b/huffman_tree.h @@ -0,0 +1,109 @@ +// +// Created by dongl on 22-11-11. +// + +#ifndef CPP_DATA_STRUCT_HUFFMAN_TREE_H +#define CPP_DATA_STRUCT_HUFFMAN_TREE_H +#include +#include + +/// 可变长度的字符串 树组 +typedef char** huffman_code; + +/// 哈夫曼节点结构 一棵树的节点结构 +struct HTNodeBase { + struct HTNodeBase* parent; // 父节点 + struct HTNodeBase* left; // 左子节点 + struct HTNodeBase* right; // 右子节点 +}; + +/// 哈夫曼节点结构 一棵树的节点信息 +typedef struct HTNode : public HTNodeBase{ + int weight; // 节点权重 + int index; // 下标 + char info; // 节点信息 +} *HuffmanTree; + + +/// 字母信息 与 出现的次数 +struct Alphabet { + char data; // 字符 + int count; // 字母出现次数 +}; + +/// 哈夫曼树 一棵树的结构 +/// 构建树 操作树 的类 +class Huffman{ +private: + HuffmanTree ht; // 树根 + int tree_node_sum{}; // 树的叶子数 +public: + // 构建哈夫曼树 + Huffman(int n, Alphabet* alphabet) { + // 如果节点小于1 没有必要构建 直接return + if (n <= 1) + return; + + // 树的空间 + // 0号单元未用 ht[2 * n - 1]表示根节点 + int m = 2 * n - 1; + ht = new HTNode[m + 1]; + // 构建树的全部节点 + for (int i = 1; i <= m; ++i) { + ht[i].left = nullptr; + ht[i].right = nullptr; + ht[i].parent = nullptr; + } + // 构建存在个数节点的 字符与权重 + for (int i = 1; i <= n; ++i) { + ht[i].weight = alphabet[i].count; + ht[i].info = alphabet[i].data; + } + + // 正式 构建 构造 huffman 的节点关系 点与点之间的关系 + for (int i = n+1; i < m; ++i) { + // 左右节点 + int s1,s2; + SelectHuffmanTree(i, s1, s2); + // 表示从F中删除s1 ,s2 + ht[i].left = &ht[s1]; + ht[i].right = &ht[s2]; + // s1 和 s2 分为为 i 的 左右叶子 权值为他俩的和 + ht[i].weight = ht[s1].weight + ht[s2].weight; + } + } + + HuffmanTree getHuffmanTree() { + return ht; + } + +private: + /// 建立哈夫曼树 根据统计结果 + /// @param ht + /// @param n + /// @param s1 + /// @param s2 + void SelectHuffmanTree(int n, int& s1, int& s2){ + s1 = min_index(n - 1); + s2 = min_index(n - 1); + } + + inline int min_index(int n){ + int min; + int min_weight; + + for (int i = 1; i <= n; ++i) { + // 没有父节点 未分配过的 + if(ht[i].parent == nullptr){ + min = i; + min_weight = ht[i].weight; + } + } + ht[min].parent = &ht[n + 1]; + std::cout << "min=" << min << ", n=" << n << ", parent=" + << ht[min].parent << ", weight=" << ht[min].weight + << ", info=" << ht[min].info << std::endl; + return min; + } +}; +#endif //CPP_DATA_STRUCT_HUFFMAN_TREE_H