zoukankan      html  css  js  c++  java
  • 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
    ", 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 }
    无欲速,无见小利。欲速,则不达;见小利,则大事不成。
  • 相关阅读:
    JavaScript Window
    3.1.3 背景音乐播放技术
    6.1 多媒体相关基本概念及计算问题
    11.5 知识产权考点讲解
    第15课 TortoiseGit程序操作介绍
    第16课 “远程 Git文档库” 的基础操作
    第11课 Git GUI程序的基本功能
    第12课 使用Git GUI
    第13课 SmartGit程序操作介绍
    第14课 SourceTree程序操作介绍
  • 原文地址:https://www.cnblogs.com/ch122633/p/8962009.html
Copyright © 2011-2022 走看看