In 1953, David A. Huffman published his paper "A Method for the Construction of Minimum-Redundancy Codes", and hence printed his name in the history of computer science. As a professor who gives the final exam problem on Huffman codes, I am encountering a big problem: the Huffman codes are NOT unique. For example, given a string "aaaxuaxz", we can observe that the frequencies of the characters 'a', 'x', 'u' and 'z' are 4, 2, 1 and 1, respectively. We may either encode the symbols as {'a'=0, 'x'=10, 'u'=110, 'z'=111}, or in another way as {'a'=1, 'x'=01, 'u'=001, 'z'=000}, both compress the string into 14 bits. Another set of code can be given as {'a'=0, 'x'=11, 'u'=100, 'z'=101}, but {'a'=0, 'x'=01, 'u'=011, 'z'=001} is NOT correct since "aaaxuaxz" and "aazuaxax" can both be decoded from the code 00001011001001. The students are submitting all kinds of codes, and I need a computer program to help me determine which ones are correct and which ones are not.
Input Specification:
Each input file contains one test case. For each case, the first line gives an integer N (2≤N≤63), then followed by a line that contains all the N distinct characters and their frequencies in the following format:
c[1] f[1] c[2] f[2] ... c[N] f[N]
where c[i]
is a character chosen from {'0' - '9', 'a' - 'z', 'A' - 'Z', '_'}, and f[i]
is the frequency of c[i]
and is an integer no more than 1000. The next line gives a positive integer M (≤1000), then followed by M student submissions. Each student submission consists of N lines, each in the format:
c[i] code[i]
where c[i]
is the i
-th character and code[i]
is an non-empty string of no more than 63 '0's and '1's.
Output Specification:
For each test case, print in each line either "Yes" if the student's submission is correct, or "No" if not.
Note: The optimal solution is not necessarily generated by Huffman algorithm. Any prefix code with code length being optimal is considered correct.
Sample Input:
7
A 1 B 1 C 1 D 3 E 3 F 6 G 6
4
A 00000
B 00001
C 0001
D 001
E 01
F 10
G 11
A 01010
B 01011
C 0100
D 011
E 10
F 11
G 00
A 000
B 001
C 010
D 011
E 100
F 101
G 110
A 00000
B 00001
C 0001
D 001
E 00
F 10
G 11
Sample Output:
Yes Yes No No
我的答案
1 #include <stdio.h> 2 #include <stdlib.h> 3 #include <unistd.h> 4 #include <string.h> 5 6 #define MAXN 64 7 #define Yes 1 8 #define No 0 9 10 typedef struct TreeNode *HuffmanTree; 11 struct TreeNode { 12 int Weight; 13 HuffmanTree Left, Right; 14 }; 15 16 /* MinHeap function */ 17 #define MinData -1 18 typedef struct HeapStruct *MinHeap; 19 struct HeapStruct{ 20 HuffmanTree Data; 21 int Size; 22 int Capacity; 23 }; 24 25 #define QueueSize 100 26 struct QNode { 27 HuffmanTree Data[QueueSize]; 28 int rear; 29 int front; 30 }; 31 typedef struct QNode *Queue; 32 33 MinHeap CreateMinHeap(int MaxSize); 34 int MinHeapIsFull(MinHeap H); 35 void MinHeapInsert(MinHeap H, HuffmanTree item); 36 int IsEmpty(MinHeap H); 37 HuffmanTree DeleteMin(MinHeap H); 38 void PrecDown(MinHeap H, int p); 39 void BuildMinHeap(MinHeap H); 40 void PrintMinHeap(MinHeap H); 41 HuffmanTree Huffman(MinHeap H); 42 MinHeap ReadData(int num, char *ch, int *cf, MinHeap H); 43 44 void AddQ(Queue PtrQ, HuffmanTree item); 45 HuffmanTree DeleteQ(Queue PtrQ); 46 int IsEmptyQ(Queue PtrQ); 47 void LevelOrderTraversal(HuffmanTree HT); 48 49 MinHeap CreateMinHeap(int MaxSize) 50 { 51 MinHeap H = (MinHeap)malloc(sizeof(struct HeapStruct)); 52 H->Data = (HuffmanTree)malloc(sizeof(struct TreeNode)*(MaxSize+1)); 53 H->Size = 0; 54 H->Capacity = MaxSize; 55 H->Data[0].Weight = MinData; //哨兵 56 return H; 57 } 58 59 int MinHeapIsFull(MinHeap H) 60 { 61 return (H->Size == H->Capacity); 62 } 63 64 void MinHeapInsert(MinHeap H, HuffmanTree item) 65 { 66 int i; 67 if(MinHeapIsFull(H)) { 68 printf("Heap full"); 69 return; 70 } 71 i = ++H->Size; 72 for(;H->Data[i/2].Weight>item->Weight;i=i/2) { 73 H->Data[i].Weight = H->Data[i/2].Weight; 74 H->Data[i].Left = H->Data[i/2].Left; 75 H->Data[i].Right = H->Data[i/2].Right; 76 } 77 H->Data[i] = *item; 78 // free(item); 79 } 80 81 int IsEmpty(MinHeap H) 82 { 83 return (H->Size == 0); 84 } 85 86 HuffmanTree DeleteMin(MinHeap H) 87 { 88 int Parent, Child; 89 HuffmanTree MinItem, temp; 90 91 MinItem = (HuffmanTree)malloc(sizeof(struct TreeNode)); 92 temp = (HuffmanTree)malloc(sizeof(struct TreeNode)); 93 94 if(IsEmpty(H)) { 95 printf("MinHeap Empty"); 96 return NULL; 97 } 98 99 *MinItem = H->Data[1]; //保存最小的元素 100 *temp = H->Data[H->Size--]; //从最后一个元素插到顶点来比较 101 // printf("Size:%d ", H->Size); 102 for(Parent=1;Parent*2<=H->Size;Parent=Child) { //有没有左儿子 103 Child = Parent*2; //有的话比较左儿子 104 if((Child!=H->Size)&&(H->Data[Child].Weight>H->Data[Child+1].Weight)) //比较左右儿子那个小 105 Child++; 106 if(temp->Weight <= H->Data[Child].Weight) break; 107 else { 108 H->Data[Parent].Weight = H->Data[Child].Weight; 109 H->Data[Parent].Left = H->Data[Child].Left; 110 H->Data[Parent].Right = H->Data[Child].Right; 111 } 112 } 113 H->Data[Parent] = *temp; 114 // free(temp); 115 return MinItem; 116 } 117 118 void PrecDown(MinHeap H, int p) 119 { 120 int Parent, Child; 121 HuffmanTree temp; 122 123 temp = (HuffmanTree)malloc(sizeof(struct TreeNode)); 124 125 *temp = H->Data[p]; /* 取出根结点存放的值 */ 126 for(Parent=p;Parent*2<=H->Size;Parent=Child) { //有没有左儿子 127 Child = Parent*2; //有的话比较左儿子 128 if((Child!=H->Size)&&(H->Data[Child].Weight>H->Data[Child+1].Weight)) //比较左右儿子那个小 129 Child++; 130 if(temp->Weight <= H->Data[Child].Weight) break; 131 else 132 H->Data[Parent].Weight = H->Data[Child].Weight; 133 } 134 H->Data[Parent] = *temp; 135 } 136 137 void BuildMinHeap(MinHeap H) 138 { 139 int i; 140 /* 从最后一个结点的父结点开始,到根结点1 */ 141 for(i=H->Size/2;i>0;i--) 142 PrecDown(H, i); 143 } 144 145 void PrintMinHeap(MinHeap H) 146 { 147 int i; 148 // printf("MinHeap: "); 149 for(i=1;i<=H->Size;i++) { 150 printf(" %d", H->Data[i].Weight); 151 } 152 printf(" "); 153 } 154 155 HuffmanTree Huffman(MinHeap H) 156 { 157 /* 假设H->Size个权值已经存在H->Elements[]->Weight里 */ 158 int i; 159 HuffmanTree T; 160 BuildMinHeap(H); /* 将H->Elemnts[]按权值调整为最小堆 */ 161 // PrintMinHeap(H); 162 for(i=1;i<H->Size;) { 163 T = (HuffmanTree)malloc(sizeof(struct TreeNode)); /* 建立新结点 */ 164 T->Left = DeleteMin(H); /* 从最小堆中删除一个结点,作为新T的左子结点 */ 165 T->Right = DeleteMin(H); /* 从最小堆中删除一个结点,作为新T的右子结点 */ 166 T->Weight = T->Left->Weight+T->Right->Weight; /* 计算新权值 */ 167 MinHeapInsert(H, T); 168 // PrintMinHeap(H); 169 // printf("Huffman:"); 170 // LevelOrderTraversal(T); 171 // printf(" "); 172 } 173 T = DeleteMin(H); 174 return T; 175 } 176 177 void PrintHuffman(HuffmanTree HT) 178 { 179 if(HT) { 180 PrintHuffman(HT->Left); 181 PrintHuffman(HT->Right); 182 printf("%d ", HT->Weight); 183 } 184 } 185 186 MinHeap ReadData(int num, char *ch, int *cf, MinHeap H) 187 { 188 int i; 189 for(i=0;i<num;i++) { 190 if(i==num-1) 191 scanf("%c %d", &ch[i], &cf[i]); 192 else 193 scanf("%c %d ", &ch[i], &cf[i]); 194 HuffmanTree T = (HuffmanTree)malloc(sizeof(struct TreeNode)); 195 T->Weight = cf[i]; 196 MinHeapInsert(H, T); 197 } 198 return H; 199 } 200 201 int WPL(HuffmanTree T, int Depth) 202 { 203 // printf("T->Weight = %d, T->Left = %p, T->Right =%p ", 204 // T->Weight, T->Left, T->Right); 205 int rw=0, lw=0; 206 if(!T->Left && !T->Right) 207 return (Depth*(T->Weight)); 208 else { 209 if(T->Left) lw = WPL(T->Left, Depth+1); 210 if(T->Right) rw = WPL(T->Right, Depth+1); 211 return lw+rw; 212 } 213 } 214 215 HuffmanTree CreateHuffmanTree() 216 { 217 HuffmanTree T = (HuffmanTree)malloc(sizeof(struct TreeNode)); 218 T->Weight = 0; 219 T->Left = T->Right = NULL; 220 return T; 221 } 222 223 void DeleteHuffmanTree(HuffmanTree T) 224 { 225 if(T) { 226 DeleteHuffmanTree(T->Left); 227 DeleteHuffmanTree(T->Right); 228 free(T); 229 } 230 } 231 232 int Judge(int N, int CodeLen, char *ch, int *cf) 233 { 234 char s1[MAXN], s2[MAXN]; 235 int i, j, weight, flag = Yes; 236 HuffmanTree T = CreateHuffmanTree(); 237 HuffmanTree pt = NULL; 238 for(i=0;i<N;i++) { 239 scanf("%s %s ", s1, s2); 240 if(strlen(s2) > N) { flag = No; break; } 241 for(j=0;s1[0]!=ch[j];j++) 242 if(j==N) { flag = No; break; } 243 weight = cf[j]; 244 pt = T; 245 for(j=0;j<strlen(s2);j++) { 246 if(s2[j] == '0') { //开始创建树 247 if(!pt->Left) pt->Left = CreateHuffmanTree(); //没有就创建 248 else if(pt->Left->Weight != 0) { 249 // printf("Exit from pt->Left->Weight == 1 "); 250 flag = No; //是否路过叶子 251 } 252 pt = pt->Left; 253 } else if(s2[j] == '1') { 254 if(!pt->Right) pt->Right = CreateHuffmanTree(); 255 else if(pt->Right->Weight != 0) { 256 // printf("Exit from pt->Right->Weight == 1 "); 257 flag = No; 258 } 259 pt = pt->Right; 260 } else { //应该不会发生 261 // printf("Exit from not happen "); 262 flag = No; 263 } 264 } 265 pt->Weight = weight; //叶子标记 266 weight = 0; //清空weight 267 if(pt->Left || pt->Right) { 268 // printf("Exit from pt->Left || pt->Right "); 269 flag = No; //不是叶子也错 270 } 271 } 272 if(flag != No && CodeLen == WPL(T, 0)) { 273 return Yes; 274 } else { 275 // printf("Exit from CodeLen != WPL(T, 0) %d ", WPL(T, 0)); 276 if(T) DeleteHuffmanTree(T); 277 return No; 278 } 279 } 280 281 int main() 282 { 283 int N, CodeLen, n, i; //huffman的叶子结点个数,WPL最优值 284 MinHeap H; //最小堆 285 char *ch; //输入的字符组 286 int *cf; 287 HuffmanTree T; //HuffmanTree 288 scanf("%d ", &N); 289 H = CreateMinHeap(N); 290 ch = (char *)malloc(sizeof(char)*N); 291 cf = (int *)malloc(sizeof(int)*N); 292 H = ReadData(N, ch, cf, H); 293 T = Huffman(H); 294 CodeLen = WPL(T, 0); 295 scanf("%d ", &n); 296 for(i=0;i<n;i++) { 297 if(Judge(N, CodeLen, ch, cf)) 298 printf("Yes "); 299 else 300 printf("No "); 301 } 302 return 0; 303 }