哈夫曼编码

#include<iostream.h>
const int MAX=20;
//哈夫曼树输入数据的结构
struct huffinit
{
    char data;
    int weight;
};
//哈夫曼树结点的结构
struct huffnode
{
    int weight;
    int lchild,rchild,parent;
};
//哈夫曼树编码的结构
struct huffcode
{
    char data;
    char code[MAX+1];
};
huffnode tree[2*MAX-1]; //存huffman树
huffcode cd[MAX];  //存编码信息
int size; //叶子结点个数
void Select(int &min1,int &min2,int m)
{
    min1=min2=0;
    int m1=32767,m2;
    int i,t;
    for(i=0;i<m;i++)
    {
        if(tree[i].parent==-1)
            if(tree[i].weight<m1)
            {
                m2=m1;
                min2=min1;
                m1=tree[i].weight;
                min1=i;
            }
            else if(tree[i].weight<m2)
            {
                m2=tree[i].weight;
                min2=i;
            }
    }
    if(min1>min2)
    {
        t=min1;
        min1=min2;
        min2=t;
    }
}
void HuffTree(huffinit w[],int n)
{
    int i;
    for(i=0;i<2*n-1;i++)//初始化,所有的结点均没有双亲和孩子
    {
        tree[i].parent=-1;
        tree[i].lchild=-1;
        tree[i].rchild=-1;
    }
    for(i=0;i<n;i++)//构造出n颗只含有根节点的二叉树
    {
        cd[i].data=w[i].data;//结点值
        tree[i].weight=w[i].weight;//权值
    }
    int k,i1,i2;
    for(k=n;k<2*n-1;k++)//经过n-1次合并
    {
        Select(i1,i2,k);//查找出最小的两个根节点,下标为i1,i2
        tree[i1].parent=k;//将i1和i2合并,且i1和i2的双亲为k
        tree[i2].parent=k;
        tree[k].weight=tree[i1].weight+tree[i2].weight;
        tree[k].lchild=i1;
        tree[k].rchild=i2;
    }
    size=n;
}
void Output()//输出哈夫曼树各节点的信息
{
    int i;
    cout<<"已建好的哈夫曼树各结点信息为:"<<endl;
    for(i=0;i<2*size-1;i++)
        cout<<tree[i].weight<<" "<<tree[i].parent<<" "<<tree[i].lchild<<" "<<tree[i].rchild<<endl;
}
void Encode()//对结点进行编码
{
    int i;
    for(i=0;i<size;i++)
    {
        char code[MAX+1];
        int start=MAX+1;
        int parent=tree[i].parent;
        int position=i;
        while(parent!=-1)
        {
            start--;
            if(tree[parent].lchild==position)
				code[start]='0';
            else
				code[start]='1';
            position=parent;
            parent=tree[parent].parent;
        }
        int j=0;
        while(start<=MAX)
        {
            cd[i].code[j]=code[start];
            j++;
            start++;
        }
        cd[i].code[j]='\0';
    }
}
void OutCode()//输出哈夫曼树的各节点编码
{
    int i;
    cout<<"已建好的哈夫曼树各结点编码为:"<<endl;
    for(i=0;i<size;i++)
        cout<<cd[i].data<<"--->"<<cd[i].code<<endl;
}
void Decode(char code[])//解码操作
{
    int i=0;
    int j=2*(size-1); //从根开始
    char dec[MAX]; //暂存已解出的字符
    int k=0;
    while(code[i]!='\0')
    {
        if(code[i]=='0')
            j=tree[j].lchild;
        else
            j=tree[j].rchild;
        if(tree[j].lchild==-1)
        {
            dec[k++]=cd[j].data;
            j=2*(size-1);
        }
        i++;
    }
    dec[k]='\0';
    //密码串读完时,若没同时达到叶子(未重新回到根),则密码串有误
    if(j!=2*(size-1)&&tree[j].lchild!=-1)
        cout<<"此密码串无解!";
    else
        cout<<dec;
    cout<<endl;
}

void main()
{
    huffinit info[MAX];
    int i,n;
    cin>>n;
    for(i=0;i<n;i++)
    {
        cin>>info[i].data;
        cin>>info[i].weight;
    }
    HuffTree(info,n);
    Output();//节点信息
    cout<<endl;
    Encode();//进行编码
    OutCode();//已建好的哈夫曼树的结点编码信息
    cout<<endl;
    char flag='Y';
    do{
        cout<<"请输入密码:";
        char code[30];
        cin>>code;
        cout<<"解码结果为:";
        Decode(code);//进行解码
        cout<<endl;
        cout<<"还继续解码吗?(Y/N)";
        cin>>flag;
    }while(flag=='Y'||flag=='y');
}

你可能感兴趣的:(哈夫曼编码)