数据结构课程设计(选):Huffman编码与解码

1.任务:

[问题描述]

对一篇不少于5000字符的英文文章(source.txt),统计各字符出现的次数,实现Huffman编码(code.dat),以及对编码结果的解码(recode.txt)。

[基本要求]

(1) 输出每个字符出现的次数和编码,并存储文件(Huffman.txt)。

(2) 在Huffman编码后,英文文章编码结果保存到文件中(code.dat),编码结果必须是二进制形式,即0 1的信息用比特位表示,不能用字符’0’和’1’表示。

(3) 实现解码功能。

2.采用的数据结构

        采用霍夫曼树和顺序查找

3.算法设计思想

        从文件中对于文章进行逐字符读入,对于每一字符出现的总次数进行累加,得到各字母的权值。每一次在未标记的权值中寻找两个最小值,取和,将和加入数组中。将两个最小值进行标记,记录它们的根节点位置(即和所在的位置),记录和的左右子树所在的位置。直至只剩下一个未标记的元素为止,该元素即为霍夫曼树的根节点。根据数组中的位置记录可以得到霍夫曼树。时间复杂度T(n)=O(n^2), 空间复杂度S(n)=O(n).

        利用霍夫曼树进行编码,规定霍夫曼树中左分支为0,右分支为1,从叶结点起,若其为其双亲结点的左节点则记0,为右节点则记1,结点上移,直至移至根节点。将所得的01序列逆序,则得到该叶结点的编码。

        利用霍夫曼树进行解码,遇到0则向左子树下移,遇到1则向右子树下移,直至到达根节点。重复该过程实现01序列的解码。

4.源程序:

#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <fstream>
#include <string>
#include <algorithm>
using namespace std;

typedef struct Alpha
{
	char alpha='\0';
	int num=0;
	bool flag=true;
	string code="";
	int Father=0,LChild=0,RChild=0;
}Alpha;
Alpha a[51];

typedef struct BiTNode
{
	Alpha data;
	BiTNode *LChild,*RChild;
}BiTNode,*BiTree;

void ReadFromFile(Alpha a[])
{
	char ch;
	int x;
	FILE *fp;
	if((fp=fopen("source.txt","r"))==NULL)
	{
		cout<<"文件打开失败!\n";
	}
	else
	{
		while(!feof(fp))
		{
			ch=fgetc(fp);
			if(('a'<= ch) && (ch <='z'))
			{
				x=ch -'a';
				a[x].num++;
				continue;
			}
			else if('A'<= ch && ch <='Z')
			{
				x=ch-'A';
				a[x].num++;
				continue;
			}
			else
			{
				continue;
			}
		}
	}
	fclose(fp);
}

int SearchMin(Alpha a[],int n)
{
	int min=5000,k;
	for(int i=0;i<n;i++)
    {
    	if(a[i].flag && (a[i].num<min))
    	{
    		min=a[i].num;
    		k=i;
		}
	}
	return k;
}
char h[20];
void Encode(Alpha a[])
{
    string s;
	for(int i=0;i<26;i++)
	{
		s="";
		int k=0,f=-1,c=i;
		while(f!=0)
		{
			f=a[c].Father;
			if(a[f].LChild==c)
			{
				s+='0';
			}
			if(a[f].RChild==c)
			{
				s+='1';
			}
			c=f;
		}
		reverse(s.begin(),s.end());
		a[i].code=s;
	}
}

void EncodeOutput(Alpha a[])
{
	char ch;
	int x;
	ifstream infile;
	infile.open("source.txt");
	ofstream outfile;
	outfile.open("code.txt");
	if(outfile&&infile)
	{
		while(!infile.eof())
		{
			infile>>noskipws;
			infile>>ch;
	    	if('a'<=ch && ch<='z')
	    	{
	    		x=ch-'a';
	    		outfile<<a[x].code;
	    	}
	    	else if('A'<=ch && ch<='Z')
	    	{
	    		x=ch-'A';
	    		outfile<<a[x].code;
	    	}
	    	else if(ch==' ')
	    	{
	    		outfile<<" ";
			}
	    	else
	    	{
	    		outfile<<ch;
	    	}
		}
	}
	else
	{
		cout<<"打开失败!\n";
	}
	outfile.close();
	infile.close();
}

void RecodeOutput(Alpha a[])
{
	char ch;
	int x;
	ifstream infile;
	infile.open("code.txt");
	ofstream outfile;
	outfile.open("recode.txt");
	if(outfile&&infile)
	{
		infile>>noskipws;
		while(!infile.eof())
		{
			infile>>ch;
	    	if((ch!='0')&&(ch!='1'))
	    	{
	    		outfile<<ch;
			}
			else if(ch==' ')
			{
				cout<<" ";
			}
			else
			{
				int k=50;
				while(k>25)
				{
					if(ch=='0')
					{
						k=a[k].LChild;
					}
					if(ch=='1')
					{
						k=a[k].RChild;
					}
					if(k>25)
					{
						infile>>ch;
					}
				}
				outfile<<a[k].alpha;
			}
		}
	}
	else
	{
		cout<<"打开失败!\n";
	}
	outfile.close();
	infile.close();
}

int main() 
{
	for(int i=0;i<26;i++)
	{
		a[i].alpha='a'+i;
	}
	ReadFromFile(a);
	int n=26;
	for(int i=0;i<25;i++)
	{
		int a1,a2;
		a1=SearchMin(a,n);
		a[a1].flag=false;
		a2=SearchMin(a,n);
		a[a2].flag=false;
		a[n].num=a[a1].num+a[a2].num;
		a[n].flag=true;
		a[n].LChild=a1;
		a[n].RChild=a2;
		a[a1].Father=n;
		a[a2].Father=n;
		n++;
	}
	Encode(a);
	EncodeOutput(a);
	cout<<"文件编码成功!\n";
	RecodeOutput(a);
	cout<<"文件译码成功!\n";
	return 0;
}

5.源程序测试数据及结果

霍夫曼树测试用例

 霍夫曼树编码测试结果

 霍夫曼树解码测试结果

6.存在问题及改进方法

        在霍夫曼树的编码和解码中,为了代码编写的方便起见,我将大小写字母全部转化为了小写字母,这对于编码再解码后的内容可能会造成影响。其次,在编码过程中,只对字母进行了编码,忽视了各种标点符号,我将读入的非字母元素原封不动的输出到了输出文档中,这对于文件的编码的保密程度有了较大的影响,应该增加结点的个数,使各种符号等都加入编码过程才更加严谨。

  • 4
    点赞
  • 51
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
数据结构中的Huffman编码是一种用于数据压缩的方法。它通过统计待压缩文件中各个字符出现的频率,然后根据频率构建出一棵哈夫曼树。在哈夫曼树中,出现频率高的字符编码为较短的二进制数,而出现频率低的字符则被编码为较长的二进制数。这样,在压缩文件时,出现频率较高的字符占用较少的位数,从而实现了对文件的压缩。 对于txt格式的文件,我们可以首先统计文件中各个字符出现频率,并根据频率构建Huffman树。构建Huffman树的过程可以使用优先队列来实现,它可以方便地维护字符频率的有序性。构建完Huffman树后,我们可以根据树的结构为每个字符生成相应的编码。 在压缩文件时,我们可以将每个字符编码组合成一串二进制数字,并将这些二进制数字存储到一个文件中。此文件即为压缩后的文件。在解压缩时,我们可以读取压缩文件中的二进制数字,并根据Huffman树的结构进行解码,还原出原始的txt文件。 Huffman编码是一种无损压缩算法,即压缩后的文件可以完全还原为原始文件。它的压缩率受文件中字符频率分布的影响,字符出现频率越高,则对应的编码长度越短,压缩率越高。因此,对于频率分布不均匀的txt文件,Huffman编码可以取得较好的压缩效果。 综上所述,Huffman编码是一种可以用于对txt格式文件进行压缩与解压的数据结构方法。它通过统计字符频率,构建Huffman树,并根据树的结构进行编码解码实现了对文件的压缩和解压缩。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值