HuffmanTree的实现及Huffman编码

来源:互联网 发布:apache tomcat什么意思 编辑:程序博客网 时间:2024/05/16 08:08

HuffTree的定义:

假设一共有n个data,第i个data有对应的权值wi。使从根节点到所有data的路径长度乘以其权值和为最小。符合其条件的树就是HuffmanTree,也被称为最优二叉树。

实现步骤:

  1. 先将n个data建成n个只有一个根节点的数
  2. 然后从n个中找出两个最小的data
  3. 将这两个数合并为一个二叉树,左孩子为最小值,右孩子为第二小值
  4. 将这个树的根节点的权值设为原来两个点的权值之和
  5. 在剩下的n-1个根节点中执行步骤2
  6. 直到只剩下一个根节点,结束循环。

下面来讲一下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;}
0 0