Huffman树的创建和Huffman编码。使带权路径最短的树。
#include<bits/stdc++.h>
#define MAX 1010
using namespace std;
/*
Huffman树:
带权路径长度最小的树
各结点到根的距离与结点的权相乘之和叫带权路径长度。
Huffman编码:
把Huffman树中各结点到左孩子的路径编码为0,到右孩子的路
编码为1(反过来也可以)。叶节点被编码的值为Huffman编码。
特点:
字符用Huffman编码后 占用的二进制位的总期望值最低。
*/
/*
操作:
把数据按权值排序,取最小的两个构建一棵树,树根的值为此两个权值的和,
然后把这两个结点删除,此树根插入。再排序,重复之前的步骤至全部插入树中。
*/
//结点结构
typedef class Node
{
public:
char character;
int probability;
string code;
Node *left;
Node *right;
Node(){ left = right = NULL; code = ""; }
Node(int t){ probability = t; left = right = NULL; code = ""; }
Node(Node &t){ this->character = t.character; this->probability = t.probability;
this->code = t.code; this->left = t.left; this->right = t.right; code = ""; }
} *Huffman;
/*
最小堆
*/
bool cmp(Node e1, Node e2){ return e1.probability > e2.probability; }
Huffman createHuffman(Node *data, int n)
{
//先建一个堆
make_heap(&data[0], &data[n], cmp);
for(int i = 1; i < n; i++)
{
//取出堆顶
Node *l = new Node(data[0]);
pop_heap(&data[0], &data[n - i + 1], cmp);
//再取出堆顶
Node* r = new Node(data[0]);
pop_heap(&data[0], &data[n - i], cmp);
//合并为一棵树
Node *temp = new Node(l->probability + r->probability);
temp->left = l;
temp->right = r;
//插入合并后的树
data[n - i - 1] = *temp;
push_heap(&data[0], &data[n - i], cmp);
}
//返回树根
return &data[0];
}
void print_preOrder_recursion(Huffman root)
{
if(root != NULL)
{
if(root->left == NULL && root->right == NULL)
cout << root->character << " " << root->probability << " " << root->code << endl;
print_preOrder_recursion(root->left);
print_preOrder_recursion(root->right);
}
}
/*
后序遍历时,存储的路径就是编码
*/
void coding(Huffman root)
{
Huffman arr[MAX];
vector<char> v;
int t = 0; //栈顶。模拟栈
Huffman pointer = root, visit = NULL;
while(pointer != NULL || t != 0)
{
while(pointer != NULL)
{
arr[t++] = pointer;
pointer = pointer->left;
v.push_back('0');
}
pointer = arr[--t];
v.pop_back();
if(pointer->right != NULL && pointer->right != visit)
{
arr[t++] = pointer;
pointer = pointer->right;
v.push_back('1');
}else{
for(int i = 0; i < v.size(); i++)
pointer->code += v[i];
visit = pointer;
pointer = NULL;
}
}
}
int main()
{
int n, i;
cin >> n;
Node *data = new Node[n];
for(i = 0; i < n; i++)
{
data[i].probability = n - i;
data[i].character = char(97 + i);
}
Huffman root = createHuffman(data, n);
coding(root);
print_preOrder_recursion(root);
return 0;
}