⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 hufftree.cpp

📁 哈夫曼编码、译码程序
💻 CPP
字号:
#include <iostream.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <conio.h>
#define MAXNUM 27

class HuffNode
{
public:
	char data;
	int weight;
	int father;
	int lc;
	int rc;
};
class HuffNodeCode
{
public:
	char data;
	char code[MAXNUM];
};
int Selete2Small(HuffNode *htree,int k,int *s1,int *s2);
int HufftreeCreate(HuffNode *htree,int n)
{
	int s1,s2,i;
	s1=s2=0;
	for(i=n+1;i<2*n;i++)
	{//选择两个父为0,权最小的树的下标
		Selete2Small(htree,i-1,&s1,&s2);
		htree[i].data=NULL;
	//置新父节点权值
		htree[i].weight=htree[s1].weight+htree[s2].weight;
	//置根无父
		htree[i].father=0;
	//置儿子指示	
		htree[i].lc=s1;
		htree[i].rc=s2;
		htree[s1].father=i;
		htree[s2].father=i;
	}
return 0;
};

int Selete2Small(HuffNode *htree,int k,int *s1,int *s2)
{
	int i,j;
	if (k<2) return -1;
	*s1=0;*s2=0;
	//令s1,s2分别指向htree中最前面的两个无父节点元素
	
	for (j=1;j<=k;j++)
	{
		if(htree[j].father!=0) continue;
		if(*s1==0) *s1=j;
		else {*s2=j;break;}
	}
	if(*s1==0||*s2==0) return -1;//表示htree中只有一棵树
	if(htree[*s1].weight>htree[*s2].weight)
	{
		i=*s1;*s1=*s2;*s2=i;}
	for(i=j+1;i<=k;i++) //j从上段程序的值开始
	{
		if(htree[i].father!=0) continue;
		if(htree[i].weight<htree[*s1].weight)
		{
			*s2=*s1;
			*s1=i;
		}
		else
			if(htree[i].weight<htree[*s2].weight) *s2=i;
	}
	return 0;
}
//列表输出哈夫曼树
void PrintHtree(HuffNode *htree,int n)
{
	cout<<"\n输出哈夫曼树结构:"<<endl;
	cout<<"序号"<<"  "<<"节点数据"<<"  "<<"权重"<<"  "<<"父亲节点"<<"  "<<"左孩子"<<"  "<<"右孩子"<<endl;
	for(int i=1;i<=2*n-1;i++)
	{
		cout<<i<<"\t"<<htree[i].data<<"\t"<<htree[i].weight<<"\t"<<htree[i].father<<"\t"<<htree[i].lc<<"\t"<<htree[i].rc<<endl;
	}
}
//哈夫曼树编码
void HufftreeCode(HuffNode *htree,int n,HuffNodeCode *pcode)
{
	int i,j,k,m;
	HuffNode *curr;
	for(i=1;i<=n;i++)
	{
		curr=&htree[i];
		j=MAXNUM-1;
		k=i;
		pcode[i].data=htree[i].data;
		do 
		{
			if(n<=1) 
			{
				pcode[i].code[j]='0';
				return;
			}
			m=curr->father;
			curr=&htree[m];
			if(curr->lc==k) 
			{
				pcode[i].code[j]='0';
			}
			else
				if(curr->rc==k)
				{
					pcode[i].code[j]='1';
				}
				k=m;
				j=j-1;
		}while(curr->father!=0);
        if(curr->lc==k) pcode[i].code[j]='0';
		else
			if(curr->rc==k) pcode[i].code[j]='1';	
	}
}
//紧缩编码表
void HuffOrder(HuffNodeCode *htreecode,HuffNodeCode *htreecdout,int n)
{
	int i,j,k,kk;
	for(i=1;i<=n;i++)
	{
		htreecdout[i].data=htreecode[i].data;
	    j=0;
		while((htreecode[i].code[j]==NULL)&&(j<MAXNUM))	{j+=1;}
		kk=0;
		for(k=j;k<MAXNUM;k++)
		{
	    	htreecdout[i].code[kk]=htreecode[i].code[k];
		    kk+=1;
		}
		if(kk<MAXNUM)
		{
			for(k=kk;k<MAXNUM;k++) htreecdout[i].code[k]=NULL;
		}
	}
}
//对输入字符串编码
void StrCodeing(char *str,int n,HuffNodeCode *pcode)
{
	int i,j,k,m,flag;
	k=0;
	m=strlen(str);
	for(i=0;i<m;i++)
	{
		flag=0;
		for(j=1;j<=n;j++)
		{
			if(pcode[j].data==str[i]) 
			{
				cout<<pcode[j].code;
				flag=1;
				break;
			}
		}
		//控制输出
		k+=strlen(pcode[j].code);
		if(k>=50) {k=0;cout<<endl;}
				
	    if(flag==0) 
		{
			cout<<"字符串中含有不能编码的字符!"<<endl;
			exit(1);
		}
	}
}

void PrintCode(HuffNodeCode *htreecdout,int n)
{
	cout<<"输出哈夫曼树编码; "<<endl;
	for(int i=1;i<=n;i++)
	{
		cout<<htreecdout[i].data<<"  :   "<<htreecdout[i].code<<endl;
	}
}

//二进制译码
void StrConcodeing(char *chr,int n,HuffNode *htree)
{
	int i=0,m;
	m=2*n-1;
	while(chr[i]!='\0')
	{
		
		if (chr[i]=='0')
		{
			m=htree[m].lc;
		}
		else if(chr[i]=='1')
		{
			m=htree[m].rc;
		}
	    if(htree[m].lc==0) 
		{
			cout<<htree[m].data;
			m=2*n-1;
		}
		i+=1;
	}
}

//主程序
void main()
{
	int n,i,sele;
    char str1[100];
	char str2[1000];
    char chr[1];
    cout<<"输入字符集大小:";
	cin>>n;
	HuffNode *htree=(HuffNode *) malloc(2*n*sizeof(HuffNode));
	HuffNodeCode *htreecode=(HuffNodeCode *) malloc((n+1)*sizeof(HuffNodeCode));
	HuffNodeCode *htreecdout=(HuffNodeCode *) malloc((n+1)*sizeof(HuffNodeCode));
	//对第htree[0]单元置初值
	htree[0].data=NULL;
	htree[0].father=htree[0].lc=htree[0].rc=htree[0].weight=0;
	for(i=1;i<=n;i++)
	{
		cout<<"\n输入第"<<i<<"个字符:"<<endl;
		gets(chr);
		htree[i].data=chr[0];
		//cin>>htree[i].data;
		cout<<"\n输入字符\""<<chr[0]<<"\"的权值:";
		cin>>htree[i].weight;
		htree[i].father=htree[i].lc=htree[i].rc=0;
	}
	//编码数组初始化
	for(i=1;i<=n;i++)
	{
		for(int j=0;j<MAXNUM;j++)
		{
			htreecode[i].code[j]=NULL;
		}
	}
	//构造哈夫曼树
	HufftreeCreate(htree,n);
	//列表输出哈夫曼树结构
	PrintHtree(htree,n);		
	//哈夫曼树编码
	HufftreeCode(htree,n,htreecode);
	//将编码正序紧缩存入htreecdout中
	HuffOrder(htreecode,htreecdout,n);
	//输出字符编码	
	PrintCode(htreecdout,n);
	while(1)
	{
        cout<<"\n------操作表------"<<endl;	
		cout<<"1   输入字符串,编写二进制码; "<<endl;
		cout<<"2   输入二进制数据,译码输出; "<<endl;
		cout<<"3   退出; "<<endl;		 
		cout<<"请选择操作:"<<endl;
	    cin>>sele;
		switch(sele)
		{
		case 1:
			{
				cout<<"请输入要编码的字符串:"<<endl;
			    gets(str1);
				cout<<"输入的字符串为:"<<str1<<endl;
				//编码
				cout<<"字符串的二进制编码为:"<<endl;
                StrCodeing(str1,n,htreecdout);
				break;
			}
		case 2:
			{	
    			cout<<"请输入要译码的二进制编码:"<<endl;
			    gets(str2);
				cout<<"输入的字符串为:"<<str2<<endl;
				//译码
				cout<<"二进制字符串的原码为:"<<endl;
				StrConcodeing(str2,n,htree);
				break;			
			}
		case 3: exit(1);
		}
	}
}


⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -