基于哈夫曼树的数据压缩算法

Posted ଳxin

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了基于哈夫曼树的数据压缩算法相关的知识,希望对你有一定的参考价值。

题目描述

输入一串字符串,根据给定的字符串中字符出现的频率建立相应哈夫曼树,构造哈夫曼编码表,在此基础上可以对待压缩文件进行压缩(即编码),同时可以对压缩后的二进制编码文件进行解压(即译码)。

输入:

多组数据,每组数据一行,为一个字符串(只考虑26个小写字母即可)。当输入字符串为“0”时,输入结束。

输出:

每组数据输出4行:
第一行为统计出来的字符出现频率(只输出存在的字符,格式为:字符:频度),每两组字符之间用一个空格分隔,字符按照ASCII码从小到大的顺序排列。
第2行为每个字符的哈夫曼编码(只输出存在的字符,格式为:字符:编码),每两组字符之间用一个空格分隔,字符按照ASCII码从小到大的顺序排列。
第3行为编码后的字符串
第4行为解码后的字符串(应该与输入的字符串相同)。
样例输入 Copy:

aaaaaaabbbbbccdddd
aabccc
0

样例输出 Copy

a:7 b:5 c:2 d:4
a:0 b:10 c:110 d:111
00000001010101010110110111111111111
aaaaaaabbbbbccdddd
a:2 b:1 c:3
a:11 b:10 c:0
111110000
aabccc

具体代码:

#include<iostream>
#include<cstring>
using namespace std;
#define MAX 500
int coun[26]; //频率 
char saveletter[26];//存字母 
char temp[MAX];//暂存被译码串 

typedef struct htnode

	int weight;
	int lchild,rchild,parent; 
	char data; 
	int frequency;//出现频率 
*huftree;

typedef char **hufcode;

void select(huftree &hf,int x,int &s1,int &s2)//在叶子结点里找最小的两个 

	int min=999,cmin=999;//最小值和次小值 
	int i=1;
	while(i<=x)
	
		if(hf[i].parent==0)
		
			if(hf[i].weight<min)//寻找权值最小 
			
				min=hf[i].weight;
				s1=i;
			
			i++;			
		
		else
			i++;		
	 
	int flag=s1;
	i=1;
	while(i<=x)
	
		if(hf[i].parent==0)
		
			if((hf[i].weight>min && hf[i].weight<cmin) || (hf[i].weight==min &&flag!=i) )//找次小值 
			
				cmin=hf[i].weight;
				s2=i;
			
			i++;					
		
		else
			i++;		
	 
	


void Create(huftree &hf,int n)//叶子为n的哈树有2n-1个结点 

	int m=2*n-1,s1=0,s2=0;
	
	if(n<=1) return;

	hf=new htnode[m+1];//0号单元不用
	
	for(int i=1;i<=m;i++)//都初始化为0 
	
		hf[i].parent=0;
		hf[i].rchild=0;
		hf[i].lchild=0;
		hf[i].data=saveletter[i-1];//字母
	
	
	for(int i=1;i<=n;i++)
		hf[i].weight=coun[i-1];//输入权值 
		
	for(int i=n+1;i<=m;i++)//前n个为叶子,后面需要构建 
	
		select(hf,i-1,s1,s2);//选择最小的两个节点,返回序号 
		hf[s1].parent=i;
		hf[s2].parent=i;//结点双亲变为i
		hf[i].lchild=s1;
		hf[i].rchild=s2;//i的左右孩子
		hf[i].weight=hf[s1].weight+hf[s2].weight;
		//i权值更改 
	 
	


void count(char str[],huftree &hf,int &n)//出现频率 ,字母个数 

	int i=0,j=0;
	int num[26];
	char ch;
	memset(num,0,sizeof(num));
	
	while(str[i]!='\\0')
	
		j=str[i]-97;
		num[j]++;
		i++;
	
	j=0;
	for(i=0;i<26;i++)
	
		if(num[i]!=0)
			
			saveletter[j]=char(i+97);
			coun[j]=num[i]; 
			j++;
			
	
	n=j;
	for(int i=0;i<n;i++)
	
		if(i==n-1)
			cout<<saveletter[i]<<":"<<coun[i];
		else
			cout<<saveletter[i]<<":"<<coun[i]<<" ";
	
	cout<<endl;



void hfcode(huftree &hf,hufcode &hc,int n)
 
	int start=0,c,f; 
	char *cd;
	
	hc=new char*[n+1];//编码表 
	cd=new char[n];//每个字符的编码一定小于n 
	cd[n-1]='\\0';
	
	for(int i=1;i<=n;i++)
	
		start=n-1;
		c=i;
		f=hf[i].parent;
		
		while(f!=0)//不是根节点
		
			start--;
			
			if(hf[f].lchild==c)
				cd[start]='0';
			else
				cd[start]='1';
				
			c=f;//向上回溯 
			f=hf[f].parent;
		
		hc[i]=new char[n-start];
		strcpy(hc[i],&cd[start]);//把临时空间的编码复制到编码表中 
	
	delete cd;
	
	int i,j,z=0;
	for(j=1;j<=n;j++)//输出字母编码 
	
		if(j==n)
			cout<<saveletter[j-1]<<":"<<hc[j];
		else
			cout<<saveletter[j-1]<<":"<<hc[j]<<" ";
	
	cout<<endl;
		



void trans_tonum(huftree &hf,hufcode &hc,int n,char str[])

	for(int i=0;str[i]!='\\0';i++)
		for(int j=1;j<=n;j++)
			if(str[i]==saveletter[j-1])
			
				cout<<hc[j];
				strcat(temp,hc[j]);
				
				
	cout<<endl;
	


void trans_toletter(huftree &hf,hufcode &hc,int n)

	int i=2*n-1;
	int j=0;
	
    while(temp[j]!='\\0')
	    
		if(temp[j]=='0')
			i=hf[i].lchild;   //左孩子
		else if(temp[j]=='1')
			i=hf[i].rchild;    //右孩子
		if(hf[i].lchild==0)
		   
       		cout<<hf[i].data;
        	i=2*n-1;
      	
		j++;   //无论是否找到叶子节点都读取下一个编码串字符
   
   cout<<endl;


int main()

	
	while(1)
	
		huftree hf;
		hufcode hc;
		int n;
		char str[MAX];

		gets(str);
		if(str[0]=='0')
			break;
		
		count(str,hf,n); 
		Create(hf,n);
		hfcode(hf,hc,n);
		trans_tonum(hf,hc,n,str);
		trans_toletter(hf,hc,n);	
		
		memset(coun,0,sizeof(coun));
		memset(saveletter,'\\0',sizeof(saveletter)); 
		memset(temp,'\\0',sizeof(temp));
		
		delete hf;
		delete hc;	
	
	return 0;

以上是关于基于哈夫曼树的数据压缩算法的主要内容,如果未能解决你的问题,请参考以下文章

霍夫曼树和霍夫曼编码以及霍夫曼编码的应用

文件压缩——哈夫曼树编码

Hufffman算法

哈夫曼编码译码器 java

Elasticsearch之数据压缩算法

赫夫曼树的构建编码译码解析