# 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

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

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\n");
80             else
81                 printf("Yes\n");
82         }
83         else
84             printf("No\n");
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\n",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\n");
95             else
96                 printf("Yes\n");
97         }
98         else
99             printf("No\n");
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\n",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\n");
101             else
102                 printf("Yes\n");
103         }
104         else
105             printf("No\n");
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

posted on 2016-04-06 19:46  kuotian  阅读(658)  评论(0编辑  收藏  举报