哈夫曼树

来源:互联网 发布:海关数据免费查询 编辑:程序博客网 时间:2024/05/01 05:35

1. 哈夫曼树结构和操作定义

HuffmanTree.h

//功能:霍夫曼树结构体typedef struct{int weight;//权值int parent;//父节点序号int left;//左子树序号int right;//右子树序号}HuffmanTree;typedef char *HuffmanCode;//Huffman编码指针/*---------------------HuffmanTree树所有操作原型声明 start ------------------------*///功能:创建HuffmanTreevoid CreateTree(HuffmanTree *ht, int n, int *w);//功能:从n个节点中选择parent节点为0,权重最小的两个节点void SelectNode(HuffmanTree *ht, int n, int *bt1, int *bt2);//功能:根据HuffmanTree生成每个字符的哈夫曼编码 //倒序编码:从叶节点开始向根节点查找,生成各叶节点的哈夫曼编码void HuffmanCoding(HuffmanTree *ht, int n, HuffmanCode *hc);//功能:将一个字符串转换为哈夫曼编码void Encode(HuffmanCode *hc, char *alphabet, char *str, char *code);//功能:将一个哈夫曼编码组成的字符串转换为明文字符串void Decode(HuffmanTree *ht, int m, char *code, char *alphabet, char *decode);/*---------------------HuffmanTree树所有操作原型声明 end --------------------------*//*---------------------HuffmanTree树所有操作具体实现 start ------------------------*///功能:创建HuffmanTreevoid CreateTree(HuffmanTree *ht, int n, int *w){int i, m=2*n-1;    //m为节点总数int bt1, bt2;      //保存权重最小的节点序号if(n<=1){printf("只有一个叶子节点,无法创建HuffmanTree!!");return;}//初始化叶节点for(i=1; i<=n; i++){ht[i].weight = w[i-1];ht[i].parent = 0;ht[i].left = 0;ht[i].right = 0;}//清空非叶节点for(; i<=m; i++){ht[i].weight = 0;ht[i].parent = 0;ht[i].left = 0;ht[i].right = 0;}//逐个计算非叶节点,创建HuffmanTree(根节点的编号为m)for(i=n+1; i<=m; i++){SelectNode(ht, i-1, &bt1,&bt2);ht[bt1].parent = i;ht[bt2].parent = i;ht[i].left = bt1;ht[i].right = bt2;ht[i].weight = ht[bt1].weight + ht[bt2].weight;}return;}//功能:从n个节点中选择parent节点为0,权重最小的两个节点void SelectNode(HuffmanTree *ht, int n, int *bt1, int *bt2){int i;HuffmanTree *ht1, *ht2, *t;ht1 = ht2 = NULL;for(i=1; i<=n; i++){if(!ht[i].parent){if(ht1==NULL){ht1=ht+i;continue;}if(ht2==NULL){ht2=ht+i;if(ht1->weight > ht2->weight){t = ht2;ht2 = ht1;ht1 = t;}continue;}if(ht1 && ht2){if(ht[i].weight <= ht1->weight){ht2 = ht1;ht1 = ht+i;}else if(ht[i].weight < ht2->weight)ht2 = ht + i;}}}//保证二叉树左侧为叶节点if(ht1>ht2){*bt1 = ht2-ht;*bt2 = ht1-ht;}else{*bt1 = ht1-ht;*bt2 = ht2-ht;}return;}//功能:根据HuffmanTree生成每个字符的哈夫曼编码,n为叶子节点数void HuffmanCoding(HuffmanTree *ht, int n, HuffmanCode *hc){char *cd;int start, i;int current, parent;cd = (char *)malloc(sizeof(char)*n);//用来临时存放一个字符的编码结果cd[n-1] = '\0';for(i=1; i<=n; i++){start=n-1;current=i;parent = ht[current].parent;while(parent){if(current==ht[parent].left)cd[--start]='0';elsecd[--start]='1';current = parent;//设置当前节点指向父节点parent = ht[parent].parent;//获取当前节点的父节点序号}hc[i-1] = (char *)malloc(sizeof(char)*(n-start));strcpy(hc[i-1], &cd[start]);}free(cd);return;}//功能:将一个字符串转换为哈夫曼编码void Encode(HuffmanCode *hc, char *alphabet, char *str, char *code){int len=0, i=0, j;code[0]='\0';while(str[i]){j=0;while(alphabet[j] != str[i])   //查哈夫曼编码表j++;strcpy(code+len, hc[j]);len +=strlen(hc[j]);i++;}code[len] = '\0';return;}//功能:将一个哈夫曼编码组成的字符串转换为明文字符串void Decode(HuffmanTree *ht, int m, char *code, char *alphabet, char *decode){int position=0, i, j=0;m=2*m-1;while(code[position]){for(i=m; ht[i].left &&ht[i].right; position++){//根节点标号为m,从根节点出发查找叶子节点if(code[position]=='0')i=ht[i].left;elsei=ht[i].right;}  decode[j]=alphabet[i-1];//得到一个字母j++;}decode[j]='\0';return;}/*---------------------HuffmanTree树所有操作具体实现 start ------------------------*/

2.哈夫曼树操作测试

HuffmanTreeTest.cpp

#include<stdio.h>#include<stdlib.h>#include<string.h>#include "HuffmanTree.h"int main(){int i, n, m, select;//char test[] ="DBDBDABDCDADBDADBDADACDBDBD";//测试字符串char testStr[50];char encode[100], decode[100];//char alphabet[]={'A','B','C','D'};char *alphabet;//int w[] = {5, 7, 2, 13};//4个字符的权值int *w;HuffmanTree *ht;HuffmanCode *hc;//哈夫曼编码字符串指针do{printf("---------------------------\n");printf("1.创建HuffmanTree               2.根据HuffmanTree生成哈夫曼编码\n");printf("3.利用哈夫曼编码加密字符串      4.利用哈夫曼编码解密“加密字符串”\n");printf("0.退出\n");printf("请选择执行的操作序号:");fflush(stdin);scanf("%d", &select);switch(select){case 1:printf("请输入叶子节点的数目:");fflush(stdin);scanf("%d", &n);m=2*n-1;ht=(HuffmanTree *)malloc((m+1)*sizeof(HuffmanTree));//申请内存,保存哈夫曼树if(!ht){printf("内存分配失败!!");exit(0);}alphabet = (char *)malloc((n+1)*sizeof(char));w = (int *)malloc((n+1)*sizeof(int));for(int j=0; j<n; j++){printf("请输入第%d个叶子节点及其权值:",j+1);fflush(stdin);scanf("%s %d", &alphabet[j], &w[j]);}CreateTree(ht, n, w);break;case 2:if(!ht){printf("请先创建HuffmanTree!!");continue;}hc=(HuffmanCode *)malloc(n*sizeof(char *));//申请内存,保存哈夫曼树if(!hc){printf("内存分配失败!!");exit(0);}HuffmanCoding(ht, n, hc);for(i=1; i<=n; i++)printf("字母:%c,权重:%d,编码为%s\n", alphabet[i-1], ht[i].weight, hc[i-1]);break;case 3:printf("请输入需要编码的字符串:");fflush(stdin);scanf("%s", testStr);Encode(hc, alphabet, testStr, encode);printf("字符串:%s\n,编码后为:%s\n", testStr,encode);break;case 4:Decode(ht, n, encode, alphabet, decode);printf("\n编码:%s\n,解码后为:%s\n", encode,decode);break;}}while(select != 0);system("pause");return 1;}


原创粉丝点击