哈夫曼编译码器

  1 //eg:
  2 //    4        A B C D        9 5 2 4
  3 //    A: 0    B: 10    C: 110    D: 111
  4 //  ABCDCBA    010110111110100
  5 #include<stdio.h>
  6 #include<stdlib.h>
  7 #include<string.h>
  8 #include<conio.h>
  9 #define OK 1
 10 #define ERROR 0
 11 typedef struct HTNode{
 12     char ch;
 13     int weight;
 14     int parent, lchild, rchild;
 15 } HTNode;
 16 typedef struct HTNode* HuffmanTree;
 17 typedef char** HuffmanCode;
 18 //定义全局变量
 19 HuffmanTree HT;
 20 HuffmanCode HC;
 21 int n;
 22 //选择两个最小结点
 23 void select(int k, int *s1, int *s2){
 24     int i, ti, t=1000;
 25     for(i = 1; i <= k; i++){
 26         if(!HT[i].parent){ 
 27             if(t > HT[i].weight){
 28                 t = HT[i].weight;//t最后为最小的weight
 29                 ti = i;
 30             }
 31         }
 32     }
 33     *s1 = ti;
 34     t = 1000;
 35     ti = 0;
 36     for(i = 1; i <= k; i++){
 37         if((!HT[i].parent) && i!=*s1){ //parent为0
 38             if(t > HT[i].weight){
 39                 t = HT[i].weight;
 40                 ti = i;
 41             }
 42         }
 43     }
 44     *s2 = ti;
 45 }
 46 //打印哈夫曼树
 47 void printHT(int m){
 48     int i;
 49     printf("\n");
 50     printf("char  weight  parent  lchild  rchild\n");
 51     for(i = 1; i <= m; i++){
 52         printf("  %c  %5d  %5d  %5d  %5d\n", HT[i].ch, HT[i].weight, HT[i].parent, HT[i].lchild, HT[i].rchild);
 53     }
 54     printf("\n");
 55 }
 56 //初始化(建树和编码表)
 57 int Init(){
 58     int m = 2*n-1;
 59     int i, s1, s2;
 60     int w[n+1];//weight 0下标不使用
 61     char ch[n+1];//字符 
 62     char title;
 63     char* cd;
 64     int start, c, f;
 65     //建立哈夫曼树
 66     while(title = getchar() != '\n');
 67     printf("■请输入各字符(用空格分开):");
 68     for(i=1; i<=n; i++){
 69         scanf("%c", &ch[i]);
 70         getchar();
 71     }
 72     printf("■请输入各权值(用空格分开):");
 73     for(i=1; i<=n; i++)
 74         scanf("%d", &w[i]);
 75     HT = (HuffmanTree)malloc((m+1)*sizeof(HTNode));//0号节点不使用
 76     for(i=1; i<=n; i++){
 77         HT[i].ch = ch[i];
 78         HT[i].weight = w[i];
 79         HT[i].lchild = 0;
 80         HT[i].rchild = 0;
 81         HT[i].parent = 0;
 82     }
 83     for(; i<=m; i++){
 84         HT[i].ch='-';
 85         HT[i].weight=0;
 86         HT[i].lchild=0;
 87         HT[i].rchild=0;
 88         HT[i].parent=0;
 89     }
 90     for(i=n+1; i<=m; i++){
 91         select(i-1, &s1, &s2);
 92         HT[s1].parent=i;
 93         HT[s2].parent=i;
 94         HT[i].lchild=s1;
 95         HT[i].rchild=s2;
 96         HT[i].weight=HT[s1].weight+HT[s2].weight;
 97     }
 98     printf("\n■生成的哈夫曼树为:");
 99     printHT(m);
100     //从叶子到根逆向求每个字符的哈夫曼编码 
101     HC = (HuffmanCode)malloc((n+1)*sizeof(char*));//分配n个字符编码的头指针向量 
102     cd = (char*)malloc(n*sizeof(char));//分配求编码的工作空间 
103     cd[n-1]='\0';//编码结束符 
104     printf("■其编码表为:\n");
105     for(i=1; i<=n; i++){//逐个字符求哈夫曼编码 
106         start = n-1;//编码结束符位置 
107         for(c = i, f = HT[i].parent; f != 0; c = f, f = HT[f].parent){
108             if(HT[f].lchild==c)
109                 cd[--start]='0';
110             else
111                 cd[--start]='1';
112         }
113         HC[i] = (char*)malloc((n-start)*sizeof(char));//为第i个字符编码分配空间 
114         strcpy(HC[i], &cd[start]);//从cd复制编码到HC 
115         printf("%c: ", HT[i].ch);
116         puts(HC[i]);
117     }
118     free(cd);
119     return OK;
120 }
121 //编码
122 int Encoding(){
123     char s[20], title;
124     int i, j;
125     while(title = getchar() != '\n');
126     printf("\n■请输入字符串:\n");
127     scanf("%s", s);
128     printf("■编码结果为:\n");
129     for(i=0; s[i]!='\0'; i++){
130         for(j=1; j<=n; j++){
131             if(s[i]==HT[j].ch){
132                 printf("%s", HC[j]);
133                 continue;
134             }
135         }
136     }
137     printf("\n");
138     return OK;
139 }
140 //译码
141 int Decoding(){
142     char s[20], title;
143     int i=0, p=2*n-1;//p在根节点位置;
144     while(title = getchar() != '\n');
145     printf("\n■请输入编码:\n");
146     scanf("%s", s);
147     printf("■译码结果为:\n");
148     for(i = 0; s[i] != '\0'; i++){
149         if(s[i]=='0')
150             p=HT[p].lchild;
151         if(s[i]=='1')
152             p=HT[p].rchild;
153         if(p<=n){
154             printf("%c", HT[p].ch);
155             p=2*n-1;
156         }
157     }
158     printf("\n");
159     return OK;
160 }
161 //菜单
162 void menu(){
163         printf("■■■■■哈夫曼编译码器■■■■■\n");
164         printf("■\t ★1-建立哈夫曼树\t■\n");
165         printf("■\t ★2-编码\t\t■\n");
166         printf("■\t ★3-译码\t\t■\n");
167         printf("■\t ★4-退出\t\t■\n");
168         printf("■■■■■■■■■■■■■■■■■\n");
169         printf("■请选择:");
170 }
171 int main(){
172     char ch, title;
173     while(1){
174         menu();
175         scanf("%c", &ch);
176         switch(ch){
177         case '1':
178             printf("\n■请输入字符数n(n>0):");
179             scanf("%d", &n);
180             Init();
181             break;
182         case '2':
183             Encoding();
184             break;
185         case '3':
186             Decoding();
187             break;
188         case '4':
189             printf("Finished, God bless you!"); 
190             exit(0);
191         }
192         printf("\n");
193         while(title = getchar() != '\n');
194     }
195     return 0;
196 }

 

posted @ 2018-11-22 13:17  cruelty_angel  阅读(1621)  评论(0编辑  收藏  举报