pta 编程题14 Huffman Codes

其它pta数据结构编程题请参见:pta

题目

题目给出一组字母和每个字母的频数,因为哈夫曼编码不唯一,然后给出几组编码,因为哈夫曼编码不唯一,所以让你判断这些编码是否符合是哈夫曼编码的一种。

解题思路:

1、构造哈夫曼树,并求出总代价COST,即各个字母的频数乘以编码长度的和。

2、对于题目给出的每一组编码,判断是否符合哈夫曼编码,即这组编码是否为前缀码,同时代价cost是否等于计算出的哈夫曼树的代价COST。

判断一组编码是否为前缀码的方法:

将这些编码逐个的添加到哈夫曼树中,对于每一个编码字符串,字符串中的每一个字符也逐个扫描,如果是0则向左构造树,1则向右构造树。如果已扫描到某节点为叶子节点但字符串还未结束,或者字符串已扫描结束但还当前节点非空,那么就不是前缀码。

需要注意的点:

最小堆数组中的元素类型ElementType为HuffmanTree型。

 

  1 #include <iostream>
  2 #include <string>
  3 #include <map>
  4 using namespace std;
  5 
  6 /*----------哈夫曼树定义---------*/
  7 typedef struct HuffmanNode *HuffmanTree;
  8 struct HuffmanNode
  9 {
 10     int weight;
 11     HuffmanTree left, right;
 12 };
 13 /*----------最小堆定义-----------*/
 14 #define minData -1;
 15 typedef HuffmanTree ElementType;
 16 typedef struct HeapNode* minHeap;
 17 struct HeapNode
 18 {
 19     ElementType *data;
 20     int size;
 21 };
 22 /*----------最小堆相关操作--------*/
 23 minHeap buildHeap(int N);
 24 void percDown(minHeap H, int p);
 25 void insert(minHeap H, HuffmanTree x);
 26 HuffmanTree deleteMin(minHeap H);
 27 /*----------哈夫曼树相关操作------*/
 28 HuffmanTree huffman(int N);
 29 HuffmanTree initHuffmanNode(int weight);
 30 bool cmp(HuffmanTree a, HuffmanTree b);
 31 void getLength(HuffmanTree T, int& total, int length);
 32 /*----------其它操作--------------*/
 33 bool valid(int N, int total);
 34 HuffmanTree insertHuffman(HuffmanTree T, string s, int n, bool& judge);
 35 map<string, int> mapp;
 36 /*--------------------------------*/
 37 
 38 int main()
 39 {
 40     int N, M, i;
 41     cin >> N;
 42     HuffmanTree T = huffman(N); //构造哈夫曼树
 43     int total = 0; //总哈夫曼编码长度
 44     getLength(T, total, 0);
 45     cin >> M;
 46     for (i = 0; i < M; i++)
 47     {
 48         if (valid(N, total)) cout << "Yes" << endl;
 49         else cout << "No" << endl;
 50     }
 51     return 0;
 52 }
 53 
 54 HuffmanTree initHuffmanNode(int weight)
 55 {
 56     HuffmanTree T = new HuffmanNode;
 57     T->weight = weight;
 58     T->left = T->right = NULL;
 59     return T;
 60 }
 61 
 62 minHeap buildHeap(int N)
 63 {
 64     minHeap H = new HeapNode;
 65     H->data = new ElementType[N + 1];
 66     H->size = 0;
 67     H->data[0] = initHuffmanNode(-1);//哨兵
 68 
 69     string c;
 70     int i, t;
 71     for (i = 1; i <= N; i++)
 72     {
 73         cin >> c >> t;
 74         mapp[c] = t;
 75         H->data[i] = initHuffmanNode(t);
 76     }
 77     H->size = N;
 78 
 79     /* 调整堆中的元素 */
 80     for (i = H->size / 2; i > 0; i--)
 81         percDown(H, i);
 82     return H;
 83 }
 84 
 85 void percDown(minHeap H, int p)
 86 { /* 下滤:将H中以H->Data[p]为根的子堆调整为最小堆 */
 87     int parent, child;
 88     ElementType X = H->data[p];
 89     for (parent = p; parent * 2 <= H->size; parent = child)
 90     {
 91         child = parent * 2;
 92         if (child != H->size && cmp(H->data[child], H->data[child + 1]))
 93             child++;
 94         if (!cmp(X, H->data[child])) break;
 95         else
 96             H->data[parent] = H->data[child];
 97     }
 98     H->data[parent] = X;
 99 }
100 
101 void insert(minHeap H, HuffmanTree x)
102 {
103     int i;
104     for (i = ++H->size; cmp(H->data[i / 2], x); i /= 2)
105         H->data[i] = H->data[i / 2];
106     H->data[i] = x;
107 }
108 
109 HuffmanTree deleteMin(minHeap H)
110 {
111     HuffmanTree minItem = H->data[1];
112     ElementType x = H->data[H->size--];
113     int parent, child;
114     for (parent = 1; parent * 2 <= H->size; parent = child)
115     {
116         child = parent * 2;
117         if (child != H->size && cmp(H->data[child], H->data[child + 1]))
118             child++; //将两个子节点中较小的一个和x比较
119         if (!cmp(x, H->data[child])) break;
120         else
121             H->data[parent] = H->data[child];
122     }
123     H->data[parent] = x;
124     return minItem;
125 }
126 
127 HuffmanTree huffman(int N)
128 {
129     HuffmanTree T;
130     minHeap H = buildHeap(N);
131 
132     while (H->size > 1)
133     {
134         T = new HuffmanNode;
135         T->left = deleteMin(H);
136         T->right = deleteMin(H);
137         T->weight = T->left->weight + T->right->weight;
138         insert(H, T);
139     }
140     T = deleteMin(H);
141     return T;
142 }
143 
144 bool cmp(HuffmanTree a, HuffmanTree b)
145 {
146     return a->weight > b->weight;
147 }
148 
149 void getLength(HuffmanTree T, int& total, int length)
150 {
151     if (!T) return;
152     if (!T->left && !T->right) //叶子节点
153         total += length * T->weight;
154     getLength(T->left, total, length + 1);
155     getLength(T->right, total, length + 1);
156 }
157 
158 bool valid(int N, int total)
159 {
160     string c, s;
161     bool isValid = true;
162     int i, sum = 0;
163     HuffmanTree T = initHuffmanNode(0);
164     for (i = 0; i < N; i++)
165     {
166         cin >> c >> s;
167         sum += s.size() * mapp[c];
168         if (!isValid) continue;
169         if (s[0] == '0')
170             T->left = insertHuffman(T->left, s, 0, isValid);
171         else
172             T->right = insertHuffman(T->right, s, 0, isValid);
173     }
174     if (!isValid || sum != total) return false;
175     else return true;
176 }
177 
178 HuffmanTree insertHuffman(HuffmanTree T, string s, int n, bool& judge)
179 {
180     if (!T)
181         T = initHuffmanNode(0);
182     else
183     {
184 
185         if (n + 1 == s.size()) judge = false;//当前节点非空且为字符串最后一个字符
186         else if (!T->left && !T->right)//当前节点为叶子节点且字符串还未结束
187             judge = false;
188     }
189     if (n + 1 < s.size())
190     {
191         if (s[n + 1] == '0')
192             T->left = insertHuffman(T->left, s, n + 1, judge);
193         else
194             T->right = insertHuffman(T->right, s, n + 1, judge);
195     }
196     return T;
197 }

 

posted @ 2018-04-22 17:07  bloglxc  阅读(614)  评论(0编辑  收藏  举报