霍夫曼编码与译码

来源:互联网 发布:美国白银数据公布 编辑:程序博客网 时间:2024/05/16 23:41

树和二叉树的应用

一.实验题目:树和二叉树的应用

二.实验内容:哈夫曼编码设计

三.实验目的:掌握树和二叉树的概念及工作原理,运用其原理及概念完成上述实验题中的内容。

四、概要设计原理:

1.选择parent为-1且weight最小的两个结点。其序号分别为s1和s2

2.建立赫夫曼树叶

3.从叶子到根逆向求每个字符的赫夫曼编码

4.输出构造的树

5.输出得到的各权Huffman编码

#include<iostream>#include<iomanip>using namespace std;struct HaffNode{    int weight;    int parent;    int lchild;    int rchild;};struct HaffCode{    int bit[10000];   //编码位    int start;        //编码开始的位置    int weight;    char c;             //编码所对应的字符};/*      由于n个叶子结点,要合并n-1次。每次从   还无双亲(无双亲代表还未合并过)   的叶子结点中选择权值最小的两个叶子结点进行合并,   新结点下标为这两个叶子的双亲,新结点的权值为这两个叶子权值之和,   左孩子为最小结点下标,右孩子为次小结点下标,叶子值不需要,双亲为0。*/void CreateHaffman(int w[],int n,HaffNode ht[]){    //建立叶结点个数为n,权值为weight的哈夫曼树haffTree    int i,j,m1,m2,x1,x2;    //哈夫曼树haffTree初始化。n个叶结点的哈夫曼树共有2n-1个结点    for(i=0;i<2*n-1;i++)    {        if(i<n)            ht[i].weight=w[i];        else            ht[i].weight=0;            ht[i].parent=0;            ht[i].lchild=-1;            ht[i].rchild=-1;    }    //构造哈夫曼树haffTree的n-1个非叶结点   for(i=0;i<n-1;i++)   {      m1=m2=1000;      x1=x2=0;      for(j=0;j<n+i;j++)//循环找出所有权重中,最小的二个值      {          if(ht[j].weight<m1&&ht[j].parent==0)          {              m1=ht[j].weight;              x1=j;          }          else if(ht[j].weight<m2&&ht[j].parent==0)          {              m2=ht[j].weight;              x2=j;          }      }      //将找出的两棵权值最小的子树合并为一棵子树      ht[x1].parent=n+i;//新结点下标为这两个叶子的双亲,      ht[x2].parent=n+i;      ht[n+i].weight=ht[x1].weight+ht[x2].weight;//新结点的权值为这两个叶子权值之和      ht[n+i].lchild=x1;      ht[n+i].rchild=x2; }}void encoded(int n,char ch[],HaffNode ht[],HaffCode hc[]){    //由n个结点的哈夫曼树haffTree构造哈夫曼编码haffCode    HaffCode cd;    int child,parent,i,j;    //求n个叶结点的哈夫曼编码    for(i=0;i<n;i++)    {        cd.start=n-1;        cd.c=ch[i];        cd.weight=ht[i].weight;//取得编码对应权值的字符        child=i;        parent=ht[child].parent;//由叶结点向上直到根结点        while(parent!=0)        {            if(ht[parent].lchild==child)                cd.bit[cd.start]=0;//左孩子结点编码0            else                cd.bit[cd.start]=1;//右孩子结点编码1                cd.start--;                child=parent;                parent=ht[child].parent;        }    //保存叶结点的编码和不等长编码的起始位        for(j=cd.start+1;j<n;j++)//重新修改编码,从根节点开始计数            hc[i].bit[j]=cd.bit[j];        hc[i].start=cd.start;        hc[i].weight=cd.weight;//保存编码对应的权值        hc[i].c=cd.c;        cout<<"字符"<<cd.c<<"的权值为:"<<hc[i].weight<<"   code=";        for(j=hc[i].start+1;j<n;j++)            cout<<hc[i].bit[j];        cout<<endl;    }}void transcode(int n,HaffNode ht[],HaffCode hc[]){    int a=2*n-2;    char b;    cout<<"请输入一串二进制编码(0,1以外的数结束)"<<endl;    cin>>b;    while((b=='0')||(b=='1'))    {        if(b=='0')            a=ht[a].lchild;        else            a=ht[a].rchild;        if(ht[a].lchild==-1)        {            cout<<hc[a].c;            a=2*n-2;        }         cin>>b;    }}int main(){    int w[1000];//权值数组    char ch[1000];//代码数组    int n,a;    cout<<"共有叶子数:"<<endl;    cin>>n;    cout<<"依次输入每个叶子的权值:"<<endl;    for(a=0;a<n;a++)        cin>>w[a];    cout<<"依次输入每个叶子所代表代码:"<<endl;    for(a=0;a<n;a++)        cin>>ch[a];    HaffNode* ht=new HaffNode[2*n-1];//树结点数组    HaffCode* hc=new HaffCode[n];//编码数组    CreateHaffman(w,n,ht);    encoded(n,ch,ht,hc);    transcode(n,ht,hc);    return 0;}


0 0
原创粉丝点击