#include <iostream> #include <iomanip> #include <string> #include <cstdlib> using namespace std; //定义哈夫曼树存储结构 typedef struct { char data; //存放结点数据 int weight; //记录结点权值 int parent, lchild, rchild; }HTNode, * HuffmanTree; //哈夫曼编码存储表示 typedef char** HuffmanCode; //动态分配数组储存哈夫曼编码表 //初始化 HuffmanTree InitHuffman(HuffmanTree& HT, int n) { if (n < 0) { cout << "输入初态结点数目不正确!!!" << endl; return NULL; } else { int m = 2 * n - 1; //n个叶子结点的哈夫曼树有2n-1个结点 HT = new HTNode[m + 1]; //0号单元未用,申请m+1个空间 for (int i = 1; i <= m; i++) { HT[i].parent = 0; HT[i].lchild = 0; HT[i].rchild = 0; HT[i].weight = 0; HT[i].data = '-'; } //输入初始数据,为了方便理解HT[0]不存放数据 cout << "请输入初态结点数据及相应权值(格式形式:a 3):"; for (int i = 1; i <= n; i++) { cin >> HT[i].data; cin >> HT[i].weight; } return HT; } } //打印HT void PrintState(HuffmanTree& HT, int n) { int m = 2 * n - 1; //总结点数 cout << "结点i data值 weight parent lchild rchild" << endl; for (int i = 1; i <= m; i++) { cout << setw(3) << i << " "; cout << setw(4) << HT[i].data << " "; cout << setw(4) << HT[i].weight << " "; cout << setw(4) << HT[i].parent << " "; cout << setw(4) << HT[i].lchild << " "; cout << setw(4) << HT[i].rchild << " " << endl; } } //选择双亲域为0且两权值最小的结点,选择范围为1到i-1 int* Select(HuffmanTree& HT, int n, int* Idx) { int MIN, MinSecond; //打擂台法使权最小值和次权最小值最大(假设第一个值权值最小无法进行) MIN = MinSecond = 99999; //循环从1到n次 for (int i = 1; i <= n; i++) { //如果双亲为0(未删除结点与新生成结点),一定会执行if语句,寻找权最小值 if ((HT[i].parent == 0) && HT[i].weight < MIN) { //将最小的权值给MinSecond方便寻找次最小值 MinSecond = MIN; MIN = HT[i].weight; //记录权最小值下标 Idx[0] = i; } //否则如果满足条件寻找次最小值 else if ((HT[i].parent == 0) && HT[i].weight < MinSecond) { MinSecond = HT[i].weight; //记录权次最小值下标 Idx[1] = i; } } return Idx; } //构造哈夫曼树 void CreateHuffmanTree(HuffmanTree& HT, int n) { if (n <= 1) return; int m = 2 * n - 1; //n个叶子结点的哈夫曼树有2n-1个结点 //从n+1开始构造哈弗曼树 for (int i = n + 1; i <= m; i++) { //Idx用于存放两个返回最小权值的下标,i-1为前n个结点,后面随着i增加,n也增加 int* Idx = Idx = new int[2]; Idx = Select(HT, i - 1, Idx); int s1 = Idx[0]; //权最小值下标 int s2 = Idx[1]; //权次最小值下标 //给两权值最小的结点置双亲,使s1,s2结点不在录入Select范围 HT[s1].parent = i; HT[s2].parent = i; //给新节点i左右孩子置位s1,s2 HT[i].lchild = s1; HT[i].rchild = s2; //给新结点赋权值 HT[i].weight = HT[s1].weight + HT[s2].weight; delete[]Idx; } } //哈夫曼编码 void CreateHuffmanCode(HuffmanTree& HT, HuffmanCode& HC, int n) { HC = new char* [n + 1]; //分配字符的空间 char* TempCode = new char[n]; //分配临时编码表空间n个 TempCode[n - 1] = '