码迷,mamicode.com
首页 > 其他好文 > 详细

3.1 层次关系结构:树(3)

时间:2016-07-19 09:26:04      阅读:260      评论:0      收藏:0      [点我收藏+]

标签:

3-5 HuffmanTree.c

  1 #include <stdlib.h>
  2 #include <stdio.h>
  3 #include <string.h>
  4 typedef struct
  5 {
  6     int weight; //权值 
  7     int parent; //父结点序号 
  8     int left; //左子树序号
  9     int right; //右子树序号 
 10 }HuffmanTree;
 11 typedef char *HuffmanCode;  //Huffman编码 
 12 void SelectNode(HuffmanTree *ht,int n,int *bt1,int *bt2)
 13 //从1~x个结点选择parent结点为0,权重最小的两个结点 
 14 {
 15      int i;
 16      HuffmanTree *ht1,*ht2,*t;
 17      ht1=ht2=NULL; //初始化两个结点为空 
 18      for(i=1;i<=n;++i) //循环处理1~n个结点(包括叶结点和非叶结点) 
 19      {
 20          if(!ht[i].parent) //父结点为空(结点的parent=0) 
 21          {
 22              if(ht1==NULL) //结点指针1为空 
 23              {
 24                  ht1=ht+i; //指向第i个结点 
 25                  continue; //继续循环 
 26              }
 27              if(ht2==NULL) //结点指针2为空 
 28              {
 29                  ht2=ht+i; //指向第i个结点 
 30                  if(ht1->weight>ht2->weight) //比较两个结点的权重,使ht1指向的结点权重小 
 31                  {
 32                      t=ht2;
 33                      ht2=ht1;
 34                      ht1=t;
 35                  }
 36                  continue; //继续循环 
 37              }
 38              if(ht1 && ht2) //若ht1、ht2两个指针都有效 
 39              {
 40                  if(ht[i].weight<=ht1->weight) //第i个结点权重小于ht1指向的结点 
 41                  {
 42                      ht2=ht1; //ht2保存ht1,因为这时ht1指向的结点成为第2小的 
 43                      ht1=ht+i; //ht1指向第i个结点 
 44                  }else if(ht[i].weight<ht2->weight){ //若第i个结点权重小于ht2指向的结点 
 45                      ht2=ht+i; //ht2指向第i个结点 
 46                  }
 47              }
 48          }
 49      }
 50      if(ht1>ht2){ //增加比较,使二叉树左侧为叶结点 
 51          *bt2=ht1-ht;
 52          *bt1=ht2-ht;
 53      }else{
 54          *bt1=ht1-ht;
 55          *bt2=ht2-ht;
 56      }
 57 }
 58 
 59 void CreateTree(HuffmanTree *ht,int n,int *w)
 60 {
 61     int i,m=2*n-1;//总的节点数
 62     int bt1,bt2; //二叉树结点序与 
 63     if(n<=1) return ; //只有一个结点,无法创建 
 64     for(i=1;i<=n;++i) //初始化叶结点 
 65     {
 66         ht[i].weight=w[i-1];
 67         ht[i].parent=0;
 68         ht[i].left=0;
 69         ht[i].right=0;
 70     }
 71     for(;i<=m;++i)//初始化后续结点 
 72     {
 73         ht[i].weight=0;
 74         ht[i].parent=0;
 75         ht[i].left=0;
 76         ht[i].right=0;
 77     }
 78     for(i=n+1;i<=m;++i) //逐个计算非叶结点,创建Huffman树 
 79     {
 80         SelectNode(ht,i-1,&bt1,&bt2); //从1~i-1个结点选择parent结点为0,权重最小的两个结点 
 81         ht[bt1].parent=i;
 82         ht[bt2].parent=i;
 83         ht[i].left=bt1;
 84         ht[i].right=bt2;
 85         ht[i].weight=ht[bt1].weight+ht[bt2].weight;
 86     }
 87 }
 88 void HuffmanCoding(HuffmanTree *ht,int n,HuffmanCode *hc)//,char *letters)
 89 {
 90      char *cd;
 91      int start,i;
 92      int current,parent;    
 93      cd=(char*)malloc(sizeof(char)*n);//用来临时存放一个字符的编码结果  
 94      cd[n-1]=\0; //设置字符串结束标志 
 95      for(i=1;i<=n;i++)
 96      {
 97          start=n-1;
 98          current=i;
 99          parent=ht[current].parent;//获取当前结点的父结点 
100          while(parent) //父结点不为空 
101          {
102              if(current==ht[parent].left)//若该结点是父结点的左子树  
103                cd[--start]=0; //编码为0 
104              else //若结点是父结点的右子树 
105                cd[--start]=1; //编码为1 
106              current=parent; //设置当前结点指向父结点 
107              parent=ht[parent].parent; //获取当前结点的父结点序号    
108          }
109          hc[i-1]=(char*)malloc(sizeof(char)*(n-start));//分配保存编码的内存 
110          strcpy(hc[i-1],&cd[start]); //复制生成的编码           
111      }
112      free(cd); //释放编码占用的内存 
113 }
114 
115 void Encode(HuffmanCode *hc,char *alphabet,char *str,char *code)
116 //将一个字符串转换为Huffman编码
117 //hc为Huffman编码表 ,alphabet为对应的字母表,str为需要转换的字符串,code返回转换的结果 
118 {
119      
120      int len=0,i=0,j;
121      code[0]=\0;
122      while(str[i])
123      {
124          j=0;
125          while(alphabet[j]!=str[i])
126              j++;         
127          strcpy(code+len,hc[j]); //将对应字母的Huffman编码复制到code指定位置 
128          len=len+strlen(hc[j]); //累加字符串长度 
129          i++;
130      }
131      code[len]=\0;
132 }
133 
134 void Decode(HuffmanTree *ht,int m,char *code,char *alphabet,char *decode)
135 //将一个Huffman编码组成的字符串转换为明文字符串 
136 //ht为Huffman二叉树,m为字符数量,alphabet为对应的字母表,str为需要转换的字符串,decode返回转换的结果 
137 {
138      int position=0,i,j=0;
139      m=2*m-1;
140      while(code[position]) //字符串未结束 
141      {
142           for(i=m;ht[i].left && ht[i].right; position++) //在Huffman树中查找左右子树为空 ,以构造一个Huffman编码 
143           {
144               if(code[position]==0) //编码位为0 
145                   i=ht[i].left; //处理左子树 
146               else //编译位为 1 
147                   i=ht[i].right; //处理右子树 
148           }
149           decode[j]=alphabet[i-1]; //得到一个字母
150           j++;//处理下一字符 
151      }  
152      decode[j]=\0; //字符串结尾 
153 }
154 int main()
155 {
156     int i,n=4,m; 
157     char test[]="DBDBDABDCDADBDADBDADACDBDBD";
158     char code[100],code1[100];
159     char alphabet[]={A,B,C,D}; //4个字符
160     int w[]={5,7,2,13} ;//4个字符的权重 
161     HuffmanTree *ht;
162     HuffmanCode *hc;    
163     m=2*n-1;    
164     ht=(HuffmanTree *)malloc((m+1)*sizeof(HuffmanTree)); //申请内存,保存赫夫曼树 
165     if(!ht)
166     {
167         printf("内存分配失败!\n");
168         exit(0);    
169     }
170     hc=(HuffmanCode *)malloc(n*sizeof(char*));
171     if(!hc)
172     {
173         printf("内存分配失败!\n");
174         exit(0);    
175     }
176     
177     CreateTree(ht,n,w); //创建赫夫曼树 
178     HuffmanCoding(ht,n,hc); //根据赫夫曼树生成赫夫曼编码 
179     for(i=1;i<=n;i++) //循环输出赫夫曼编码 
180         printf("字母:%c,权重:%d,编码为 %s\n",alphabet[i-1],ht[i].weight,hc[i-1]);
181     
182     Encode(hc,alphabet,test,code); //根据赫夫曼编码生成编码字符串 
183     printf("\n字符串:\n%s\n转换后为:\n%s\n",test,code); 
184     
185     Decode(ht,n,code,alphabet,code1); //根据编码字符串生成解码后的字符串 
186     printf("\n编码:\n%s\n转换后为:\n%s\n",code,code1); 
187     getch();
188     return 0;
189 }

 

3.1 层次关系结构:树(3)

标签:

原文地址:http://www.cnblogs.com/wozixiaoyao/p/5683130.html

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