PS:仅数据结构实验记录
题目:根据哈夫曼(Huffman)编码的原理,编写一个程序,在用户输入节点权重的基础上建立它的哈夫曼编码。
#includeusing namespace std; const int Max = 10; struct ElemType { int weight; //记录权值,假定权值为整数 int parent, lchild, rchild; //游标 char hCode[Max]; //哈夫曼编码 //string Node; }; //HuffmanTree类 class HuffmanTree { public: HuffmanTree(int w[], int n); //有参构造函数 HuffmanTree(); //无参构造函数 void huffmanTreeCode( int n); //哈夫曼编码 void Print(); //输出路径 void PrintTreeCode(int n); private: ElemType* huffTree; int num; void Select(int n, int& i1, int& i2); //权值最小的根节点下标 }; //选取最小的两个权值下标 void HuffmanTree::Select(int n, int& i1, int& i2) { int i = 0, temp; for (; i < n; i++) //寻找第一个没有双亲的节点,下标赋值给i1 if (huffTree[i].parent == -1) { i1 = i; break; } for (i = i + 1; i < n; i++) //寻找第二个没有双亲的节点,下标赋值给i2 if (huffTree[i].parent == -1) { i2 = i; break; } if (huffTree[i1].weight > huffTree[i2].weight)//比较i1和i2大小,小的下标赋给i1,大的i2 { temp = i1; i1 = i2; i2 = temp; } for (i = i + 1; i < n; i++) // 遍历i后的权值,更新i1和i2 { if (huffTree[i].parent == -1) { //权值小于i1,则i1赋值给i2、i赋值给i1 if (huffTree[i].weight < huffTree[i1].weight) { i2 = i1; i1 = i; } else if (huffTree[i].weight < huffTree[i2].weight) //权值小于i2,i赋值给i2 { i2 = i; } } } } //有参构造函数 HuffmanTree::HuffmanTree(int w[], int n) { int i, k, i1, i2; huffTree = new ElemType[2 * n - 1]; num = n; for (i = 0; i < 2 * num - 1; i++) //初始化,所有结点均没有双亲和孩子 { huffTree[i].parent = -1; huffTree[i].lchild = huffTree[i].rchild = -1; } for (i = 0; i < num; i++) //存储叶子结点的权值 huffTree[i].weight = w[i]; for (k = num; k < 2 * num - 1; k++) //n-1次合并 { Select(k, i1, i2); //权值最小的根结点下标为i1和i2 huffTree[k].weight = huffTree[i1].weight + huffTree[i2].weight; huffTree[i1].parent = k; huffTree[i2].parent = k; huffTree[k].lchild = i1; huffTree[k].rchild = i2; } } //确定权值编码 void HuffmanTree::huffmanTreeCode(int n) { char hc[Max]; int hcLen; int i, j, k, parent, p; for (i = 0; i < n; i++) { hcLen = 0; parent = huffTree[i].parent; //待编码字符的双亲结点下标 p = i; while (parent != -1) //未到达根结点 { if (huffTree[parent].lchild == p) //左孩子 hc[hcLen] = '0', hcLen++; else if (huffTree[parent].rchild == p) //右孩子 hc[hcLen] = '1', hcLen++; p = parent; parent = huffTree[parent].parent; //继续向根结点查找 } for (j = 0, k = hcLen - 1; j < hcLen; j++, k--) //将编码写入相应字符数组 huffTree[i].hCode[j] = hc[k]; huffTree[i].hCode[j] = ' '; //字符串结束符 } return; } //打印权值路径 void HuffmanTree::Print() { int i, k; cout << "n每个叶子到根结点的路径是:" << endl; for (i = 0; i < num; i++) { cout << huffTree[i].weight; k = huffTree[i].parent; while (k != -1) { cout << "-->" << huffTree[k].weight; k = huffTree[k].parent; } cout << endl; } cout << "n"; } //打印权值的哈夫曼编码 void HuffmanTree::PrintTreeCode(int n) { for (int i = 0; i < n; i++) { int j = 0; cout << "权值为: " << huffTree[i].weight << "t哈夫曼编码为: " << huffTree[i].hCode << endl; } } //测试 int main() { cout << "请输入叶子节点的个数: "; int n,j; cin >> n; int* w = new int[n]; for (int i = 0; i < n; i++) { cout << "请输入各叶子节点的权值大小(整数类型):"; cin >> j; w[i] = j; } HuffmanTree T{ w, n }; T.huffmanTreeCode(n); T.Print(); T.PrintTreeCode(n); delete[]w; return 0; }
测试结果



