huffman编码与解码

#include<iostream>
#include<string>
using namespace std;
struct hufftree
{
    int parent;
    int lchild;
    int rchild;
    int weight;
    string flag;
};
struct lowestnode
{
    char ch;                 //统计各个字符
    int ch_num;              //字符的频率
};
void coding(int length,hufftree tree[],int n,int &a,int &b)
{                            //函数功能:一组数中选择出最小的两个数
    int i;                   
    int r,s;                 
    r=s=length;
    for(i=0;i<n;i++)
    {
        if((tree[i].weight<r)&&(tree[i].parent==-1))
        {                    //"<"而不是"<="代表若最小的数有多个选择前
            r=tree[i].weight;  //面的旧的两个这样避免增加树的层数
            a=i;
        }
    }
    for(i=0;i<n;i++)
    {
        if((tree[i].weight<s)&&(i!=a)&&(tree[i].parent==-1))
        {
            s=tree[i].weight;
            b=i;
        }
    }
}
void sort(lowestnode node[],int n)        //给结构体排序
{
    int i,j;
    for(i=0;i<n;i++)
    {
        for(j=0;j<(n-1);j++)
        {
            if(node[j].ch_num==node[j+1].ch_num)
            {                            //如果频率相同,按字母表排序
                if(node[j].ch>node[j+1].ch)
                {                             //按频率由大到小
                    int temp1;
                    char ch_temp1;
                    temp1=node[j].ch_num;
                    ch_temp1=node[j].ch;
                    node[j].ch_num=node[j+1].ch_num;
                    node[j].ch=node[j+1].ch;
                    node[j+1].ch_num=temp1;
                    node[j+1].ch=ch_temp1;
                }
            }
            if(node[j].ch_num<node[j+1].ch_num)
            {
                int temp;
                char ch_temp;
                temp=node[j].ch_num;
                ch_temp=node[j].ch;
                node[j].ch_num=node[j+1].ch_num;
                node[j].ch=node[j+1].ch;
                node[j+1].ch_num=temp;
                node[j+1].ch=ch_temp;
            }

        }
    }

}
void free(string str)                         //编码函数
{
    int length=str.length();
    lowestnode *node=new lowestnode[length];
    int i,j;
    for(i=0;i<length;i++)
    {
        node[i].ch_num=0;
    }
    int type=0;
    for(i=0;i<length;i++)
    {
        for(j=0;j<type;j++)
        {
            if(str[i]==node[j].ch/*||(node[j].ch>='a'&&node[j].ch<='z'&&str[i]+32==node[j].ch)*/)
            {
                node[j].ch_num++;
                break;
            }
        }
        if(j==type)
        {
           /*if(str[i]>='A'&&str[i]<='Z')
                node[j].ch=str[i]+32;
           else
                */node[j].ch=str[i];
            node[j].ch_num++;
            type++;
        }
    }

    sort(node,type);

    for(i=0;i<type;i++)
        cout<<"字符"<<node[i].ch<<"出现了 "<<node[i].ch_num<<" 次"<<endl;
    hufftree *huff=new hufftree[2*type-1];
    hufftree temp;
    string *code=new string[2*type-1];
    for(i=0;i<2*type-1;i++)
    {
        huff[i].lchild=-1;
        huff[i].rchild=-1;
        huff[i].parent=-1;
        huff[i].flag=-1;
    }
    for(j=0;j<type;j++)
    {
        huff[j].weight=node[j].ch_num;
    }
    int min1,min2;
    for(int k=type;k<2*type-1;k++)
    {
        coding(length,huff,k,min1,min2); //codeing函数选出的数当成
        huff[min1].parent=k;             //孩子结点
        huff[min2].parent=k;
        huff[min1].flag="0";
        huff[min2].flag="1";
        huff[k].lchild=min1;
        huff[k].rchild=min2;
        huff[k].weight=huff[min1].weight+huff[min2].weight;
    }
    for(i=0;i<type;i++)
    {
        temp=huff[i];
        while(1)
        {
            code[i]=temp.flag+code[i];
            temp=huff[temp.parent];
            if(temp.parent==-1)
                break;
        }
    }
    //cout<<"字符串的每个字符huffman编码为:"<<endl;
    //for(i=0;i<type;i++)
      //  cout<<node[i].ch<<" "<<code[i]<<endl;
    cout<<"总共有 "<<type<<" 个字符"<<endl;
    cout<<"整个字符串的huffman编码为:"<<endl;
    for(i=0;i<length;i++)
    {
        for(j=0;j<type;j++)
        {
            if(str[i]==node[j].ch)
                cout<<code[j];
        }
    }
    delete[] node;
    node=NULL;
    delete[] huff;
    huff=NULL;
    delete[] code;
    code=NULL;
}


int main()
{
    char an;
    do
    {
        int ans;
        cout<<"想编码还是解码?";
        cout<<"解码输入 0 编码输入 1 : ";
        cin>>ans;
        if(ans==1)
        {
            string str;
            cin.clear();
            cin.sync();
            cout<<"请输入一个字符串后回车两下:"<<endl;//vc6.0的bug
            getline(cin,str,'\n');
            free(str);
            cout<<endl;
        }                                 
        else if(ans==0)                          //解码主体
        {
            cout<<"请输入字符种类个数(数字):";
            int n,i=0,j=0,m;
            int length=0;
            cin>>n;
            char c[5];
            cout<<"按顺序输入字符(包括空格)和频率:"<<endl;
            lowestnode *yuan=new lowestnode[n];
            for(m=0;m<n;m++)
            {
              cout<<"字符:";
              cin.clear();
              cin.sync();
              cin.getline(c,2);
              yuan[m].ch=c[0];
              cout<<yuan[m].ch<<"的";
              cout<<"频率:";
              cin>>yuan[m].ch_num;
            }
            for(i=0;i<n;i++)
            {
               length=length+yuan[i].ch_num;
            }
            sort(yuan,n);
            hufftree *huff=new hufftree[2*n-1];
            hufftree temp;
            string *code=new string[2*n-1];
            for(i=0;i<2*n-1;i++)
            {
               huff[i].lchild=-1;
               huff[i].rchild=-1;
               huff[i].parent=-1;
               huff[i].flag=-1;
            }
            for(j=0;j<n;j++)
            {
               huff[j].weight=yuan[j].ch_num;
            }
            int min1=0,min2=0;
            for(int k=n;k<2*n-1;k++)
            {
              coding(length,huff,k,min1,min2); 
              huff[min1].parent=k;             
              huff[min2].parent=k;
              huff[min1].flag="0";
              huff[min2].flag="1";
              huff[k].lchild=min1;
              huff[k].rchild=min2;
             huff[k].weight=huff[min1].weight+huff[min2].weight;
            }
            for(i=0;i<n;i++)
            {
                temp=huff[i];
                 while(1)
                 {
                     code[i]=temp.flag+code[i];
                     temp=huff[temp.parent];
                     if(temp.parent==-1)
                      break;
                 }
            }
            //cout<<"字符串的每个字符huffman编码为:"<<endl;
            //for(i=0;i<n;i++)
                //cout<<yuan[i].ch<<" "<<code[i]<<endl;

            cout<<"........................"<<endl;
            string s;
            cout<<"请输入编码:"<<endl;
            cin>>s;
            while(s.length()>(n-1)*length)
            {
                cout<<"输入编码溢出";
                cout<<"请再输入一次编码:"<<endl;
                cin.clear();
                cin.sync();
                cin>>s;
            }
            string *fang=new string[length];

            for(i=0,m=0;m<length;)
            {
                for(j=0;j<code[i].size();j++)
                {
                    if(s[j]!=code[i][j])
                    {
                       i++;
                       if(i==n)
                       {
                          cout<<"输入编码错误";
                          return 0;
                       }
                       break;
                    }
                    else if(j==(code[i].size()-1))
                    {
                        fang[m]=yuan[i].ch;
                        s=s.erase(0,j+1);
                        i=0,m++;
                        break;
                    }
                }
            }
            for(i=0;i<length;i++)
            {
                cout<<fang[i];
            }
            cout<<endl;
            delete[] yuan;
            yuan=NULL;
            delete[] huff;
            huff=NULL;
            delete[] code;
            code=NULL;
            delete[] fang;
            fang=NULL;
        }
        cout<<"输入 y or Y 继续:";
        cin>>an;
    }while(an=='y'||an=='Y');
    return 0;
}

可包括空格的字符串编码,解码需要输入字符个数和权重。不过程序过于繁琐,还能优化。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值