实验八:最优树Huffman 算法求解
实验目的和要求
实验目的:
Huffman 算法的一个经典应用就是 Huffman 编码,结合在图论部分对二元树这种图结构的学习,了解该算法在数据通信编码、图像压缩编码中的最直接应用。主要描述为:数据通信中经常需要将传送的内容转换成二进制编码,Huffman 编码是一种变长的编码方案,其核心是使频率越高的码采用越短的编码方式,同时所有码在解码时不会出现二义性。
理解最优二元树的编码原理,并借助 Huffman 算法实现最优树求解。
实验要求:
(1).借助已有平台基于 Huffman 算法求解实验最优二元树的求解。
(2).或自行编码实现最优二元树的求解及结果展示。
2. 实验环境和工具
开发环境:Visual Studio 2019
3. 实验结果
3.1 程序流程图
3.2 程序代码 (仅供参考,水平有限,有错请指出)
#include#include #include #include #include #include #include #include using namespace std; class Hnode { public: Hnode(int w, char a) { this->weight = w; this->data = a; this->lchild = NULL; this->rchild = NULL; } Hnode() { this->weight = 0; this->lchild = NULL; this->rchild = NULL; } string code;//哈夫曼编码(string型) //int* code;//哈夫曼编码(int型) int weight;//权值 char data;//字符 Hnode* lchild;//左子树 Hnode* rchild;//右子树 }; class HuffmanTree { public: HuffmanTree();//构造函数,读取文件创建与字符数相等的动态数组 Hnode* get_root();//取根结点 void Coding(Hnode* p);//编码 void input();//从文件中读入原文 void creat();//建树 void sort(int size);//构建过程中的排序 Hnode* combine(Hnode* t1, Hnode* t2);//取两个最小权值结点结合 void Delete(Hnode* insert, int size);//结合后删除列表中那两个被结合的结点 void read();//读取文件中的原文 void load_code(Hnode* p);//将字符与对应的编码储存到数组中 void Print(Hnode* p);//大音哈夫曼树 void Mid(Hnode* p);//中序遍历哈夫曼树 private: int weight[126] = { 0 }; int num; Hnode** w; Hnode* root; string a[126];//存码表 vector v; }; HuffmanTree::HuffmanTree() { this->read(); w = new Hnode * [num]; } Hnode* HuffmanTree::get_root() { return this->root; } void HuffmanTree::Mid(Hnode* p) { if (p != NULL) { Mid(p->lchild); v.push_back(p); Mid(p->rchild); } } void HuffmanTree::Print(Hnode* p) { string template_str;//模板string,表示每行打印string的长度 int location = 0; unordered_map first_locations;//存储节点对应在本行string中的首位置 for (auto& i : v) { location = template_str.size(); template_str += to_string(i->weight) + " "; first_locations[i] = location; } for (auto& i : template_str)//把模板全部置为空格方便后续使用 i = ' '; queue q;//逐层按序遍历 q.push(p); while (!q.empty()) { int currentLevelSize = q.size(); int cur_loc = 0; string tmp_str1 = template_str, tmp_str2 = template_str;//1为节点所在行,2为其下一行 for (int i = 1; i <= currentLevelSize; ++i) { Hnode* node = q.front(); q.pop(); cur_loc = first_locations[node]; string num_str = to_string(node->weight); //左边,如果存在左孩子,那么在第二行对应位置打印'/',在第一行补上'_' if (node->lchild) { q.push(node->lchild); int first_loc = first_locations[node->lchild] + 1; tmp_str2[first_loc++] = '/'; while (first_loc < cur_loc)tmp_str1[first_loc++] = '_'; } //中间,对应位置打印节点值(有可能为多位数) for (int j = 0; j < num_str.length(); ++j, ++cur_loc) { tmp_str1[cur_loc] = num_str[j]; } //右边,如果存在右孩子,那么在第二行对应位置打印'',在第一行补上'_' if (node->rchild) { q.push(node->rchild); int last_loc = first_locations[node->rchild] - 1; tmp_str2[last_loc] = '\'; while (cur_loc < last_loc) { tmp_str1[cur_loc++] = '_'; } } } //打印两行 cout << tmp_str1 < data != NULL) { a[int(p->data)] = p->code; } load_code(p->lchild); load_code(p->rchild); } } void HuffmanTree::read() { ifstream ifs; ifs.open("original_test1.txt", ios::in); if (!ifs.is_open()) { cout << "文件打开失败" << endl; return; } string file; while (!ifs.fail()) { string buf; getline(ifs, buf); file += buf; file += 'n'; } file.pop_back(); file.pop_back(); for (int i = 0; i < file.size(); i++) { weight[int(file[i])]++; } this->num = 0; int j = 0; for (; j < 126; j++) { if (weight[j] != 0) { num++; } } ifs.close(); } void HuffmanTree::input() { int j = 0, k = 0; for (; j < 126; j++) { if (weight[j] != 0) { w[k] = new Hnode(weight[j], char(j)); k++; } } } void HuffmanTree::sort(int size) { Hnode* temp = new Hnode; for (int i = 0; i < size; i++) { for (int j = 0; j < size - 1 - i; j++) { if (w[j]->weight > w[j + 1]->weight) { temp = w[j]; w[j] = w[j + 1]; w[j + 1] = temp; } } } } Hnode* HuffmanTree::combine(Hnode* t1, Hnode* t2) { Hnode* temp = new Hnode; temp->weight = t1->weight + t2->weight; temp->lchild = t1; temp->rchild = t2; return temp; } void HuffmanTree::Delete(Hnode* insert, int size) { w[0] = insert; for (int i = 1; i < size - 1; i++) w[i] = w[i + 1]; } void HuffmanTree::creat() { for (int i = 0; i < num - 1; i++) { sort(num - i); root = combine(w[0], w[1]); Delete(root, num - i); } } void HuffmanTree::Coding(Hnode* p) { if (p != NULL) { if (p->lchild != NULL) { p->lchild->code = p->code + '0'; } if (p->rchild != NULL) { p->rchild->code = p->code + '1'; } //if (p->data != ' ') cout << "字符:" << p->data << " 权值:" << p->weight << " 编码:" << p->code << endl; Coding(p->lchild); Coding(p->rchild); } } int main() { HuffmanTree H; H.input(); H.creat(); cout << "哈夫曼编码如下:" << endl; H.Coding(H.get_root()); H.load_code(H.get_root()); H.Mid(H.get_root()); H.Print(H.get_root()); return 0; }
3.3 运行结果
其他实验:
合肥工业大学2021离散数学上机实验一https://blog.csdn.net/qq_52791068/article/details/122654230
合肥工业大学2021离散数学上机实验四https://blog.csdn.net/qq_52791068/article/details/122656507
合肥工业大学2021离散数学上机实验六https://blog.csdn.net/qq_52791068/article/details/122656801



