(2016-3)字符串的哈夫曼编码长度

问题描述:

给定一个字符串(长度不超过100),求哈夫曼编码的最短长度

样例输入:

输入1:

abbcccdddd

输出1:

19

输入2:

we will we will r u

输出2:

50

思路:

本题如果真要用哈夫曼来建树,计算值会非常复杂。

首先要能够发现规律:哈夫曼树的编码长度等于各个叶节点权值与路径长度乘积之和,同时这个值等于非叶节点之和。

采用优先队列模拟哈夫曼树的建立。采用map记录字符与出现的次数,将每个字符的次数依次加入优先队列(数值小的在队头),每一次从队列中出队最小的两个,相加后再加入队列中。用ans记录每一次相加和temp值之和,当队列中剩下一个元素时,ans的值即为所求

知识点:

priority_queue 优先队列

  1. priority_queue<int>q; 默认为数字(字典序)大的值在队首top,等价于priority_queue<int, vector<int>, less<int> >q;
  2. priority_queue<int, vector<int>, greater<int> >q; 表示数字(字典序)小的在队首
  3. 没有front、back函数,只有top用于读取队首元素

注意:

  1. map中查找元素用find,要仔细
#include <iostream>
#include <string>
#include <cstring>
#include <queue>
#include <map>
using namespace std;
const int maxn = 100;

string str;
map<char, int> mp;
priority_queue<int, vector<int>, greater<int> >q;

int main(){ 
    getline(cin, str);
    int len = str.length();
    for(int i = 0; i < len; i++){
       if(mp.find(str[i]) == mp.end()){
            mp[str[i]] = 1;
       }
       else{
            mp[str[i]]++;
       }
    }
    for(map<char, int>::iterator it = mp.begin(); it != mp.end(); it++){
        q.push(it->second);
    }
    int ans = 0;
    while(q.size() != 1){
        int a, b, temp;
        a = q.top();
        q.pop();
        b = q.top();
        q.pop();
        temp = a + b;
        ans += temp;
        q.push(temp);
    }
    cout << ans << endl;
    return 0;
}

猜你喜欢

转载自blog.csdn.net/weixin_35093872/article/details/88055475