树的应用——哈夫曼编码(C语言版)

利用哈夫曼编码进行通信可以大大提高信道的利用率,缩短信息传输的时间,降低传输成本。根据哈夫曼编码的原理,编写一个程序,在用户输入结点权值的基础上求哈夫曼编码。
从键盘输入若干字符及每个字符出现的频率,将字符出现的频率作为结点的权值,建立哈夫曼树,求出各字符的哈夫曼编码。要求:
1.输出存放哈夫曼树的数组HT的初态和终态;
2.输出每个字符的哈夫曼编码;
3.输入一个字符串,对字符串进行编码并输出;
4.(选作)输入一串以哈夫曼编码方式编码的二进制码,进行译码并输出。

运行截图如下,输入结点的个数和每个结点的字符和频率,然后回车即可得出Huffman树和每个结点的Huffman编码。
在这里插入图片描述

首先建立Huffman树的数据结构如下:

typedef struct Huffman {
	int weight;
	int lchild,rchild,parent;
}Huffman,*HTree;

完整代码如下(相关代码都有注释说明,就不做详细解释了):

#include<iostream>
#include<string.h>
#define OK 1
#define ERROR 0
typedef int Status;
using namespace std;
//#include"header.h"
typedef char **CTree;
typedef struct Huffman {
	int weight;
	int lchild,rchild,parent;
}Huffman,*HTree;
//构造哈夫曼树
//重载复制函数(将s2的从第n个字符开始复制到s1中去)
void strcpy(char *s1,char *s2,int n){
	int len2=strlen(s2);
	for(int i=0;i<=len2;i++){
		s1[i]=s2[i+n];
	}
}
//在HT中选择最小的结点
void  select(HTree &HT,int n,int &s1,int &s2){
	int m1=32767,m2=32767;
	s1=0;s2=0;
	for(int k=1;k<=n;k++){
		if((HT[k].parent==0)&&(HT[k].weight<m1)){
			m2=m1;
			s2=s1;
			m1=HT[k].weight;
			s1=k;
		}else if((HT[k].parent==0)&&(HT[k].weight<m2)){
			m2=HT[k].weight;
			s2=k;
		}
	}
	
}
//构造哈夫曼编码
void createHuffmanCode(HTree HT,CTree &CT,int n){
	CT=new char*[n+1];//应是char*,不是*char,因为声明指针类型的时候就是char* 
	char *temp=new char[n];//临时数组 
	int s,tp,tc;
	temp[n-1]='\0';
	for(int i=1;i<=n;i++){
		tp=HT[i].parent;
		tc=i;
		s=n-1;
		while(tp){
			if(HT[tp].lchild==tc)
				temp[--s]='0';
			else
				temp[--s]='1';
			tc=tp;
			tp=HT[tp].parent;
		}
		CT[i]=new char[n-s];
		strcpy(CT[i],temp,s);
	}
	delete temp;
}
Status createHuffmanTree(HTree &HT,int n,char *&str){
	int num,i;
	int s1,s2;
	if(n<=1)
		return ERROR;
	num=2*n-1;
	HT=new Huffman[num+1];//0号单元未用
	str=new char[num+1];//同样0号单元未用 
	for(i=1;i<=num;i++){
		HT[i].parent=0;
		HT[i].lchild=0;
		HT[i].rchild=0;
	}
	cout<<"输入结点(字符)和结点的权值(频率):\n";
	for(i=1;i<=n;i++){
		getchar();
		scanf("%c%d",&str[i],&HT[i].weight) ;
	}
	cout<<"------------HT的初态-------------\n";
	cout<<"结点i\tweight\tparent\tlchild\trchild\n";
	for(i=1;i<=num;i++){
		cout<<i<<"\t";
		if(i<=n) 
			cout<<HT[i].weight<<"\t";
		else
			cout<<0<<"\t";
		cout<<0<<"\t"<<HT[i].lchild<<"\t"<<HT[i].rchild<<endl;
	}
	//----开始创建
	for(i=n+1;i<=num;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;
	}
	cout<<"------------HT的终态-------------\n";
	cout<<"结点i\tweight\tparent\tlchild\trchild\n";
	for(i=1;i<=num;i++)
		cout<<i<<"\t"<<HT[i].weight<<"\t"<<HT[i].parent<<"\t"<<HT[i].lchild<<"\t"<<HT[i].rchild<<endl;
	return OK;
}
int main(){
	HTree HT;
	CTree CT;
	int num;
	char *str=NULL;
	cout<<"输入结点的个数:";
	cin>>num;
	createHuffmanTree(HT,num,str);
	createHuffmanCode(HT,CT,num);
	cout<<"每个结点的哈夫曼编码:\n";
	for(int i=1;i<=num;i++)
		cout<<str[i]<<":"<<CT[i]<<endl;
	system("pause");
	return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qzxl

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值