[问题描述]
利用哈夫曼编码进行通信,可以压缩通信的数据量,提高传输效率,缩短信息的传输时间,还有一定的保密性。现在要求编写一程序模拟传输过程,实现在发送前将要发送的字符信息进行编码,然后进行发送,接收后将传来的数据进行译码,即将信息还原成发送前的字符信息。
[实现提示]
在本例中设置发送者和接受者两个功能,
发送者的功能包括:
①输入待传送的字符信息;
②统计字符信息中出现的字符种类数和各字符出现的次数(频率);
②根据字符的种类数和各自出现的次数建立哈夫曼树;
③利用以上哈夫曼树求出各字符的哈夫曼编码;
④将字符信息转换成对应的编码信息进行传送。
接受者的功能包括:
①接收发送者传送来的编码信息;
②利用上述哈夫曼树对编码信息进行翻译,即将编码信息还原成发送前的字符信息。
从以上分析可发现,在本例中的主要算法有三个:
(1)哈夫曼树的建立;
(2)哈夫曼编码的生成;
(3)对编码信息的翻译。
源代码
#include<iomanip> #include<stdlib.h> #include<string.h> #include<stdio.h> #include<iostream> using namespace std; #define maxsize 100 struct frequence//统计频率 { char a;//存放字符 int n;//该字符出现的次数 }; typedef struct { unsigned int weight; // 用来存放各个结点的权值 unsigned int parent, lchild, rchild;//指向双亲、 孩子结点的指针 }HTNode, *HuffmanTree; //动态分配数组存储赫夫曼树 typedef char **HuffmanCode;//动态分配数组存储赫夫曼编码表 int W[maxsize], *w;//存放字符的权值 int c1 = 0;//输入报文的长度 frequence ch[27];//26个英文字母,0号位置不存储字符,用来存储总共的字符个数,多次出现的只记一次 char a[maxsize];//存放所有的字符 int Frequent() { int i = 0; for (; i <= 26; i++)//初始化结构体数组 { ch[i].n = 0; } cout << "输入电报:(输入#键结束输入):"; char c; cin >> c; while (c != '#') { a[c1] = c; bool flag; i = 1; flag = false; for (; i <= ch[0].n; i++) { if (c == ch[i].a) { flag = true; break; } } if (flag)//已存在 { ch[i].n++; } else//不存在 { ch[0].n++; ch[ch[0].n].n++; ch[ch[0].n].a = c; } c1++; cin >> c; } cout << "报文的长度:" << c1 << endl; for (int j = 1; j <= ch[0].n; j++) { cout << ch[j].a << " " << ch[j].n << " "; W[j - 1] = ch[j].n; } cout << endl; cout << "不重复字符的总个数:" << ch[0].n << endl; w = W; } void Select(HuffmanTree HT, int i, int &s1, int &s2) { int j, k = 1; while (HT[k].parent != 0) k++; s1 = k; for (j = 1; j <= i; ++j) if (HT[j].parent == 0 && HT[j].weight<HT[s1].weight) s1 = j; k = 1; while ((HT[k].parent != 0 || k == s1)) k++; s2 = k; for (j = 1; j <= i; ++j) if (HT[j].parent == 0 && HT[j].weight<HT[s2].weight&&j != s1) s2 = j; } void HuffmanCoding(HuffmanTree &HT, HuffmanCode&HC, int *w, int n) { //w存放n个权值, 构造哈夫曼树p, 并求出哈夫曼编码hc int m, i, s1, s2, start, c, f; HuffmanTree p; if (n <= 1) return; m = 2 * n - 1;//总结点数 HT = (HuffmanTree)malloc((m + 1)*sizeof(HTNode));//0号单元未用 for (p = HT + 1, i = 1; i <= n; ++i, ++p, ++w) { p->weight = *w; p->parent = 0; p->lchild = 0; p->rchild = 0; } for (; i <= m; ++i, ++p) { p->weight = 0; p->parent = 0; p->lchild = 0; p->rchild = 0; } cout << endl << endl << "建立的哈夫曼树如下列次序:"; for (i = n + 1; i <= m; ++i)//建立赫夫曼树 { Select(HT, i - 1, s1, s2); HT[s1].parent = i; HT[s2].parent = i; HT[i].lchild = s1; HT[i].rchild = s2; HT[i].weight = HT[s1].weight + HT[s2].weight; cout << endl << "HT[" << s1 << "] and HT[" << s2 << "] create"; cout << " HT[" << i << "], weight=" << HT[i].weight << endl; } //从叶子到根逆向求每个字符的赫夫曼编码 HC = (HuffmanCode)malloc((n + 1)*sizeof(char *));//分配n个字符编码的走指针向量 char *cd; cd = (char *)malloc(n*sizeof(char));//分配求编码的工作空间 cd[n - 1] = '