HuffTree的定义:
假设一共有n个data,第i个data有对应的权值wi。使从根节点到所有data的路径长度乘以其权值和为最小。符合其条件的树就是HuffmanTree,也被称为最优二叉树。
实现步骤:
- 先将n个data建成n个只有一个根节点的数
- 然后从n个中找出两个最小的data
- 将这两个数合并为一个二叉树,左孩子为最小值,右孩子为第二小值
- 将这个树的根节点的权值设为原来两个点的权值之和
- 在剩下的n-1个根节点中执行步骤2
- 直到只剩下一个根节点,结束循环。
下面来讲一下HuffmanTree的一个最经典的应用,Huffman编码。
(以下定义摘自百度百科)
Huffman编码是一种无前缀变字长编码。解码时不会混淆。
使用Huffman编码的前提是知道每一个字母出现的频率。
在编码时,字母出现的频率相当于HuffmanTree中的data的权值。然后从根节点开始,每经过一个左子树,编码加一个0。每经过一个右子树,编码加一个1。
这样建树之后,每一个字母都有自己的唯一编码,且无重复前缀。
HuffmanTree及编码的实现代码:
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<cstdio>
using namespace std;
const int maxn=100;
typedef struct {
int weight;
int parent,lchild,rchild;
}HafNode;//HuffmanTree的基本定义
typedef struct {
int weight;
char data;
char code[maxn];//需要被建树的信息
}HafCode;
void Init(HafCode *h,int &n)//初始化输入数据
{
cout<<"Input The Number"<<endl;
cin>>n;
cout<<"Input The Character And Weight"<<endl;
for(int i=0;i<n;++i)
cin>>h[i].data>>h[i].weight;
}
void select(HafNode *h,int k,int &s1,int &s2)//选择两个最小的值
{
int i;
for(i=0; i<k && h[i].parent != 0; ++i);//选择一个父节点为0的根节点
s1 = i;
for(i=0; i<k; ++i){
if(h[i].parent==0 && h[i].weight<h[s1].weight)
s1 = i;
}
for(i=0; i<k; ++i){
if(h[i].parent==0 && i!=s1)
break;
}
s2 = i;
for(i=0; i<k; ++i){
if(h[i].parent==0 && i!=s1 && h[i].weight<h[s2].weight)
s2 = i;
}
}
void Huffman(HafCode *h2,HafNode *h1,int n)
{
char str[maxn];
int m=2*n-1;
for(int i=0;i<m;++i){
if(i<n)//前n个全部是叶子节点,
h1[i].weight=h2[i].weight;
else//后面的是还没建成的树
h1[i].weight==0;
h1[i].lchild=h1[i].parent=h1[i].rchild=0;
}
int s1,s2;
for(int i=n;i<m;++i){
select(h1,i,s1,s2);
h1[s1].parent=i;//建立二叉树
h1[s2].parent=i;
h1[i].lchild=s1;
h1[i].rchild=s2;
h1[i].weight=h1[s1].weight+h1[s2].weight;
//cout<<h1[s1].weight<<" "<<h1[s2].weight<<endl;
}
str[n]='\0';
//memset(str,0,sizeof(str));
int l,p;
for(int i=0;i<n;++i){//从每个叶子节点开始倒序遍历
l=n-1;//倒序赋值字符串
//cout<<h2[i].data<<endl;
for(int k=i,p=h1[k].parent;p;k=p,p=h1[k].parent){//沿着叶子回溯到根节点
if(k==h1[p].lchild)
str[l]='0';
else
str[l]='1';
// cout<<str[l];
l--;
}
//cout<<endl;
strcpy(h2[i].code,str+l+1);
}
}
int main()
{
int n;
HafCode hc[maxn];
HafNode tree[maxn];
Init(hc,n);
Huffman(hc,tree,n);
for(int i=0;i<n;++i)
cout<<hc[i].data<<" "<<hc[i].code<<endl;
return 0;
}