哈夫曼编码译码的应用(0.9a版)

来源:互联网 发布:java中的构造器是什么 编辑:程序博客网 时间:2024/06/05 19:22

一. 设计思路

1. 生成明文的 { 字符 + 权 } 集

2. 构造Huffman树(贪心法 + 自底向上)

3. 利用Huffman树,对明文进行编码

4. 利用huffman树,对编码译码为明文

二. 生成明文的 { 字符 + 权 } 集

1. 字符表:包括字符项目和权值项。

<span style="font-size:14px;">#define N 256//字符表struct charcode {char c; //字符int w;  //权值};struct charcode ctable[N];//全局变量,明文中出现的字符个数int num = 0;</span>

2. 在字符表中查找字符

<span style="font-size:14px;">//在字符表中查找字符,成功找到则返回字符位置;不成功返回-1int find (char ch){int i;for(i = 0; ctable[i].c != 0; i++){if(ctable[i].c == ch) //找到字符{return i;}}return i;//未找到}</span>

3. 然后记录字符出现的频率(权值)

<span style="font-size:14px;">//在字符表中查找字符,成功返回字符位置;不成功返回0//然后记录字符出现的频率(权值)void getweight(){char ch;freopen("plaintext.txt", "r", stdin);while((ch=getchar())!=EOF){int i = find(ch);//查找字符位置if(!ctable[i].c)//若字符表相应的位置未存放字符{ctable[i].c = ch;//存入字符num++;//字符数加1}ctable[i].w++; //权值加1}fclose(stdin);}</span>

二. 构造Huffman树

1. Huffman树结构:字符,权,父亲下标,左孩子下标,右孩子下标

<span style="font-size:14px;">//Huffman树结构:字符,权,父亲下标,左孩子下标,右孩子下标struct treenode//静态链表{char c; //charint w;  //weightint f;  //fatherint l;  //left child indexint r;  //right child index};//N个外部结点,总结点不超过2N - 1struct treenode htree[2 * N - 1];</span>

2. 按权值排序

<span style="font-size:14px;">//使用选择法进行排序void sort(){int i,j;struct charcode t;for(i = 0; i < num; i++) //每次选择最小的权值{int m = i; //m记录最小权值的下标for(j = i + 1; j < num; j++){if(ctable[j].w < ctable[m].w){m = j;}}t = ctable[m];ctable[m] = ctable[i];ctable[i] = t;}}</span>

三. 构建Huffman树

<span style="font-size:14px;">//使用贪心法建立Huffman树,每次选择权值最小的根节点void huffman(){int i, j, k, n;for(i = 0; i < num; i++){//初始化哈夫曼表htree[i].c = ctable[i].c;htree[i].w = ctable[i].w;htree[i].l = htree[i].f = htree[i].r = -1;//printf("[%d]%c: %d\n",i, htree[i].c, htree[i].w);}j = 0;//j记录叶子节点的下标k = num;//K记录内部节点的下标for(n = num; n < 2 * num -1; n++){//每次选择权值最小int r = 0, s = 0;htree[n].l = htree[n].f = htree[n].r = -1;while(r < 2){if(htree[k].w == 0 || htree[k].w > htree[j].w && j < num){s+=htree[j].w;//加入父亲的权值if(r == 0){htree[n].l = j;//左孩子}else{htree[n].r = j;//右孩子}htree[j].f = n;//父亲j++;}else{//选择内部结点s+=htree[k].w;if(r == 0){htree[n].l = k;}else{htree[n].r = k;}htree[k].f = n;k++;}r++;}htree[n].w = s;//父亲的权值}}</span>

四. Huffman编码

<span style="font-size:14px;">//从plaintext.txt中读入明文,生成编码,存入telgraph.txt中void encode(){char ch;freopen("plaintext.txt", "r", stdin);freopen("telegraph.txt", "w", stdout);char* str= (char*)malloc(sizeof(char) * N);while((ch=getchar()) != EOF){int i = find(ch);memset(str,0,sizeof(char) * N);getcode(i, str);printf("%s", str);}fclose(stdout);fclose(stdin);//free(str);}</span>

<span style="font-size:14px;">//根据字符所在的下标,从叶子节点往上搜索到根节点//然后逆置得到该字符的huffman编码void getcode(int i, char* str){int n, j, l = 0;for(n = i;htree[n].f != -1; n = htree[n].f){//沿着父亲往上搜索int m = htree[n].f;if(n == htree[m].l){str[l++] = '0';//左孩子记为0}else{str[l++] = '1';//右孩子记为1}}for(j = 0; j <= (l -1)/2;j++){//将编码逆置char t;t = str[j];str[j] = str[l - 1 -j];str[l - 1 - j] = t;}str[l] = '\0';//str存放huffman编码,字符串结束标记}</span>

五. Huffman译码 

<span style="font-size:14px;">//从telgraph.txt中读入编码,译码为明文//存入tanslation.txtvoid decode(){char ch;freopen("telegraph.txt", "r", stdin);freopen("tanslation.txt", "w", stdout);ch = getchar();//根据编码,从根节点往下搜索到叶子节点,得到该编码的字符while(ch != EOF){int i;for(i = 2 * num - 2; htree[i].l != -1;){if(ch == '0'){i = htree[i].l;}else{i = htree[i].r;}ch = getchar();}printf("%c", htree[i].c);} fclose(stdout); fclose(stdin);}</span>

六. 主函数

<span style="font-size:14px;">//思路:主函数实现实验任务的基本流程int _tmain(int argc, _TCHAR* argv[]){getweight();//记录字符出现的频率(权值)sort();//权值排序huffman();//建立Huffman树encode();//编码decode();//译码return 0;}</span>

七. VC 2008 HumanTest 案例 http://download.csdn.net/detail/u013354805/8849497

5 0
原创粉丝点击