哈弗曼树

来源:互联网 发布:交通事故数据统计 编辑:程序博客网 时间:2024/06/07 14:17

哈弗曼树原理暂时不叙述(实为贪心算法)。先奉上自己写的源代码。

/*  huffman tree */#include<stdio.h>#include<string.h>#include<stdlib.h>#define N 100typedef struct _arrTree{int weight;int parent;int lchild;int rchild;}arrayTree,*pArrayTree;typedef struct _tree{int data;int visit;char code[256];struct _tree *left;struct _tree * right;}tree,*pTree;void initArray(pArrayTree at,int* len){int i=0;scanf("%d",len);while(scanf("%d",&((at+i)->weight)),++i<*len);}void arrayCreate(pArrayTree at,int len){int min1,min2,j,k=len;if(len<2){printf("the tree is so small!\n");return;}for(;k<2*len-1;++k){min1=0;while(at[min1].parent){++min1;}min2=min1+1;while(at[min2].parent){++min2;}for(j=0;j<k;++j){if(at[j].parent||j==min1||j==min2){continue;}if(at[min1].weight>at[min2].weight){int t=min1;min1=min2;min2=t;}if(at[j].weight<at[min1].weight){min2=min1;min1=j;}else if(at[j].weight<at[min2].weight){min2=j;}}at[k].weight=at[min1].weight+at[min2].weight;at[k].lchild=min1;at[k].rchild=min2;at[min1].parent=k;at[min2].parent=k;}}void show(pArrayTree at,int len){int i=0;printf("index weight parent lchild rchild\n");for(;i<2*len-1;++i){printf("%-7d%-7d%-7d%-7d%-7d\n",i,at[i].weight,at[i].parent,at[i].lchild,at[i].rchild);if(i==len-1){printf("---------------------------------------\n");}}}pTree createTree(pTree root,pArrayTree at,int len){int i=2*len-2;root=(pTree)malloc(sizeof(tree)*(2*len-1));while(i>=0){root[i].data=at[i].weight;if(at[i].lchild){root[i].left=root+at[i].lchild;root[i].right=root+at[i].rchild;}else{root[i].left=NULL;root[i].right=NULL;}--i;}return root+2*len-2;}void traverse(pTree root,char* str){ //遍历并建立码表。if(root){ char st[256]="";printf("%-5d ",root->data);strcpy(root->code,str);printf("%s\n",root->code);strcpy(st,root->code);traverse(root->left,strcat(st,"0"));//关键st[strlen(st)-1]='1';st[strlen(st)]=0;traverse(root->right,st);//关键}}/*  show the code */void showCode(pTree root){if(root){if(!root->left&&!root->right){printf("%-5d %s\n",root->data,root->code);}showCode(root->left);showCode(root->right);}}void initCodes(char (*codes)[256],int len,pTree root){int i=0;for(;i<len;++i){strcpy(codes[i],(root-2*len+2+i)->code);}}void showInitCode(char (*codes)[256],int len){int i=0;for(;i<len;++i){printf("      %s\n",codes[i]);}}void decode(char (*codes)[256],int len,const char* str){char* ps=str;char res[1024]="";int num[N]={0},i;for(i=0;i<len;++i){num[i]=strlen(codes[i]+1);}while(*ps){ //暂时是暴力解码,待日后想出一个更优秀的算法for(i=0;i<len;++i){char ss[256]="";strncpy(ss,ps,num[i]);if(!strcmp(ss,codes[i]+1)){printf("%d",i);//此处用于调试输出。// strcat(res,itoa(i,ss,10));sprintf(ss,"%d",i);strcat(res,ss);ps+=num[i];break;}}}printf("\n%s\n",res);}int main(){int len;char codes[N][256];char source[1024];pTree root;arrayTree at[2*N-1]={{0,0,0,0}};initArray(at,&len);arrayCreate(at,len);show(at,len);printf("\n");root=createTree(root,at,len);traverse(root,"#");printf("\n");showCode(root);initCodes(codes,len,root);showInitCode(codes,len);getchar();gets(source);decode(codes,len,source);//执行解码操作return 0;}



测试数据

8
5 29 7 8 14 23 3 11
00000001001011011011101111


结果输出

100   #
42    #0
19    #00
8     #000
3     #0000
5     #0001
11    #001
23    #01
58    #1
29    #10
29    #11
14    #110
15    #111
7     #1110
8     #1111


3     #0000
5     #0001
11    #001
23    #01
29    #10
14    #110
7     #1110
8     #1111
      #0001
      #10
      #1110
      #1111
      #110
      #01
      #0000
      #001
65611757557557555755555
65611757557557555755555

0 0