05-树9 Huffman Codes(30 分)

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 (2N63), 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\n", 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("\n");
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("\n");
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\n", 
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\n", 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\n");
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\n");
257                     flag = No;
258                 }
259                 pt = pt->Right;
260             } else {                                //应该不会发生
261                 // printf("Exit from not happen\n");
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\n");
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\n", 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", &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", &n);
296     for(i=0;i<n;i++) {
297         if(Judge(N, CodeLen, ch, cf))
298             printf("Yes\n");
299         else
300             printf("No\n");
301     }
302     return 0;
303 }

 

转载于:https://www.cnblogs.com/ch122633/p/8962009.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值