哈夫曼编码及其解码

混江龙づ霸主 提交于 2019-12-04 04:14:54

添加注释版本:

/*
cout<<i<<endl<<" 结点 | data | weight | lchild | rchild | parent "<<endl; 
for(int i=1;i<=m;++i)
{
    cout<<i<<" | "<<HT[i].data<<" | "<<HT[i].weight<<" | "<<HT[i].lchild<<" | "<<HT[i].rchild<<" | "<<HT[i].parent<<endl;
}
*/
#include<iostream>
#include<stdio.h>
#include<string>
#include<cstring>
#include<algorithm>
#define MAX 0x3f3f3f3f 
using namespace std;

typedef struct
{
    char data;
    int weight;
    int parent;
    int lchild;
    int rchild;
    bool tag;
}Huffnode,*HuffmanTree;
typedef struct
{
    string *code;//存放字符的编码 
    char *data;//存放字符 
    int num;//存放一共有多少字符 
}HuffmanCode;
void DisplayHuffmanCode(HuffmanCode &HC,int n)
{
    for(int i=0;i<n;++i)
    {
        cout<<HC.code[i]<<endl;
    }
}
void Select(HuffmanTree &HT,int index, int &s1, int &s2)
{
    int min1=MAX;
    int min2=MAX;
    for(int i=1;i<=index;++i)
    {
        if(HT[i].parent==0&&HT[i].tag)
        {
            if(HT[i].weight<min1)
            {
                s1=i;
                min1=HT[i].weight;
            }
        }
    }
    HT[s1].tag=0;//表明此节点已经被选中过 
    for(int i=1;i<=index;++i)
    {
        if(HT[i].parent==0&&HT[i].tag)
        {
            if(HT[i].weight<min2)
            {
                s2=i;
                min2=HT[i].weight;
            }
        }
    }
    HT[s2].tag=0; 
}
void CreatHuffmanTree(HuffmanTree &HT,int n)
{
    /*n:待编码数有多少*/
    if(n<=1)return;
    int m=2*n-1; //计算节点个数
    HT=new Huffnode[m+1];//0号单元未用,HT[m]表示根结点,从1开始存放数据 
    //初始化哈夫曼表
    for(int i=1;i<=m;++i)
    {
        HT[i].lchild=0;
        HT[i].rchild=0;
        HT[i].parent=0;
        HT[i].tag=1;
        HT[i].data='\0';
    }
    //依次输入待编码的数据的权重 
    cout<<"请依次输入每一个字和它的权重:"<<endl;
    for(int i=1;i<=n;++i)
    {
        scanf("%c",&HT[i].data);
        getchar();
        scanf("%d",&HT[i].weight);
        getchar();
//        cin>>HT[i].data>>HT[i].weight;
    }
     //构造  Huffman树
    int s1,s2;
    for(int i=n+1;i<=m;++i)      
    {
        Select(HT,i-1,s1,s2);
        //在已经有数据的哈夫曼节点中,选择两个双亲域为0,且权值最小的结点
        //并返回它们在HT中的序号s1和s2
        HT[s1].parent=i;
        HT[s2].parent=i;  
         //表示从F中删除s1,s2
        HT[i].lchild=s1;    
        HT[i].rchild=s2; 
         //s1,s2分别作为i的左右孩子
        HT[i].weight=HT[s1].weight + HT[s2].weight;
         //i 的权值为左右孩子权值之和
    }
    cout<<" 结点 | data | weight | lchild | rchild | parent "<<endl; 
    for(int i=1;i<=m;++i)
    {
        cout<<i<<" | "<<HT[i].data<<" | "<<HT[i].weight<<" | "<<HT[i].lchild<<" | "<<HT[i].rchild<<" | "<<HT[i].parent<<endl;
    }
}
//根据创建的哈夫曼树,从叶子到根逆向求每个字符的赫夫曼编码,存储在编码表HC中
void CreatHuffmanCode(HuffmanTree HT, HuffmanCode &HC, int n)
{
    /*n:代表编码个数*/
    HC.code=new string[n+1];                 //分配n个指向字符串的指针
    HC.data=new char[n+1];
    HC.num=n+1;//从1开始存 
     
    for(int i=1; i<=n; ++i)
    {    //逐个字符求赫夫曼编码
        int c=i; //哈夫曼表的下标
        int f=HT[i].parent;
        string cd="";
        while(f!=0)
        {    //从叶子结点开始向上回溯,直到根结点
             if (HT[f].lchild==c)  
             {
                 cd+="0";    //结点c是f的左孩子,则生成代码0
             }
             else 
             {
                 cd+="1"; //结点c是f的右孩子,则生成代码1
             }
             c=f; //跟新孩子,找上一代
             f=HT[f].parent;                     //继续向上回溯
        }     
        reverse(cd.begin(),cd.end());
        HC.code[i]=cd;   //将求得的编码从临时空间cd复制到HC的当前行中
//        cout<<cd<<endl; 
      }
      cout<<"当前的哈夫曼编码表为:"<<endl;
      for(int i=1;i<=n;++i)
      {
          HC.data[i]=HT[i].data;
          cout<<i<<" | "<<HC.data[i]<<" | "<<HC.code[i]<<endl;
          
      }
} 
void Encoding(HuffmanCode HC,string str)
{
    cout<<"编码结果为:"<<endl; 
    for(int i=0;i<str.length();++i)
    {
        for(int j=1;j<=HC.num;++j)
        {
//            cout<<"\nHC.data[j]==str[i]"<<HC.data[j]<<" "<<str[i]<<endl; 
            if(HC.data[j]==str[i])
            {
                cout<<HC.code[j];
                break; 
            }
        }
        
     } 
}
void Decoding(HuffmanCode HC,string str)
{
    cout<<"解码结果为:"<<endl; 
    string temp="";
    int postion=0;
    for(int i=0;i<str.length();)
    {
        for(int j=1;j<=HC.num;++j)
        {
            int k=0;
//            cout<<"\n当前查找的是:"<<HC.code[j]; 
            for(;k<HC.code[j].length();++k)
            {
//                cout<<" HC.code[j][k]!=str[i] "<<HC.code[j][k]<<","<<str[i+k]; 
                if(HC.code[j][k]!=str[i+k])
                {
                    break;
                }
            }
//            cout<<" k="<<k<<endl;
            if(k==HC.code[j].length())
            {
                i+=HC.code[j].length();
                cout<<HC.data[j];
                break;
            }
        }
     } 
}
int main()
{
    HuffmanTree HT;
    HuffmanCode HC;
    //构造赫夫曼树,输出各字符的赫夫曼编码
    cout<<"\n请输入编码的个数:"<<endl;
    int n=0;
    cin>>n; 
    getchar();
    CreatHuffmanTree(HT,n);
    CreatHuffmanCode(HT,HC,n);
    //     编码:输入字符序列,输出对应的赫码序列。
    cout<<"\n请输入要编码的字符:"<<endl;
    string e_str="";
    getline(cin,e_str);
    Encoding(HC,e_str);
//    cout<<e_str<<endl;
    // 译码:输入赫夫曼码序列,输出原始字符代码。
    cout<<"\n请输入要解码的字符:"<<endl;
    string d_str="";
    getline(cin,d_str);
    Decoding(HC,d_str);
     
}
View Code

未加注释清爽版:

#include<iostream>
#include<stdio.h>
#include<string>
#include<cstring>
#include<algorithm>
#define MAX 0x3f3f3f3f 
using namespace std;

typedef struct
{
	char data;
	int weight;
	int parent;
	int lchild;
	int rchild;
	bool tag;
}Huffnode,*HuffmanTree;
typedef struct
{
	string *code;
	char *data;
	int num;
}HuffmanCode;
void DisplayHuffmanCode(HuffmanCode &HC,int n)
{
	for(int i=0;i<n;++i)
	{
		cout<<HC.code[i]<<endl;
	}
}
void Select(HuffmanTree &HT,int index, int &s1, int &s2)
{
	int min1=MAX;
	int min2=MAX;
	for(int i=1;i<=index;++i)
	{
		if(HT[i].parent==0&&HT[i].tag)
		{
			if(HT[i].weight<min1)
			{
				s1=i;
				min1=HT[i].weight;
			}
		}
	}
	HT[s1].tag=0;
	for(int i=1;i<=index;++i)
	{
		if(HT[i].parent==0&&HT[i].tag)
		{
			if(HT[i].weight<min2)
			{
				s2=i;
				min2=HT[i].weight;
			}
		}
	}
	HT[s2].tag=0; 
}
void CreatHuffmanTree(HuffmanTree &HT,int n)
{
	if(n<=1)return;
	int m=2*n-1;
	HT=new Huffnode[m+1];

	for(int i=1;i<=m;++i)
	{
		HT[i].lchild=0;
		HT[i].rchild=0;
		HT[i].parent=0;
		HT[i].tag=1;
		HT[i].data='\0';
	}
	cout<<"请依次输入每一个字和它的权重:"<<endl;
	for(int i=1;i<=n;++i)
	{
		scanf("%c",&HT[i].data);
		getchar();
		scanf("%d",&HT[i].weight);
		getchar();
	}

	int s1,s2;
	for(int i=n+1;i<=m;++i)      
	{
		Select(HT,i-1,s1,s2);
	    HT[s1].parent=i;
		HT[s2].parent=i;  
	    HT[i].lchild=s1;    
		HT[i].rchild=s2; 
	    HT[i].weight=HT[s1].weight + HT[s2].weight;
	}
}
void CreatHuffmanCode(HuffmanTree HT, HuffmanCode &HC, int n)
{

	HC.code=new string[n+1];
	HC.data=new char[n+1];
	HC.num=n+1;
	 
	for(int i=1; i<=n; ++i)
	{
		int c=i; 
		int f=HT[i].parent;
		string cd="";
		while(f!=0)
		{
			 if (HT[f].lchild==c)  
			 {
				 cd+="0";
			 }
			 else 
			 {
				 cd+="1";
			 }
			 c=f;
			 f=HT[f].parent;
		}     
		reverse(cd.begin(),cd.end());
		HC.code[i]=cd;
	  }
	  cout<<"当前的哈夫曼编码表为:"<<endl;
	  for(int i=1;i<=n;++i)
	  {
	  	HC.data[i]=HT[i].data;
	  	cout<<i<<" | "<<HC.data[i]<<" | "<<HC.code[i]<<endl;
	  	
	  }
} 
void Encoding(HuffmanCode HC,string str)
{
	cout<<"编码结果为:"<<endl; 
	for(int i=0;i<str.length();++i)
	{
		for(int j=1;j<=HC.num;++j)
		{
			if(HC.data[j]==str[i])
			{
				cout<<HC.code[j];
				break; 
			}
		}
		
	 } 
}
void Decoding(HuffmanCode HC,string str)
{
	cout<<"解码结果为:"<<endl; 
	string temp="";
	int postion=0;
	for(int i=0;i<str.length();)
	{
		for(int j=1;j<=HC.num;++j)
		{
			int k=0;
			for(;k<HC.code[j].length();++k)
			{
				if(HC.code[j][k]!=str[i+k])
				{
					break;
				}
			}
			if(k==HC.code[j].length())
			{
				i+=HC.code[j].length();
				cout<<HC.data[j];
				break;
			}
		}
	 } 
}
int main()
{
	HuffmanTree HT;
	HuffmanCode HC;
	//构造赫夫曼树,输出各字符的赫夫曼编码
	cout<<"\n请输入编码的个数:"<<endl;
	int n=0;
	cin>>n; 
	getchar();
	CreatHuffmanTree(HT,n);
	CreatHuffmanCode(HT,HC,n);
	// 编码:输入字符序列,输出对应的赫码序列。
	cout<<"\n请输入要编码的字符:"<<endl;
	string e_str="";
    getline(cin,e_str);
	Encoding(HC,e_str);
	// 译码:输入赫夫曼码序列,输出原始字符代码。
	cout<<"\n请输入要解码的字符:"<<endl;
	string d_str="";
	getline(cin,d_str);
	Decoding(HC,d_str);
	 
}

测试样例:

输入:

27

输入:

 
186
a
64
b
13
c
22
d
32
e
103
f
21
g
15
h
47
i
57
j
1
k
5
l
32
m
20
n
56
o
63
P
15
q
1
r
48
s
51
t
80
u
23
v
8
w
18
x
1
y
16
z
1
View Code

输入:

you are bad gay but laolao is not

输入:

1000111001000011111010001001011110000010101011011110000110101000111111000000000111011111011110101001101111010100111101110011111011010011101

输出:

 

 

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!