1. 程式人生 > >C語言做哈夫曼編譯碼器

C語言做哈夫曼編譯碼器

  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 }