哈夫曼编译码器.docx

上传人:b****8 文档编号:30774003 上传时间:2023-08-23 格式:DOCX 页数:21 大小:136.27KB
下载 相关 举报
哈夫曼编译码器.docx_第1页
第1页 / 共21页
哈夫曼编译码器.docx_第2页
第2页 / 共21页
哈夫曼编译码器.docx_第3页
第3页 / 共21页
哈夫曼编译码器.docx_第4页
第4页 / 共21页
哈夫曼编译码器.docx_第5页
第5页 / 共21页
点击查看更多>>
下载资源
资源描述

哈夫曼编译码器.docx

《哈夫曼编译码器.docx》由会员分享,可在线阅读,更多相关《哈夫曼编译码器.docx(21页珍藏版)》请在冰豆网上搜索。

哈夫曼编译码器.docx

哈夫曼编译码器

 

西安郵電大學

数据结构课程设计报告

题目:

哈夫曼编/译码器

院系名称:

专业名称:

班级:

学生姓名:

学号(8位):

指导教师:

设计起止时间:

 

一.设计目的

本次课程设计的主要目的是综合运用所学的数据结构知识,使用一种自己擅长的语言,解决问题,侧重对栈、哈夫曼树等相关内容的综合应用,使同学们能进一步熟悉掌握使用各种数据结构的实现,进一步提升自己分析问题的能力、培养编程能力、锻炼编程思维,进而不断提高同学们解决问题的能力,并为以后解决实际问题打下良好的基础。

二.设计内容

1.程序设计的环境为VisualC++,使用的语言为C语言。

2.设计了几种结构体:

哈夫曼树(字符、权值、左右孩子、标记位、编码),权值(字符、权值)。

3.使用的数据结构类型是二叉树。

4.读取已存的字符串信息:

与程序存放在同一目录下的souce.txt中。

5.创建哈夫曼树,并放入文件huffmantree.txt中。

6.编码操作:

通过折半查找得到字符的哈夫曼编码,并存放在code.txt文件中。

7.译码操作:

读取code.txt中的内容,译码,结果放入decode.txt文件中。

8.栈的基本操作:

栈的初始化、判空、出栈、入栈、取栈顶。

9.为使界面美观,还使用了清屏函数。

三.概要设计

1.功能模块图

对系统进行分析,给出系统结构图。

整个系统除了主函数外,另外还有14个函数,实现四项功能:

读取文件功能,编码功能,译码功能,写文件功能。

其基本功能模块如下图所示:

 

2.各个模块详细的功能描述。

(1).主函数main()

进入开始界面函数,读取字符串,编码,译码,最后到退出界面。

(2).界面功能Host()、Go_on()、Quit()

(3).读文件ReadFile()

读取与程序在同一目录下的souce.txt文件,获取字符串。

(4).统计字符串中各字符的权值CreateCount()

按照ASCII码的顺序将字符出现的次数记录。

(5).创建哈夫曼树CreateHT()

先创建叶子结点的各种信息,在经过两次查找最小权值而生成非叶子结点,并完善相关的信息。

(6).查找当前权值最小的字符的下标FindMin()

在未查找过的字符中查找。

(7).创建哈夫曼编码CreateHCode()

对哈夫曼进行先序遍历,为左孩子则为0,右孩子为1

(8).将创建好的哈夫曼树相关内容存放到文件中HTWriteFile()

将字符及其对应的编码存放在同一目录下的huffmantree.txt文件中。

(9).统计要编码的总长度GetHCodeLen()

各字符的权值和码长的总和。

(10).哈夫曼编码结果GetResultStr()

将要进行编码的字符串逐个按字符的编码进行编码。

(11).折半查找字符对应的编码HalfSearch()

根据字符的ASCII码的大小查找编码。

(12).写文件WriteFile()

将编码或译码结果分别存放在同一目录下的code.txt或decode.txt文件中。

(13).译码操作DeCode()

按照编码的0、1用先序遍历哈夫曼树,直到找到相对应的叶子,即字符的,追加入译码字符串中。

 

四.详细设计

1.功能函数的调用关系图

 

2.各功能函数的数据流程图

创建哈夫曼树:

创建哈夫曼编码:

 

译码操作:

编码操作:

 

3.重点设计及编码

//创建哈夫曼编码

voidCreateHCode(HUFFMAN_TREE*ht,introot,inti,char*s)

{

if(ht[root].leftchild==-1)//通过对树的先序遍历得到哈夫曼密码

{

s[i]='\0';

strcpy(ht[root].code,s);//遇到叶子结点停止此次遍历,并得到密码

}

else//若为左孩子则为0,为右孩子则为1

{

s[i]='0';

CreateHCode(ht,ht[root].leftchild,i+1,s);

s[i]='1';

CreateHCode(ht,ht[root].rightchild,i+1,s);

}

}

//折半查找要编码内容的相关信息

HUFFMAN_TREE*HalfSearch(HUFFMAN_TREE*ht,intHTLen,charc)

{

inthead=0,tail,middle,Find=FALSE;

tail=(HTLen+1)/2-1;

while(!

Find&&head<=tail)

{

middle=(head+tail)/2;

if(ht[middle].character==c)

Find=TRUE;

elseif(ht[middle].character>c)

tail=middle-1;

else

head=middle+1;

}

returnht+middle;

}

//译码操作

voidDeCode(HUFFMAN_TREE*ht,intHTLen,char*code,intcodelen)

{

char*str;

inti,j,root;//i是密码的下标,j是码串的下标、根结点

root=HTLen-1;

str=(char*)malloc(sizeof(char)*codelen);

for(i=j=0;i<=codelen;)

{//从根结点通过0,1查找左右孩子,遇叶子结点则回到根结点

if(ht[root].leftchild==-1)

{

str[j++]=ht[root].character;

root=HTLen-1;

}

else

root=code[i++]=='0'?

ht[root].leftchild:

ht[root].rightchild;

}

str[j]='\0';

WriteFile(str,"decode.txt");

printf("译码结果:

\n%s\n\n",str);

}

五.测试数据及运行结果

1.正常测试数据和运行结果

读取文件souce.txtx中的内容:

哈夫曼树的创建及编码:

译码操作:

2.异常测试数据及运行结果

读取文件失败:

六.调试情况,设计技巧及体会

1.改进方案

对自己设计进行评价,指出合理和不足之处,提出改进的方案。

通过第二周的编程,我完成了哈夫曼编码/译码器。

程序总体设计结构较合理,功能基本完善,界面友好清晰。

优点:

熟练的应用二叉树这个数据结构的基本操作。

使程序可以更高效的运行,实现对字符串进行哈夫曼编码、译码等基本功能。

也加深了自己对数据结构的认识。

缺点:

在某些方面存在着不足,比如,没有使用位运算来解决问题,使程序浪费了大量的存储空间;变换得到字符串的方式,如直接输入等,使程序更加灵活。

改进的方法:

使用位运算,对其进行压缩和解压缩。

2.体会

在为期两周的程序设计实习中,我受益颇多。

更进一步的了解和掌握了各种数据结构的操作。

熟练的使用数据结构以解决实际问题。

从中,我可以将书本知识应用于实践,为以后的计算机语言的学习打下了坚实的基础;同时,我分析问题的能力也在不断的提高,编程的能力也有显著的进步。

但在本次程序设计中,我学会的更多是坚持的精神和持之以恒的心态,哪怕报错的信息多到显示不完,也要静下心,认认真真一点一点地寻找错误的原因。

另外,我也学会了利用调试来查找出错点的方法,以及一些从未用过但是却功能特殊的函数。

同时真正意识到编写一个程序的不容易,以及多得考虑不完的问题,更是突显出团队合作的重要性。

七.参考文献

[1]耿国华.2008.《数据结构——C语言描述》.北京:

高等教育出版社

[2]王曙燕.2005.《C语言程序设计》.北京:

科学出版社

八.附录:

(可不要,不要打印源程序,只交电子版)

#include

#include

#include

#include

#defineTRUE1

#defineFALSE0

#defineN500

//哈夫曼树的定义

typedefstructHUFFMAN_TREE

{

charcharacter;//字符

intcount;//权值

intleftchild;//左孩子

intrightchild;//右孩子

intflag;//标记位,为0则表示还未查找过,1表示已查找过

char*code;//哈夫曼密码

}HUFFMAN_TREE;

//临时存储权值的定义

typedefstructCOUNT

{

charcharacter;

intcount;

}COUNT;

voidHost(void);

voidGo_on(void);

char*ReadFile(char*);

COUNT*CreateCount(char*,int*);

HUFFMAN_TREE*CreateHT(COUNT*,int);

intFindMin(HUFFMAN_TREE*,int);

voidCreateHCode(HUFFMAN_TREE*,int,int,char*);

voidHTWriteFile(HUFFMAN_TREE*,int);

intGetHCodeLen(HUFFMAN_TREE*,int,int);

char*GetResultStr(char*,HUFFMAN_TREE*,int,int);

HUFFMAN_TREE*HalfSearch(HUFFMAN_TREE*,int,char);

voidWriteFile(char*,char*);

voidDeCode(HUFFMAN_TREE*,int,char*,int);

voidQuit(void);

main()

{

char*str,*code,*result,*HTCode;//原串、编码串1、编码串2、编码串3

intHTLen,Leaf,codelen;//总结点数、叶子结点、密码长度

COUNT*count;//存放临时的所有权值

HUFFMAN_TREE*ht;//哈夫曼树

Host();

Go_on();

//读取文件操作

str=ReadFile("souce.txt");

printf("从文件souce.txt中读取的内容如下:

\n");

printf("%s\n\n",str);

//编码文件内容

Go_on();

count=CreateCount(str,&Leaf);

HTCode=(char*)malloc(sizeof(char)*Leaf);//得到编码的最大长度

HTLen=2*Leaf-1;//计算得到所有结点的个数

ht=CreateHT(count,HTLen);

CreateHCode(ht,HTLen-1,0,HTCode);

HTWriteFile(ht,Leaf);

codelen=GetHCodeLen(ht,HTLen,Leaf);

result=GetResultStr(str,ht,HTLen,codelen);

WriteFile(result,"code.txt");

free(result);

//进行译码的操作

Go_on();

code=ReadFile("code.txt");

printf("编码的内容如下:

\n%s\n\n",code);

DeCode(ht,HTLen,code,codelen);

free(code);

//销毁操作

free(ht);

free(count);

Go_on();

Quit();

}

voidQuit(void)

{

printf("\n\n---------------------------------谢谢使用!

-------------------------------------\n\n");

exit(0);

}

//译码操作

voidDeCode(HUFFMAN_TREE*ht,intHTLen,char*code,intcodelen)

{

char*str;

inti,j,root;//i是密码的下标,j是码串的下标、根结点

root=HTLen-1;

str=(char*)malloc(sizeof(char)*codelen);

for(i=j=0;i<=codelen;)//从根结点开始通过0,1值查找左,右孩子,遇叶子结点则重新回到根结点

{

if(ht[root].leftchild==-1)

{

str[j++]=ht[root].character;

root=HTLen-1;

}

else

root=code[i++]=='0'?

ht[root].leftchild:

ht[root].rightchild;

}

str[j]='\0';

WriteFile(str,"decode.txt");

printf("译码结果:

\n%s\n\n",str);

}

//写文件

voidWriteFile(char*result,char*fname)

{

FILE*fp;

fp=fopen(fname,"wt");

fprintf(fp,"%s",result);

printf("数据已存入%s文件中。

\n",fname);

fclose(fp);

}

//折半查找要编码内容的相关信息

HUFFMAN_TREE*HalfSearch(HUFFMAN_TREE*ht,intHTLen,charc)

{

inthead=0,tail,middle,Find=FALSE;

tail=(HTLen+1)/2-1;

while(!

Find&&head<=tail)

{

middle=(head+tail)/2;

if(ht[middle].character==c)

Find=TRUE;

elseif(ht[middle].character>c)

tail=middle-1;

else

head=middle+1;

}

returnht+middle;

}

//哈夫曼编码的结果

char*GetResultStr(char*str,HUFFMAN_TREE*ht,intHTLen,intcodelen)

{

char*result;//存放编码结果

inti;

result=(char*)malloc(sizeof(char)*codelen);

*result='\0';

for(i=0;str[i];i++)

strcat(result,HalfSearch(ht,HTLen,str[i])->code);

returnresult;

}

//计算要翻译的内容的哈夫曼密码的长度

intGetHCodeLen(HUFFMAN_TREE*ht,intHTLen,intLeaf)

{

inti,resLen=0;

for(i=0;i

resLen+=ht[i].count*strlen(ht[i].code);

returnresLen+1;

}

//将创建好的哈弗曼数的字符和密码信息存入文件

voidHTWriteFile(HUFFMAN_TREE*ht,intLeaf)

{

inti;

FILE*fp;

fp=fopen("huffmantree.txt","wt");

for(i=0;i

fprintf(fp,"%c\t%s\n",ht[i].character,ht[i].code);

printf("\n\n哈夫曼树创建成功,并已存入文件huffmantree.txt中。

\n");

fclose(fp);

}

//创建哈夫曼编码

voidCreateHCode(HUFFMAN_TREE*ht,introot,inti,char*s)

{

if(ht[root].leftchild==-1)//通过对树的先序遍历得到哈夫曼密码

{

s[i]='\0';

strcpy(ht[root].code,s);//遇到叶子结点停止此次遍历,并得到密码

}

else//若为左孩子则为0,为右孩子则为1

{

s[i]='0';

CreateHCode(ht,ht[root].leftchild,i+1,s);

s[i]='1';

CreateHCode(ht,ht[root].rightchild,i+1,s);

}

}

//查找当前权值最小的字符下标

intFindMin(HUFFMAN_TREE*ht,intlen)

{

inti,min;

for(i=0;ht[i].flag;i++)

;

for(min=i;i

if(ht[i].flag==0&&ht[i].count

min=i;

ht[min].flag=1;

returnmin;

}

//创建哈夫曼树

HUFFMAN_TREE*CreateHT(COUNT*count,intHTLen)

{

HUFFMAN_TREE*ht=NULL;

inti,len,leftchild,rightchild;//下标、总结点、左孩子下标、右孩子下标

len=(HTLen+1)/2;//计算叶子结点数

ht=(HUFFMAN_TREE*)malloc(sizeof(HUFFMAN_TREE)*HTLen);

//初始化叶子结点

for(i=0;i

{

ht[i].character=count[i].character;

ht[i].count=count[i].count;

ht[i].leftchild=ht[i].rightchild=-1;

ht[i].flag=0;

ht[i].code=(char*)malloc(sizeof(char)*len);//得到密码的最大的长度

}

//初始化非叶子结点

while(len

{

leftchild=FindMin(ht,len);

rightchild=FindMin(ht,len);

ht[len].character='#';

ht[len].count=ht[leftchild].count+ht[rightchild].count;

ht[len].leftchild=leftchild;

ht[len].rightchild=rightchild;

ht[len].flag=0;

ht[len++].code=NULL;

}

returnht;

}

//创建临时的字符权值

COUNT*CreateCount(char*str,int*HTLen)

{

COUNT*frp=NULL;

intcount=0,total[128]={0},i,j;//出现字符的个数、统计

for(i=0;str[i];i++)

total[str[i]]++;

for(i=0;i<128;i++)

if(total[i])

count++;

frp=(COUNT*)malloc(sizeof(COUNT)*count);

for(i=j=0;i<128;i++)

if(total[i])

{

frp[j].character=i;

frp[j++].count=total[i];

}

*HTLen=count;//得到所有的叶子节点的数量

returnfrp;

}

char*ReadFile(char*fname)

{

FILE*fp;

charch,*str;

inti;

if((fp=fopen(fname,"rt"))==NULL)

{

printf("\n\n打开文件出错!

可能不存在这个文件!

\n\n");

exit(0);

}

str=(char*)malloc(sizeof(char)*N);

for(i=0;(ch=fgetc(fp))!

=EOF;i++)

str[i]=ch;

str[i]='\0';

fclose(fp);

printf("\n\n读取文件%s成功!

\n",fname);

returnstr;

}

voidGo_on(void)

{

printf("\n\n\n按任意键继续");

getch();

system("cls");

}

voidHost(void)

{

printf("\n\n---------------------欢迎使用哈夫曼编码、译码器---------------------------------\n\n");

printf("\t注意:

\n\t\t请将需要编码的数据提前存入同一目录下souce.txt文件中!

\n\n");

}

 

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 经管营销 > 公共行政管理

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1