中国大学MOOC-数据结构基础习题集、04-3、Huffman Codes

题目链接:http://www.patest.cn/contests/mooc-ds/04-3

题目分析:这是一道考察“哈夫曼编码”的问题,但是这里大家不要陷入一个误区:就是一定要把哈夫曼树构造出来。我们首先分析一下题目的需求:

  输入:第一行是结点数目num;第二行是每个结点数据data及出现的次数weight;第三行是测试数据的组数checkNum;第四行及以后是结点数据ch及编码s。

  输出:对于每一组测试数据,输出编码是否符合“哈夫曼编码”,是则输出Yes,否则输出No。

  符合“哈夫曼编码”需要符合两个条件:①WPL最小,②编码的前缀不能是其他编码的前缀。

特别说明:

  1) 这里我们不用“堆”,改用C++标准库中的优先级队列。使用优先级队列需要引入头文件 #include <queue>。优先级队列的特点是,当我们把数据放入队列里,编译器会自动按照“优先级”帮我们排好顺序。  

// 使用优先级队列模拟“堆”
priority_queue<int, vector<int>, greater<int> >pq;
// 向队列中添加元素
pq.push(f[i]);

  2) 计算WPL的值,从队列中取出两个元素,相加之后再放回队列里。如果对这段代码不理解,不妨自己拿出纸笔走一遍代码。

 1     // 计算WPL的值
 2     int myWpl = 0;
 3     while(!pq.empty())
 4     {
 5         int myTop = pq.top();
 6         pq.pop();
 7         if(!pq.empty())
 8         {
 9             int myTop2 = pq.top();
10             pq.pop();
11             pq.push(myTop + myTop2);
12             int m = myTop + myTop2;
13             myWpl += m;
14         }
15     }

  3) 标准库并没有为map制定sort函数,因此我们用vector装载pair类型,既可以模仿出map的功能,又可以用vector的排序函数了。

// 要使用排序函数sort,必须引入此头文件
#include <algorithm>
// 用PAIR来代替pair<char, string>
typedef pair<char, string> PAIR;
// cmp函数决定是从小到大排,还是从大到小排
// 还有按什么内容排,这里是按编码的长度排序
int cmp(const PAIR& x, const PAIR& y)
{
    return x.second.size() < y.second.size();
}
// vector的定义
vector<PAIR> checkVec;
// 向vector中添加元素
checkVec.push_back(make_pair(ch, s));
// 按照编码的长度排序
sort(checkVec.begin(), checkVec.end(), cmp);

  4) 判断前缀问题,我们用到了substr函数,取字符串中的一段并与当前编码进行比较。

1  for(int i=0; i<num; i++)
2  {
3    string tmp = checkVec[i].second;
4    for(int j=i+1; j<num; j++)
5    {
6      if(checkVec[j].second.substr(0,tmp.size())==tmp)
7           flag = false;
8    }
9  }

代码分析:

头文件及其他相关声明:1~11

比较函数,用于sort中用来指定依据什么来进行排序,以及从小到大还是从大到小:14~18

输入:19~35

计算WPL值:36~50

输入测试数据及进行处理、判断:51~98

 1 #include <iostream>
 2 // 要使用排序函数sort,必须引入此头文件
 3 #include <algorithm>
 4 #include <map>
 5 #include <queue>
 6 
 7 using namespace std;
 8 
 9 // 用PAIR来代替pair<char, string>
10 typedef pair<char, string> PAIR;
11 
12 // cmp函数决定是从小到大排,还是从大到小排
13 // 还有按什么内容排,这里是按编码的长度排序
14 int cmp(const PAIR& x, const PAIR& y)
15 {
16     return x.second.size() < y.second.size();
17 }
18 
19 int main()
20 {
21     int num;
22     cin >> num;
23     char *c = new char[num];
24     int *f = new int[num];
25     map<char, int> myMap;
26     // 使用优先级队列模拟“堆”
27     priority_queue<int, vector<int>, greater<int> >pq;
28     // 输入结点及出现次数
29     for(int i=0; i<num; i++)
30     {
31         cin >> c[i] >> f[i];
32         myMap[c[i]] = f[i];
33         // 向队列中添加元素
34         pq.push(f[i]);
35     }
36     // 计算WPL的值
37     int myWpl = 0;
38     while(!pq.empty())
39     {
40         int myTop = pq.top();
41         pq.pop();
42         if(!pq.empty())
43         {
44             int myTop2 = pq.top();
45             pq.pop();
46             pq.push(myTop + myTop2);
47             int m = myTop + myTop2;
48             myWpl += m;
49         }
50     }
51     // 输入测试数据
52     int checkNum;
53     cin >> checkNum;
54     for(int i=0; i<checkNum; i++)
55     {
56         int wpl = 0;
57         char ch;
58         string s;
59         // vector的定义
60         vector<PAIR> checkVec;
61         for(int j=0; j<num; j++)
62         {
63             cin >> ch >> s;
64             // 向vector中添加元素
65             checkVec.push_back(make_pair(ch, s));
66             wpl += s.size() * myMap[ch];
67         }
68         // 按照编码的长度排序
69         sort(checkVec.begin(), checkVec.end(), cmp);
70         if(wpl != myWpl)
71         {
72             cout << "No" << endl;
73             continue;
74         }
75         else
76         {
77             bool flag = true;
78 
79             for(int i=0; i<num; i++)
80             {
81                 string tmp = checkVec[i].second;
82                 for(int j=i+1; j<num; j++)
83                 {
84                     if(checkVec[j].second.substr(0,tmp.size())==tmp)
85                         flag = false;
86                 }
87             }
88 
89             if(flag == true)
90                 cout << "Yes" << endl;
91             else
92                 cout << "No" << endl;
93             continue;
94         }
95         cout << "Yes" << endl;
96     }
97     return 0;
98 }

 AC成果:

posted @ 2014-12-30 12:45  聪明的聪聪  阅读(645)  评论(0编辑  收藏  举报