基本概念

给定N个权值作为N个叶子结点,构造一棵二叉树,若该树的带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树(Huffman Tree)。哈夫曼树是带权路径长度最短的树,权值较大的结点离根较近。

  • 带权路径长度:

    哈夫曼树 - 图1

    题目

    哈夫曼编码

    注意考虑树只有一个点的情况 ```cpp

    include

    include

    include

    include

    include

    include

using namespace std;

const int N = 1010;

char s[N]; unordered_map rec; // 记录字母出现次数

int main() {

  1. #ifdef SUBMIT
  2. freopen("in.txt", "r", stdin);
  3. freopen("out.txt", "w", stdout);
  4. long _begin_time = clock();
  5. #endif
  6. while (scanf("%s", s), strcmp(s, "END") != 0) {
  7. int len = strlen(s);
  8. rec.clear(); // 记得清空
  9. for (int i = 0; i < len; i++) {
  10. rec[s[i]]++;
  11. }
  12. priority_queue<int, vector<int>, greater<int>> heap; // 优先队列没有clear方法
  13. for (auto it = rec.begin(); it != rec.end(); it++) {
  14. heap.push(it->second);
  15. // cout << (double)it->second / len << ' ';
  16. }
  17. // cout << endl;
  18. int avg = 0;
  19. if (heap.size() == 1) { // 注意,只有一个点时,带权路径长度就是那个点的权值
  20. avg = heap.top();
  21. }
  22. while (heap.size() > 1) { // 至少有两个点才能合并
  23. double a1 = heap.top(); heap.pop();
  24. double a2 = heap.top(); heap.pop();
  25. avg += a1 + a2;
  26. heap.push(a1 + a2);
  27. }
  28. // cout << avg << endl;
  29. int ori = len * 8;
  30. printf("%d %d %.1lf\n", ori, avg, (double)ori / avg);
  31. }
  32. #ifdef SUBMIT
  33. long _end_time = clock();
  34. printf("\n\ntime = %ld ms", _end_time - _begin_time);
  35. #endif
  36. return 0;

} ```