哈夫曼编码及解码

这是一个使用C++实现的哈夫曼编码和解码程序。程序接收输入的权值和字符,构造哈夫曼树,生成哈夫曼编码,并进行编码与解码操作。用户可以输入多个数据集进行测试。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

#include<iostream>
#include<string>
#include<cstring>
using namespace std;
const int MaxW=9999;
class HuffNode
{
public:
    int weight;
char name;
    int parent;
    int lchild;
    int rchild;
};
class HuffMan
{
private:
    void MakeTree()
    {
        int i,s1,s2;
        for(i=lnum+1;i<=len;i++)
        {
            SelectMin(i-1,&s1,&s2);//找出权值最小的两个节点
            huffTree[s1].parent=i;//权值最小的两个节点的父节点从n+1开始
            huffTree[s2].parent=i;
            huffTree[i].lchild=s1;//父节点左右孩子分别是这两个最小的权值的指针值
            huffTree[i].rchild=s2;
            huffTree[i].weight=huffTree[s1].weight+huffTree[s2].weight;//父节点的权值是这两个最小的节点的权值之和
        }
    }
    void SelectMin(int pos,int *s1,int *s2)//找出最小权值的的两个节点,并把他们的指针值赋给s1,s2
    {
        int w1,w2,i;
        w1=MaxW;w2=MaxW;
        *s1=0;*s2=0;
        for(i=1;i<=pos;i++)
        {
            if(huffTree[i].weight<w1 && huffTree[i].parent==0)//w1比w2小,所以出现有比w1小的权值时,s1的指针值赋给s2,w1的权值赋给w2
            {                         //一定要注意父节点的值为0是条件,是为了排除已经找出的最小权值的节点重新进行排序
                *s2=*s1;w2=w1;
                *s1=i;
w1=huffTree[i].weight;//然后将该指针值赋给s1,并把权值赋给w1
            }
            else if(huffTree[i].weight<w2 && huffTree[i].parent==0)//出现比w1大比w2小的权值时,直接将该指针值赋给s2,并把权值赋给w2
            {
                *s2=i;
                w2=huffTree[i].weight;
            }
        }
    }
public:
    int len;
    int lnum;
    HuffNode *huffTree;
    string *huffCode;//存放编码的string指针
    void MakeTree(int n,int wt[],char name[])//传入叶子节点的数量,权值,和名字
    {
        int i;
        lnum=n;
len=2*n-1;//节点的数量是2*n-1
        huffTree = new HuffNode[2*n];//给结构体指针huffTree分配大小为2*n大小的空间
        huffCode = new string[lnum+1];//给哈夫曼的编码string指针分配n+1de大小空间
        for(i=1;i<=n;i++)//注意是下标是从1开始的
{
            huffTree[i].weight=wt[i-1];//初始化叶子结点的权值和名字
huffTree[i].name=name[i-1];
}
        for(i=1;i<=len;i++)
        {
            if(i>n) huffTree[i].weight=0;//初始化化其他节点的权值为0
            huffTree[i].parent=0;//初始化所有节点的父节点,左右孩子的指针值为0
            huffTree[i].lchild=0;
            huffTree[i].rchild=0;
        }
        MakeTree();//初始化其他节点的父节点,左右孩子,和权值
    }
    void Coding()
    {
        char *cd;
        int i,c,f,start;
        cd=new char[lnum];//存放编码的字符数组
        cd[lnum-1]='\0';
        for(i=1;i<=lnum;++i)
        {
            start=lnum-1;//c是自节点,f是父节点,循环就是子节点变为父节点,父节点变为父节点的父节点,依次类推
            for(c=i,f=huffTree[i].parent;f!=0;c=f,f=huffTree[f].parent)//先依次找到叶子节点的父节点,然后再判断是父节点的左孩子,还是右孩子
                if(huffTree[f].lchild==c) cd[--start]='0';//直到节点的父节点为0
                else cd[--start]='1';
            huffCode[i].assign(&cd[start]);//将字符编码存放到字符编码的指针
        }
        delete []cd;
    }  
void display(char str[])
{
int len=strlen(str);
for(int i=0;i<len;i++)
{
for(int j=0;j<=lnum;j++)
{
if(str[i]==huffTree[j].name)
cout<<huffCode[j];
}
}
cout<<endl;
}
int Decode(const string codestr,char txtstr[])
    {
        int i,k,c;
        char ch;
        c=len;//从最大的父节点开始
        k=0;
        for(i=0;i<codestr.length();i++)
        {
            ch=codestr[i];
            if(ch=='0') c=huffTree[c].lchild;//如果是0的话,子节点变为当前节点的左节点
            if(ch=='1') c=huffTree[c].rchild;//如果是1的话,子节点变为当前节点的右节点
            if(ch!='0'&&ch!='1') return -1;
            if(huffTree[c].lchild==0 && huffTree[c].rchild==0)//当找到叶子节点时候
            {
                txtstr[k]=huffTree[c].name;//将叶子节点的名字赋给解编码的数组
                k++;
                c=len;//每次找到一个叶子节点,都要回到最大的父节点
            }
            else ch='\0';
        }
        if(ch=='\0') return -1;
        else txtstr[k]='\0';
        return 1;
    }




    void Destroy()
    {
        len=0;
        lnum=0;
        delete []huffTree;
        delete []huffCode;
    }
};
int main()
{
    int t,n,i,j;
char name[100];
    int wt[800];
    string str;
char Name[1000];
    HuffMan myHuff,myHuff1;
    cin>>t;
    for(i=0;i<t;i++)
    {
        cin>>n;
for(j=0;j<n;j++)
cin>>name[j];
  for(j=0;j<n;j++)
            cin>>wt[j];
        myHuff.MakeTree(n,wt,name);
        myHuff.Coding();
cin>>Name;
cin>>str;
            char ch[800];
            int m=myHuff.Decode(str,ch);
        for(j=1;j<=n;j++)
        {
            cout<<myHuff.huffTree[j].name<<" :";
            cout<<myHuff.huffCode[j]<<endl;
        }
 myHuff.display(Name);
        if(m==-1) cout<<"error!"<<endl;
            if(m==1) cout<<ch<<endl;
        myHuff.Destroy();
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值