码迷,mamicode.com
首页 > 编程语言 > 详细

一步两步学算法之哈夫曼编码(最优二叉树)

时间:2015-04-29 00:18:26      阅读:235      评论:0      收藏:0      [点我收藏+]

标签:

比较难理解的 都打了备注了

  1 #include "stdio.h"
  2 #include "stdlib.h"
  3 #include "string.h"
  4 char alphabet[]={A,B,C,D};
  5 typedef struct 
  6 {
  7     int weight;        //权值 
  8     int parent;        //父节点序号 
  9     int left ;
 10     int right;
 11 }HuffmanTree;
 12 
 13 typedef char *HuffmanCode;  //Huffman编码指针 
 14 void SelectNode (HuffmanTree *ht,int n,int *bt1,int *bt2)
 15 //从n个节点中选择parent节点为0,权重最小的两个节点 
 16 {
 17     int i;
 18     HuffmanTree *ht1,*ht2,*t;
 19     ht1=ht2=NULL;
 20     for(i=1;i<=n;i++)
 21     {
 22         if(!ht[i].parent)                //父节点为空 
 23         {
 24             if(ht1==NULL)    
 25             {
 26                 ht1=ht+i;                // 
 27                 continue;
 28             }
 29             if(ht2==NULL)
 30             {
 31                 ht2=ht+i;
 32                 if(ht1->weight>ht2->weight)
 33                 {
 34                     t=ht2;
 35                     ht2=ht1;
 36                     ht1=t;            //让ht1指向最小节点 ht2指向第二小 
 37                 }
 38                 continue;
 39             }
 40             if(ht1 &&ht2)
 41             {
 42                 if(ht[i].weight<=ht1->weight)
 43                 {
 44                     ht2=ht1;                    //如果还有比ht1更小的则把ht1赋给ht2 ,ht1继续等于最小 
 45                     ht1=ht+i;
 46                 }
 47                 else if(ht[i].weight<ht2->weight){
 48                     ht2=ht+i;                        //没有比ht1更小的 但有比ht2小的 
 49                 }
 50             }
 51         }
 52     } 
 53     if(ht1>ht2){                    //按数组最初的位置排序 
 54         *bt2=ht1-ht;
 55         *bt1=ht2-ht;
 56     }
 57     else
 58     {
 59         *bt1=ht1-ht;
 60         *bt2=ht2-ht;
 61     }
 62 }
 63 void CreateTree(HuffmanTree *ht,int n,int *w)
 64 {
 65     int i,m=2*n-1;    //总节点数 
 66     int bt1,bt2;
 67     if(n<=1)
 68         return ;
 69     for(i=1;i<=n;++i)
 70     {
 71         ht[i].weight=w[i-1];
 72         ht[i].parent=0;
 73         ht[i].left=0;
 74         ht[i].right=0;
 75     } 
 76     for(;i<=m;++i)
 77     {
 78         ht[i].weight=0;
 79         ht[i].parent=0;
 80         ht[i].left=0;
 81         ht[i].right=0;
 82     }
 83     for(i=n+1;i<=m;++i)
 84     {
 85         SelectNode(ht,i-1,&bt1,&bt2);
 86         ht[bt1].parent=i;
 87         ht[bt2].parent=i;
 88         ht[i].left=bt1;
 89         ht[i].right=bt2;
 90         ht[i].weight=ht[bt1].weight+ht[bt2].weight;  
 91     }
 92 }
 93 
 94 
 95 void HuffmanCoding(HuffmanTree *ht,int n,HuffmanCode *hc)
 96 {
 97     char *cd;
 98     int start,i;
 99     int current,parent;
100     cd=(char*)malloc(sizeof(char)*n);
101     cd[n-1]=\0;
102     for(i=1;i<=n;i++)
103     {
104         start=n-1;                        
105         current=i;                            //获得当前节点序号 
106         parent=ht[current].parent;            //获得当前节点父亲的序号 
107         while(parent)            //当父节点不为空 
108         {
109             if(current==ht[parent].left)    //若当前节点是父亲的左节点 
110                 cd[--start]=0;            //字符最后编码为0 注意这个编码是逆序的 最后其实根节点 
111             else
112                 cd[--start]=1;
113             current=parent;                    //从当前节点向根节点寻找 
114             parent=ht[parent].parent;
115         }
116         hc[i-1]=(char*)malloc(sizeof(char)*(n-start));    //分配保存编码的内存 
117         strcpy(hc[i-1],&cd[start]);                        //复制生成的编码 
118     }
119     free(cd);
120 } 
121 
122 void Encode(HuffmanCode *hc,char *alphabet,char *str,char *code)
123 {
124     int len=0,i=0,j;
125     code[0]=\0;
126     while(str[i])
127     {
128         j=0;
129         while(alphabet[j]!=str[i])   //搜索字母在编码表的位置 
130             j++;
131         strcpy(code+len,hc[j]);        //字母在叶节点的编号到根节点的编号全部复制给code 
132         len=len+strlen(hc[j]);        // 扩大len的长度(也就是节点深度) 
133         i++;                    
134     }
135     code[len]=\0;
136 }
137 
138 void Decode(HuffmanTree *ht,int m,char *code,char *alphabet,char *decode)//解码 
139 {
140     int    position=0,i,j=0;
141     m=2*m-1;
142     while(code[position])
143     {
144         for(i=m;ht[i].left &&ht[i].right;position++ )    
145         {    
146             if(code[position]==0)                
147                 i=ht[i].left;                
148             else
149                 i=ht[i].right;
150         }
151         decode[j]=alphabet[i-1];
152         j++;
153     }    
154     decode[j]=\0;
155 }
156 int main()
157 {
158     int i,n=4,m;
159     char test[]="DBDBDABDCDADBDADBDADACDBDBD";
160     char code[100],code1[100];
161     
162     int w[]={5,7,2,13};
163     HuffmanTree *ht;
164     HuffmanCode *hc;
165     m=2*n-1;
166     ht=(HuffmanTree *)malloc((m+1)*sizeof(HuffmanTree));
167     if(!ht)
168     {
169         printf("分配内存失败\n");
170         exit(0);
171     }
172     CreateTree(ht,n,w);
173     HuffmanCoding(ht,n,hc);
174     for(i=1;i<=n;i++)
175         printf("字母:%c,权重:%d,编码:%s\n",alphabet[i-1],ht[i].weight,hc[i-1]);
176     Encode(hc,alphabet,test,code);
177     printf("\n字符串:\n%s\n转换后:\n%s\n",test,code);
178     Decode(ht,n,code,alphabet,code1);
179     printf("\n编码:\n%s\n转换后:\n%s\n",code,code1);
180 
181     return 0;
182 } 

 

一步两步学算法之哈夫曼编码(最优二叉树)

标签:

原文地址:http://www.cnblogs.com/threezj/p/4464210.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!