霍夫曼编码

Description
对输入的英文大写字母序列进行统计概率,然后构建Huffman树,输出按照概率降序排序输出Huffman编码。
 
Input

第一行是大写字母个数n(0<n<=100)

第二行为n个字母,中间以一个空格分隔。
 
Output

假设输入中共有m个不同的字母,按照出现概率降序输出,每个字母单独一行输出。格式如下:

字母1 出现次数 Huffman编码
字母2 出现次数 Huffman编码
字母3 出现次数 Huffman编码
字母m 出现次数 Huffman编码
 
Sample Input
Copy sample input to clipboard
10
S S U U U S U L U U
Sample Output
U 6 1
S 3 01
L 1 00

题目分析

构造哈夫曼树非常简单,每次将所有节点排序,用一个节点替换两个频率最低的节点,新节点的频率就是这两个节点的频率之和。这样,新节点就是两个被替换节点的父节点了。如此循环,直到只剩一个节点(树根)。
注意使被替换节点中频率低的为左孩子,高者为右孩子

为了适应题目需求,定义了如下结构体
struct Node {
  int value;    // 记录频率
  char c;       // 记录字符
  std::string code;   // 记录编码
  Node* l;            // 左孩子
  Node* r;            // 右孩子
  Node(int num, int index) { };   //num为频率, index用来确定是那个字符
} *nodes[26];
在按照上面方法构造哈夫曼树的时候,同时将所有的叶子节点(左右孩子为NULL)按频率从低到高(左孩子先入栈)入栈
当只剩下一个节点时,从上到下确定每个节点的编码
if (root->l != NULL) {
  root->l->code = root->code + "0";
  dfs(root->l);
}同理确定右孩子的编码
最后按要求输出栈内节点的值

#include <iostream>
#include <stack>
#include <algorithm>
#include <memory.h>

struct Node {
  int value;
  char c;
  std::string code;
  Node* l;
  Node* r;
  Node(int num, int index) {
    value = num;
    c = 'A' + index;
    code = "";
    l = r = NULL;
  }
} *nodes[26];

bool com(Node* a, Node* b) {
  return a->value > b->value;
}

void dfs(Node* root) {
  if (root->l != NULL) {
    root->l->code = root->code + "0";
    dfs(root->l);
  }
  if (root->r != NULL) {
    root->r->code = root->code + "1";
    dfs(root->r);
  }
}

int main()
{
  int num;
  std::cin >> num;
  int arr[26];
  memset(arr, 0, sizeof(arr));
  char temp;
  int count = 0;
  for (int i = 0; i < num; ++i) {
    std::cin >> temp;
    if (arr[temp-'A'] == 0)
      count++;
    arr[temp-'A']++;
  }
//std::cout << count << std::endl;
  int index = 0;
  for (int i = 0; i < 26; ++i) {
    if (arr[i] > 0) {
      nodes[index++] = new Node(arr[i], i);
    }
  }

  std::stack<Node*> s;
  while (count != 1) {
    std::sort(nodes, nodes+count, com);
    if (nodes[count-1]->l == NULL && nodes[count-1]->r == NULL)
      s.push(nodes[count-1]);
    if (nodes[count-2]->l == NULL && nodes[count-2]->r == NULL)
      s.push(nodes[count-2]);
    Node* father = new Node(nodes[count-1]->value + nodes[count-2]->value, 0);
    father->l = nodes[count-1];
    father->r = nodes[count-2];
    nodes[count-2] = father;
    count--;
  }
//std::cout << count << std::endl;
  dfs(nodes[0]);
//std::cout << "coding end" << std::endl;
  while (!s.empty()) {
    std::cout << s.top()->c << " " << s.top()->value << " " << s.top()->code << std::endl;
    s.pop();
  }
}



你可能感兴趣的:(霍夫曼编码)