数据结构第六次上机试验——哈夫曼编码算法的实现

实验目的:

(1) 掌握二叉树的定义;

(2) 掌握哈夫曼树和哈夫曼编码算法的实现。     

实验内容:

实现一个哈夫曼编码系统,系统包括以下功能:

(1) 字符信息统计:读取待编码的源文件SourceFile.txt,统计出现的字符及其频率。

附:SourceFile.txt文件内容为

AAAAABBBBBBBBBBBBBBBBBBBBBBBBBCCCCCCCDDDDDDDDEEEEEEEEEEEEEEFFFFFFFFFFFFFFFFFFFFFGGGHHHHHHHHHHH

(2) 建立哈夫曼树:根据统计结果建立哈夫曼树。

(3) 建立哈夫曼码表:利用得到的哈夫曼树,将各字符对应的编码表保存在文件Code.txt中。

(4) 对源文件进行编码:根据哈夫曼码表,将SourceFile.txt中的字符转换成相应的编码文件ResultFile.txt。

实现提示:

(1) 字符信息统计:假设源文件SourceFile.txt中的字符只有大小写英文字母(同一个字母的大小写看作一个字符),则字符统计算法的实现过程可以归纳为:先定义一个含有26个元素的整形数组,用来存储各个字母出现的次数,最后还要排除其中出现次数为0的数组元素。

(2) 建立哈夫曼树:参考教材算法5.10,补充函数Select的实现。

(3) 建立哈夫曼码表:参考教材算法5.11,将编译表HC中的内容写到文件Code.txt中。

(4) 对源文件进行编码:依次读入文件SourceFile.txt中的字符 c,在编码表 HC 中找到此字符,将字符c转换为编码表中存放的编码串,写入编码文件ResultFile.txt中,直到所有的字符处理完毕为止。

#include<iostream>
#include<cstring>
#include<cstdio>
#include<fstream>
#include<iostream>
using namespace std;
typedef struct{
	int weight;
	int parent,lchild,rchild;
}HTNode,*HuffmanTree;
typedef char **HuffmanCode; 
int a[24+1],b[24+1];
char c[24+1];
void Select(HuffmanTree &HT,int n,int &s1,int &s2){
	for(int i=1;i<=n;i++)
		if(HT[i].parent==0&&s1==0) {s1=i;break;} 
	for(int i=1;i<=n;i++)	
		if(HT[i].parent==0&&HT[i].weight<HT[s1].weight) s1=i;
	for(int i=1;i<=n;i++)
		if(HT[i].parent==0&&s2==0&&i!=s1) {s2=i;break;}
	for(int i=1;i<=n;i++)
		if(HT[i].parent==0&&HT[i].weight<HT[s2].weight&&i!=s1) s2=i;
}
void CreateHuffmanTree(HuffmanTree &HT,int n){
	if(n<=1) return;
	int m=2*n-1;//构造一棵哈夫曼树所需要的所有节点数 
	HT=new HTNode[m+1];//m+1指从第一个结点开始,第0个结点不用 
	for(int i=1;i<=m;i++){
		HT[i].parent=0;
		HT[i].lchild=0;
		HT[i].rchild=0;
	}
	for(int i=1;i<=n;i++) HT[i].weight=b[i];//把字母出现的次数赋值给哈夫曼树的weight 
	for(int i=n+1;i<=m;i++){
		int s1=0,s2=0;
		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 CreateHuffmanCode(HuffmanTree &HT,HuffmanCode &HC,int n){
	HC=new char*[n+1];
	char *cd=new char[n];
	cd[n-1]='\0';
	for(int i=1;i<=n;i++){
		int start=n-1,c=i,f=HT[i].parent;
		while(f){
			--start;
			if(HT[f].lchild==c) cd[start]='0';
			else cd[start]='1';
			c=f;
			f=HT[f].parent;
		}
		HC[i]=new char[n-start];
		strcpy(HC[i],&cd[start]);
	}
	delete cd;
}
int main(){
	freopen("SourceFile.txt","r",stdin);//打开输入文件	
	memset(a,0,sizeof(a));
	string str;
	getline(cin,str);//接收文件的字符串并保存到str中 
	for(int i=0;i<str.length();i++)//统计每个字母出现的频率即次数 
		a[str[i]-64]++;
	int n=0;
	for(int i=1,j=1;i<=24;i++)//统计有多少个不同的字母以及把没出现的字母去除掉 
		if(a[i]!=0){
			n++;
			b[j]=a[i];
			c[j++]=i+64;
		}
	HuffmanTree HT;
	HuffmanCode HC;
	CreateHuffmanTree(HT,n);
	CreateHuffmanCode(HT,HC,n);
	freopen("Code.txt","w",stdout);
	for(int i=1;i<=n;i++)
		cout<<c[i]<<':'<<HC[i]<<endl;
	freopen("ResultFile.txt","w",stdout);
	for(int i=0;i<str.length();i++){
		for(int j=1;j<=n;j++){
			if(str[i]==c[j]) cout<<HC[j];
		}
	}
	return 0;
}

输出结果:

字符对应的编码表保存在文件Code.txt,结果为:

A:0001
B:10
C:1110
D:1111
E:110
F:01
G:0000
H:001

 根据哈夫曼码表,将SourceFile.txt中的字符转换成相应的编码文件ResultFile.txt,结果为:

0001000100010001000110101010101010101010101010101010101010101010101010111011101110111011101110111011111111111111111111111111111111110110110110110110110110110110110110110110010101010101010101010101010101010101010101000000000000001001001001001001001001001001001

 

评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值