• 中国大学MOOC数据结构基础习题集、043、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成果:

  • 相关阅读:
    文本建模、文本分类相关开源项目推荐(Pytorch实现)
    自然语言推断(NLI)、文本相似度相关开源项目推荐(Pytorch 实现)
    20155312 张竞予 Exp9 Web安全基础
    20155312 张竞予 Exp 8 Web基础
    20155312 张竞予 Exp7 网络欺诈防范
    20155312 张竞予 Exp6 信息搜集与漏洞扫描
    20155312 张竞予 Exp5 MSF基础应用
    20155312 张竞予 Exp4 恶意代码分析
    20155312 张竞予 Exp3 免杀原理与实践
    20155312 张竞予 Exp2 后门原理与实践
  • 原文地址:https://www.cnblogs.com/clevercong/p/4193370.html
Copyright © 2020-2023  润新知