1 #include <iostream>
2 #include <vector>
3 #include <algorithm>
4 using namespace std;
5
6 //Huffman树的节点类
7 typedef struct Node
8 {
9 char value; //结点的字符值
10 int weight; //结点字符出现的频度
11 Node *lchild, *rchild; //结点的左右孩子
12 }Node;
13
14 //自定义排序规则,即以vector中node结点weight值升序排序
15 bool ComNode(Node *p, Node *q)
16 {
17 return p->weight<q->weight;
18 }
19
20 //构造Huffman树,返回根结点指针
21 Node* BuildHuffmanTree(vector<Node*> vctNode)
22 {
23 while (vctNode.size()>1) //vctNode森林中树个数大于1时循环进行合并
24 {
25 sort(vctNode.begin(), vctNode.end(), ComNode); //依频度高低对森林中的树进行升序排序
26
27 Node *first = vctNode[0]; //取排完序后vctNode森林中频度最小的树根
28 Node *second = vctNode[1]; //取排完序后vctNode森林中频度第二小的树根
29 Node *merge = new Node; //合并上面两个树
30 merge->weight = first->weight + second->weight;
31 merge->lchild = first;
32 merge->rchild = second;
33
34 vector<Node*>::iterator iter;
35 iter = vctNode.erase(vctNode.begin(), vctNode.begin() + 2); //从vctNode森林中删除上诉频度最小的两个节点first和second
36 vctNode.push_back(merge); //向vctNode森林中添加合并后的merge树
37 }
38 return vctNode[0]; //返回构造好的根节点
39 }
40
41 //用回溯法来打印编码
42 void PrintHuffman(Node *node, vector<int> vctchar)
43 {
44 if (node->lchild == NULL && node->rchild == NULL)
45 {//若走到叶子节点,则迭代打印vctchar中存的编码
46 cout << node->value << ": ";
47 for (vector<int>::iterator iter = vctchar.begin(); iter != vctchar.end(); iter++)
48 cout << *iter;
49 cout << endl;
50 return;
51 }
52 else
53 {
54 vctchar.push_back(1); //遇到左子树时给vctchar中加一个1
55 PrintHuffman(node->lchild, vctchar);
56 vctchar.pop_back(); //回溯,删除刚刚加进去的1
57 vctchar.push_back(0); //遇到左子树时给vctchar中加一个0
58 PrintHuffman(node->rchild, vctchar);
59 vctchar.pop_back(); //回溯,删除刚刚加进去的0
60
61 }
62 }
63
64 int main()
65 {
66 cout << "************ Huffman编码问题 ***************" << endl;
67 cout << "请输入要编码的字符,并以空格隔开(个数任意):" << endl;
68 vector<Node*> vctNode; //存放Node结点的vector容器vctNode
69 char ch; //临时存放控制台输入的字符
70 while ((ch = getchar()) != '\n')
71 {
72 if (ch == ' ')continue; //遇到空格时跳过,即没输入一个字符空一格空格
73 Node *temp = new Node;
74 temp->value = ch;
75 temp->lchild = temp->rchild = NULL;
76 vctNode.push_back(temp); //将新的节点插入到容器vctNode中
77 }
78
79 cout << endl << "请输入每个字符对应的频度,并以空格隔开:" << endl;
80 for (int i = 0; i<vctNode.size(); i++)
81 cin >> vctNode[i]->weight;
82
83 Node *root = BuildHuffmanTree(vctNode); //构造Huffman树,将返回的树根赋给root
84 vector<int> vctchar;
85 cout << endl << "对应的Huffman编码如下:" << endl;
86 PrintHuffman(root, vctchar);
87
88 system("pause");
89 }