• 05-树9 Huffman Codes


    哈夫曼树

    Yes 需满足两个条件:1.HuffmanTree 结构不同,但WPL一定。子串WPL需一致

              2.判断是否为前缀码

      开始判断用的strstr函数,但其传值应为char *,不能用在string类型。所以后来改用substr。

    substr(start,length);start为子串起始位置,length为从起始位置的长度。

     1 #include <iostream>
     2 #include <string>
     3 using namespace std;
     4 
     5 int main()
     6 { 
     7     string str = "123456",endStr;   
     8     endStr = str.substr(0,3);   
     9     cout<< endStr <<endl;  
    10     return 0;
    11 }
    12 //output:123
    View Eg Code

      因为这里用了容器优先队列,且判断前缀码用了暴力求解,substr(start,length);函数。所以 要点:最大N&M,code长度等于63  超时了。

      自己写,会快。

    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 NNdistinct 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', '_'}, andf[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 MM student submissions. Each student submission consists of NN 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 <iostream>
     2 #include <cstdio>
     3 #include <string>
     4 #include <queue>
     5 #include <algorithm>
     6 using namespace std;
     7 
     8 struct HuffTreeNode
     9 {
    10     char c;
    11     int f;
    12 };
    13 struct HuffTreeNode HuffNode[65];
    14 
    15 struct strNod
    16 {
    17     char c;
    18     string code;
    19 };
    20 struct strNod strNode[65];
    21 
    22 bool compare(strNod a, strNod b)
    23 {
    24     return a.code.size() < b.code.size();/*长度从小到大排序 */
    25 }
    26 
    27 /*strstr(str1,str2) 函数用于判断字符串str2是否是str1的子串。
    28 如果是,则该函数返回str2在str1中首次出现的地址;否则,返回NULL。*/
    29 /*[Error] cannot convert 'std::string {aka std::basic_string<char>}' to 'const char*' for argument '1' to 'char* strstr(const char*, const char*)'*/
    30 /*是子串返回true ,否则false */
    31 bool isStrstr(int N)
    32 {
    33     sort(strNode, strNode+N, compare);
    34     for(int i = 0; i < N; i ++) {
    35         for(int j = i + 1; j < N; j++) {
    36             if( strNode[j].code.substr( 0, strNode[i].code.size() ) == strNode[i].code )
    37                 return true;
    38         }
    39     }
    40     return false;
    41 }
    42 
    43 int main()
    44 {
    45     int N;
    46     scanf("%d",&N);
    47     priority_queue<int, vector<int>, greater<int> > pq;
    48     for(int i = 0; i < N; i++) {
    49         getchar();        /*排除回车 空格的影响 */
    50         scanf("%c",&HuffNode[i].c);
    51         scanf("%d",&HuffNode[i].f);
    52         pq.push(HuffNode[i].f);
    53     }
    54     /*计算HuffmanTree WPL*/
    55     int WPL = 0;
    56     int smallA,smallB;
    57     while( !pq.empty() ) {
    58         smallA = pq.top(); pq.pop();    /*取出两个最小的 */
    59         if( !pq.empty() ) {
    60             smallB = pq.top(); pq.pop();
    61             smallA += smallB; 
    62             pq.push(smallA);    /*求和后push进优先队列 */
    63         }                
    64         WPL += smallA;
    65     }
    66     WPL -= smallA;    /*求出WPL */
    67 /*    printf("WPL = %d",WPL);*/
    68     int M;
    69     scanf("%d",&M);
    70     for(int i = 0; i < M; i++) {
    71         int checkWpl = 0;
    72         for(int j = 0; j < N; j++) {
    73             cin >> strNode[j].c >> strNode[j].code;
    74             checkWpl += strNode[j].code.size() * HuffNode[j].f; //计算wpl 
    75         }
    76 /*        printf("checkWpl = %d",checkWpl);*/
    77         if(checkWpl == WPL) {    /*WPL符合,判断是否是前缀 */
    78             if( isStrstr(N) )    /*有子串,不符合 */
    79                 printf("No
    ");
    80             else
    81                 printf("Yes
    ");
    82         }
    83         else
    84             printf("No
    "); 
    85     }
    86     return 0;
    87 } 

    事实证明,自己写最小堆,并不能达到要求。大头应该是字符串比较那里。

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstdlib>
      4 #include <algorithm>
      5 using namespace std;
      6 
      7 #define MINDATA 0  /* 该值应根据具体情况定义为小于堆中所有可能元素的值 */
      8 #define ERROR -1
      9 
     10 struct HNode {
     11     int *Data; /* 存储元素的数组 */
     12     int Size;          /* 堆中当前元素个数 */
     13     int Capacity;      /* 堆的最大容量 */
     14 };
     15 typedef struct HNode *MinHeap; /* 堆的类型定义 */
     16 
     17 struct TreeNode {
     18     char c;
     19     int f;
     20 };
     21 struct TreeNode HuffNode[65];
     22 
     23 struct strNod
     24 {
     25     char c;
     26     string code;
     27 };
     28 struct strNod strNode[65];
     29 MinHeap CreateHeap( int MaxSize );
     30 bool IsFull( MinHeap H );
     31 bool Insert( MinHeap H, int X );
     32 bool IsEmpty( MinHeap H );
     33 int DeleteMin( MinHeap H );
     34 
     35 bool compare(strNod a, strNod b)
     36 {
     37     return a.code.size() < b.code.size();/*长度从小到大排序 */
     38 }
     39 
     40 /*strstr(str1,str2) 函数用于判断字符串str2是否是str1的子串。
     41 如果是,则该函数返回str2在str1中首次出现的地址;否则,返回NULL。*/
     42 /*[Error] cannot convert 'std::string {aka std::basic_string<char>}' to 'const char*' for argument '1' to 'char* strstr(const char*, const char*)'*/
     43 /*是子串返回true ,否则false */
     44 bool isStrstr(int N)
     45 {
     46     sort(strNode, strNode+N, compare);
     47     for(int i = 0; i < N; i ++) {
     48         for(int j = i + 1; j < N; j++) {
     49             if( strNode[j].code.substr( 0, strNode[i].code.size() ) == strNode[i].code )
     50                 return true;
     51         }
     52     }
     53     return false;
     54 }
     55 
     56 int main()
     57 {
     58     int N;
     59     scanf("%d",&N);
     60     MinHeap Heap = CreateHeap(N);
     61     for(int i = 0; i < N; i++) {
     62         getchar();        /*排除回车 空格的影响 */
     63         scanf("%c",&HuffNode[i].c);
     64         scanf("%d",&HuffNode[i].f);
     65         Insert(Heap, HuffNode[i].f);
     66     }
     67     
     68     //计算WPL的值 
     69     int WPL = 0;
     70     int smallA, smallB;
     71     while( !IsEmpty(Heap) ) {
     72         smallA = DeleteMin(Heap);
     73         if( !IsEmpty(Heap) ) {
     74             smallB = DeleteMin(Heap);
     75             smallA += smallB;
     76             Insert( Heap, smallA);
     77         }
     78         WPL += smallA;    
     79     } 
     80     WPL -= smallA;    
     81 //    printf("WPL = %d
    ",WPL);
     82 
     83     int M;
     84     scanf("%d",&M);
     85     for(int i = 0; i < M; i++) {
     86         int checkWpl = 0;
     87         for(int j = 0; j < N; j++) {
     88             cin >> strNode[j].c >> strNode[j].code;
     89             checkWpl += strNode[j].code.size() * HuffNode[j].f; //计算wpl 
     90         }
     91 /*        printf("checkWpl = %d",checkWpl);*/
     92         if(checkWpl == WPL) {    /*WPL符合,判断是否是前缀 */
     93             if( isStrstr(N) )    /*有子串,不符合 */
     94                 printf("No
    ");
     95             else
     96                 printf("Yes
    ");
     97         }
     98         else
     99             printf("No
    "); 
    100     }
    101     return 0;    
    102 } 
    103 
    104 /* 创建容量为MaxSize的空的最小堆 */ 
    105 MinHeap CreateHeap( int MaxSize )
    106 { 
    107  
    108     MinHeap H = (MinHeap)malloc(sizeof(struct HNode));
    109     H->Data = (int*)malloc((MaxSize+1)*sizeof(int));
    110     H->Size = 0;
    111     H->Capacity = MaxSize;
    112     H->Data[0] = MINDATA; /* 定义"哨兵"为小于堆中所有可能元素的值*/
    113     return H;
    114 }
    115 
    116 bool IsFull( MinHeap H )
    117 {
    118     return (H->Size == H->Capacity);
    119 }
    120 
    121 /* 将元素X插入最小堆H,其中H->Data[0]已经定义为哨兵 */ 
    122 bool Insert( MinHeap H, int X )
    123 {
    124     if ( IsFull(H) ) { 
    125         printf("最小堆已满");
    126         return false;
    127     }
    128     int i = ++H->Size; /* i指向插入后堆中的最后一个元素的位置 */
    129     for ( ; H->Data[i/2] > X; i /= 2 )
    130         H->Data[i] = H->Data[i/2]; /* 上滤X */
    131     H->Data[i] = X; /* 将X插入 */
    132     return true;
    133 }
    134 
    135 bool IsEmpty( MinHeap H )
    136 {
    137     return (H->Size == 0);
    138 }
    139 
    140 /* 从最小堆H中取出键值为最小的元素,并删除一个结点 */ 
    141 int DeleteMin( MinHeap H )
    142 { 
    143     int Parent, Child;
    144     int MinItem, X;
    145  
    146     if ( IsEmpty(H) ) {
    147         printf("最小堆已为空");
    148         return ERROR;
    149     }
    150  
    151     MinItem = H->Data[1]; /* 取出根结点存放的最小值 */
    152     /* 用最小堆中最后一个元素从根结点开始向上过滤下层结点 */
    153     X = H->Data[H->Size--]; /* 注意当前堆的规模要减小 */
    154     for( Parent = 1; Parent * 2 <= H->Size; Parent = Child ) {
    155         Child = Parent * 2;
    156         if( (Child != H->Size) && (H->Data[Child] > H->Data[Child+1]) )
    157             Child++;  /* Child指向左右子结点的较小者 */
    158         if( X <= H->Data[Child] ) break; /* 找到了合适位置 */
    159         else  /* 下滤X */
    160             H->Data[Parent] = H->Data[Child];
    161     }
    162     H->Data[Parent] = X;
    163  
    164     return MinItem;
    165 } 
    View Code

     剪枝、。。。失败

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstdlib>
      4 #include <algorithm>
      5 using namespace std;
      6 
      7 #define MINDATA 0  /* 该值应根据具体情况定义为小于堆中所有可能元素的值 */
      8 #define ERROR -1
      9 
     10 struct HNode {
     11     int *Data; /* 存储元素的数组 */
     12     int Size;          /* 堆中当前元素个数 */
     13     int Capacity;      /* 堆的最大容量 */
     14 };
     15 typedef struct HNode *MinHeap; /* 堆的类型定义 */
     16 
     17 struct TreeNode {
     18     char c;
     19     int f;
     20 };
     21 struct TreeNode HuffNode[65];
     22 
     23 struct strNod
     24 {
     25     char c;
     26     string code;
     27 };
     28 struct strNod strNode[65];
     29 MinHeap CreateHeap( int MaxSize );
     30 bool IsFull( MinHeap H );
     31 bool Insert( MinHeap H, int X );
     32 bool IsEmpty( MinHeap H );
     33 int DeleteMin( MinHeap H );
     34 
     35 bool compare(strNod a, strNod b)
     36 {
     37     return a.code.size() < b.code.size();/*长度从小到大排序 */
     38 }
     39 
     40 /*strstr(str1,str2) 函数用于判断字符串str2是否是str1的子串。
     41 如果是,则该函数返回str2在str1中首次出现的地址;否则,返回NULL。*/
     42 /*[Error] cannot convert 'std::string {aka std::basic_string<char>}' to 'const char*' for argument '1' to 'char* strstr(const char*, const char*)'*/
     43 /*是子串返回true ,否则false */
     44 bool isStrstr(int N)
     45 {
     46     sort(strNode, strNode+N, compare);
     47     for(int i = 0; i < N; i ++) {
     48         for(int j = i + 1; j < N; j++) {
     49             if( strNode[j].code.substr( 0, strNode[i].code.size() ) == strNode[i].code )
     50                 return true;
     51         }
     52     }
     53     return false;
     54 }
     55 
     56 int main()
     57 {
     58     int N;
     59     scanf("%d",&N);
     60     MinHeap Heap = CreateHeap(N);
     61     for(int i = 0; i < N; i++) {
     62         getchar();        /*排除回车 空格的影响 */
     63         scanf("%c",&HuffNode[i].c);
     64         scanf("%d",&HuffNode[i].f);
     65         Insert(Heap, HuffNode[i].f);
     66     }
     67     
     68     //计算WPL的值 
     69     int WPL = 0;
     70     int smallA, smallB;
     71     while( !IsEmpty(Heap) ) {
     72         smallA = DeleteMin(Heap);
     73         if( !IsEmpty(Heap) ) {
     74             smallB = DeleteMin(Heap);
     75             smallA += smallB;
     76             Insert( Heap, smallA);
     77         }
     78         WPL += smallA;    
     79     } 
     80     WPL -= smallA;    
     81 //    printf("WPL = %d
    ",WPL);
     82 
     83     int M;
     84     
     85     scanf("%d",&M);
     86     for(int i = 0; i < M; i++) {
     87         int checkWpl = 0;
     88         bool overFlag = false; //其中一个字符串超出长度 
     89         for(int j = 0; j < N; j++) {
     90             cin >> strNode[j].c >> strNode[j].code;
     91             if(strNode[j].code.size() > N-1) {    //如果有size超出N-1 一定不满足WPL 这里卡一刀希望快些
     92                  overFlag = true; 
     93                  break;
     94             }
     95             checkWpl += strNode[j].code.size() * HuffNode[j].f; //计算wpl 
     96         }
     97 /*        printf("checkWpl = %d",checkWpl);*/
     98         if(checkWpl == WPL && !overFlag) {    /*WPL符合,判断是否是前缀 */
     99             if( isStrstr(N) )    /*有子串,不符合 */
    100                 printf("No
    ");
    101             else
    102                 printf("Yes
    ");
    103         }
    104         else
    105             printf("No
    "); 
    106     }
    107     return 0;    
    108 } 
    109 
    110 /* 创建容量为MaxSize的空的最小堆 */ 
    111 MinHeap CreateHeap( int MaxSize )
    112 { 
    113  
    114     MinHeap H = (MinHeap)malloc(sizeof(struct HNode));
    115     H->Data = (int*)malloc((MaxSize+1)*sizeof(int));
    116     H->Size = 0;
    117     H->Capacity = MaxSize;
    118     H->Data[0] = MINDATA; /* 定义"哨兵"为小于堆中所有可能元素的值*/
    119     return H;
    120 }
    121 
    122 bool IsFull( MinHeap H )
    123 {
    124     return (H->Size == H->Capacity);
    125 }
    126 
    127 /* 将元素X插入最小堆H,其中H->Data[0]已经定义为哨兵 */ 
    128 bool Insert( MinHeap H, int X )
    129 {
    130     if ( IsFull(H) ) { 
    131         printf("最小堆已满");
    132         return false;
    133     }
    134     int i = ++H->Size; /* i指向插入后堆中的最后一个元素的位置 */
    135     for ( ; H->Data[i/2] > X; i /= 2 )
    136         H->Data[i] = H->Data[i/2]; /* 上滤X */
    137     H->Data[i] = X; /* 将X插入 */
    138     return true;
    139 }
    140 
    141 bool IsEmpty( MinHeap H )
    142 {
    143     return (H->Size == 0);
    144 }
    145 
    146 /* 从最小堆H中取出键值为最小的元素,并删除一个结点 */ 
    147 int DeleteMin( MinHeap H )
    148 { 
    149     int Parent, Child;
    150     int MinItem, X;
    151  
    152     if ( IsEmpty(H) ) {
    153         printf("最小堆已为空");
    154         return ERROR;
    155     }
    156  
    157     MinItem = H->Data[1]; /* 取出根结点存放的最小值 */
    158     /* 用最小堆中最后一个元素从根结点开始向上过滤下层结点 */
    159     X = H->Data[H->Size--]; /* 注意当前堆的规模要减小 */
    160     for( Parent = 1; Parent * 2 <= H->Size; Parent = Child ) {
    161         Child = Parent * 2;
    162         if( (Child != H->Size) && (H->Data[Child] > H->Data[Child+1]) )
    163             Child++;  /* Child指向左右子结点的较小者 */
    164         if( X <= H->Data[Child] ) break; /* 找到了合适位置 */
    165         else  /* 下滤X */
    166             H->Data[Parent] = H->Data[Child];
    167     }
    168     H->Data[Parent] = X;
    169  
    170     return MinItem;
    171 } 
    View Code
  • 相关阅读:
    linux的文件权限分析
    Bash 文件夹操作
    bash shell 文本文件操作
    Vim文字编辑
    Windows环境Vim编辑器如何执行Ruby代码
    JavaWeb-Servlet
    app遮罩层--网赚
    flex布局 居中
    实现绝对定位元素水平垂直居中的两种方法
    CSS背景图怎么自适应全屏(手机或者电脑)
  • 原文地址:https://www.cnblogs.com/kuotian/p/5360832.html
Copyright © 2020-2023  润新知