数据结构课程设计-赫夫曼编码(C语言)

合集下载

数据结构课设报告 哈夫曼编译器 C语言 源码

数据结构课设报告 哈夫曼编译器 C语言 源码

中南大学数据结构课程设计报告题目哈夫曼编译器学生姓名孙毅指导教师杨希学院信息科学与工程学院专业班级信息安全1401班二○一六年十一月1 / 23目录一、课程设计目的数据结构是计算机专业的核心课程,是计算机科学的算法理论基础和软件设计的技术基础,实践性强,课程设计是加强学生实践能力的一个重要手段。

课程设计要求学生在完成程序设计的同时能够写出规范的设计报告,培养学生分析问题、解决问题,提高学生软件设计能力。

二、课程设计的内容哈夫曼编译器2.1、问题描述利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。

这要求在发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行译码。

对于双向传输信息的信道,每端都需要一个完整的编译码系统。

为这样的信息收发站编写哈夫曼编译系统。

2.2、基本要求(1)从键盘读入字符集大小n , 以及n个字符和权值,建立哈夫曼树。

(2)利用已建好的哈夫曼树对文件正文进行编码,将结果存入相关文件中。

(3)利用已建好的哈夫曼树将编码文件中的代码进行译码,结果存入文件中。

(4)输出代码文件,以紧凑格式显示。

(5)以直观的方式输出哈夫曼树,同时将此字符形式的哈夫曼树写入文件中。

三、问题描述,解决的方法3.1从键盘读入字符集大小n , 以及n个字符和权值,建立哈夫曼树。

a.首先设计一个结构体,成员有权值、左右儿子、以及字符本身,再设计一个输入函数,函数中要求输入字符集大小n,以及这n个字符和他们各自对应的权值。

b.再根据以上的各种输入结合建立哈夫曼树的思想原理建立起哈夫曼树,设计的函数包括有两个,一个是选中最小权值的两棵树,另一个是创建哈夫曼树。

3.2利用已建好的哈夫曼树对文件正文进行编码,将结果存入相关文件中。

a.第一步是要求用户输入待编码文件的路径,再根据路径读取待编码文件里的内容,再利用哈夫曼树将内容编码。

b.将编码的结果存入文件中,文件起名为编码结果.txt,这个工作已经在编码路径的同时并完成了。

哈夫曼编译码---数据结构C语言版课程设计

哈夫曼编译码---数据结构C语言版课程设计

《数据结构》课程设计报告%设计题目?学院名称信息工程学院专业班级12 计本 2姓名张翠翠学号17 ______$题目:哈夫曼(Huffman)编/译码器一、问题描述利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。

但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行译码(复原)。

对于双工信道(即可以双向传输信息的信道),每端都需要一个完整的编/译码系统。

试为这样的信息收发站写一个哈夫曼码的编/译码系统。

二、设计目标帮助学生熟练掌握树的应用和基本操作,重点掌握二叉树的存储,这里以哈夫曼树为设计目标进一步提高学生的设计能力及对树的理解。

三、任务要求;一个完整的系统应具有以下功能:1) I:初始化(Initialization)。

从终端读入字符集大小n,以及n个字符和n个权值,建立哈夫曼树,并将它存于文件hfmTree 中。

2) E:编码(Encoding)。

利用以建好的哈夫曼树(如不在内存,则从文件hfmTree中读入),对文件ToBeTran中的正文进行编码,然后将结果存入文件CodeFile中。

3) D:译码(Decoding)。

利用已建好的哈夫曼树将文件CodeFile 中的代码进行译码,结果存入文件TextFile中。

4) P:印代码文件(Print)。

将文件CodeFile以紧凑格式显示在终端上,每行50个代码。

同时将此字符形式的编码文件写入文件CodePrin中。

5) T:印哈夫曼树(Tree Printing)。

将已在内存中的哈夫曼树以直观的方式(树或凹入表形式)显示在终端上,同时将此字符形式的哈夫曼树写入文件TreePrint中。

四、需求分析~利用哈夫曼树(Huffman)编/译码(一)、初始化哈夫曼树(二)、建立哈夫曼树(三)、对哈夫曼树进行编码(四)、输出对应字符的编码(五)、译码过程五、概要设计哈夫曼树的存储结构描述~typedef struct{unsigned int weight;unsigned int parent, lchild, rchild;}HTNode, *HuffmanTree;哈弗曼树的算法void CreateHT(HTNode ht[],int n)arent=ht[i].lchild=ht[i].rchild=-1; arent==-1) eight<min1) eight;lnode=k;}}else if (ht[k].weight<min2){min2=ht[k].weight;rnode=k;}}}ht[lnode].parent=i;ht[rnode].parent=i;eight=ht[lnode].weight+ht[rnode].weight;child=lnode;ht[i].rchild=rnode; arent;while (f!=-1) child==c) arent;、}++; ata);for (k=hcd[i].start;k<=n;k++) d[k]); }printf("\n");}}#void editHCode(HTNode ht[],HCode hcd[],int n) ata)tart;k<=n;k++){printf("%c",hcd[j].cd[k]);}break; tart,j=0;k<=n;k++,j++)d[k]) ata);for(x=0;code[x-1]!='#';x++) ata=str[i];ht[i].weight=fnum[i];}(while (flag) .");getch();system("cls");break;case 'b':case 'B':system("cls");printf("请输入要进行编码的字符串(以#结束):\n"); &editHCode(ht,hcd,n);printf("\n按任意键返回...");getch();system("cls");break;case 'c':case 'C':system("cls");!DispHCode(ht,hcd,n);printf("请输入编码(以#结束):\n");deHCode(ht,hcd,n);printf("\n按任意键返回...");getch();system("cls");break;case 'd':<case 'D':flag=0;break;default:system("cls");}}}字符(空格A B C D E F G&HI J K L M频度186【64132232103211547—57153220由上表画出哈夫曼树:…由哈夫曼树得出各字符的编码:字符编码字符编码空格10|0001DA010E111111001 B011111%FC0000G01110关系调用:;该程序的流程图:`【开始结点数是否大于1将data 和权值赋给ht输出根结点和权值调用selectmin 函数 计算根结点函数父结点为两子结点之和"是否为根结点左子是否为空此时编码为0i<=2*ni++编码为1结束、否否右子是否为空是是否否|是是七、测试分析白盒:查看代码完整性¥白盒测试也称结构测试或逻辑驱动测试,它是按照程序内部的结构测试程序,通过测试来检测产品内部动作是否按照设计规格说明书的规定正常进行,检验程序中的每条通路是否都能按预定要求正确工作。

c哈夫曼编码课程设计

c哈夫曼编码课程设计

c 哈夫曼编码课程设计一、课程目标知识目标:1. 学生能理解哈夫曼编码的基本原理,掌握其构建过程和应用场景。

2. 学生能运用哈夫曼编码进行数据压缩,并了解压缩比的概念。

3. 学生能理解哈夫曼编码在通信、图像处理等领域的重要性。

技能目标:1. 学生能够运用所学知识,独立构建哈夫曼树并进行编码。

2. 学生能够分析给定数据,选择合适的编码方法进行数据压缩。

3. 学生能够运用编程工具实现哈夫曼编码和解码过程。

情感态度价值观目标:1. 学生通过学习哈夫曼编码,培养对数据压缩技术的兴趣,提高信息素养。

2. 学生在合作学习过程中,培养团队协作能力和沟通能力。

3. 学生了解我国在数据压缩领域的研究成果,增强民族自豪感。

课程性质:本课程为信息技术课程,旨在帮助学生掌握数据压缩的基本方法,提高数据处理能力。

学生特点:学生处于高年级阶段,具备一定的编程基础和逻辑思维能力。

教学要求:结合学生特点和课程性质,注重理论与实践相结合,培养学生的实际操作能力和创新能力。

通过分解课程目标为具体学习成果,使学生在学习过程中能够明确自身的学习进度和目标。

二、教学内容1. 哈夫曼编码基本原理:介绍哈夫曼编码的概念、原理和优势,结合教材相关章节,使学生理解哈夫曼编码在数据压缩中的应用。

- 哈夫曼树的构建方法- 哈夫曼编码的生成过程- 压缩比的概念及其计算方法2. 哈夫曼编码的实际操作:通过实际操作,让学生掌握哈夫曼编码的构建和编码过程。

- 利用编程工具实现哈夫曼树的构建- 编程实现哈夫曼编码的生成- 数据压缩与解压缩的实际操作3. 哈夫曼编码的应用案例分析:结合教材案例,分析哈夫曼编码在通信、图像处理等领域的作用。

- 通信领域的数据压缩- 图像处理中的哈夫曼编码应用- 其他领域中的应用案例4. 编程实践:布置相关编程任务,巩固学生对哈夫曼编码的理解和应用。

- 实现哈夫曼编码的压缩和解压缩程序- 分析不同数据集的压缩效果,优化哈夫曼编码方法教学内容安排和进度:第1课时:哈夫曼编码基本原理及构建方法第2课时:哈夫曼编码的实际操作(构建哈夫曼树、生成编码)第3课时:哈夫曼编码的应用案例分析第4课时:编程实践(实现压缩与解压缩程序,优化编码方法)三、教学方法本课程将采用以下教学方法,以促进学生的主动参与和深入理解:1. 讲授法:对于哈夫曼编码的基本原理和概念,通过教师清晰的讲解,结合教材内容,使学生快速掌握理论基础。

数据结构课程设计赫夫曼编译码器C

数据结构课程设计赫夫曼编译码器C

赫夫曼编\译码器摘要本次课程设计过程中我主要根据课本中的实现思想及算法编写程序,体现以课本知识的应用为主,在学习了线性表、栈、队列、二叉树、树和图等结构的基础上,以能够更加熟练的应用所学知识,并能结合一些著名算法来实现对一些实际问题的应用,例如,赫夫曼树等,从而更为深刻理解数据结构的内涵,熟悉它们各自的应用场合及方法。

有些在平时课程中并没有掌握的内容在这次课程设计中都是先通过看课本学懂了,然后再在课程设计中加深印象,实现算法的应用和扩展。

这次课程设计的设计内容主要是通过实际的例子和程序来实现课本中所学习的算法的应用。

程序设计设计语言采用C++,程序运行平台为Windows XP。

赫夫曼编\译码器的主要功能是先建立赫夫曼树,然后利用建好的赫夫曼树生成哈夫曼编码后进行译码。

赫夫曼编译系统分为五个功能模块:原始数据载入,打印编码规则、编码、译码。

以二叉树的应用为基础,包括统计信息,并通过构建赫夫曼树、对信息进行赫夫曼编码,将编码信息等存入文档。

关键字数据结构栈和队列赫夫曼树赫夫曼编码目录1引言 (1)1.1课程设计目的 (1)1.2课程设计背景 (1)1.3课程设计主要内容 (1)2需求分析 (3)3 概要设计 (4)3.1 设计思想 (4)3.2 函数间的关系 (4)3.3数据结构与算法设计 (4)4详细设计 (6)4.1 赫夫曼的主要结构 (6)5 调试分析 (8)6 测试并列出测试结果 (9)6.1 测试方式 (9)6.2 测试结果 (9)7 总结 (13)致谢 (14)参考文献 (14)附录 (15)1 引言当今社会,计算机技术和通信技术已不断发展,处理和传输的数据量越来越庞大。

如何采用有效的数据压缩技术引起了人们的极大重视。

从而产生了哈夫曼编码,它是一种应用广泛且非常有效的数据压缩技术,该技术一般可将数据压缩20%至90%,通常我们将压缩技术称为编码,解压缩过程称为解码。

树状结构简称为树,是一种以分支关系进行定义的层次结构,是十分重要的非线性数据结构,在计算机软件设计方面,有着广泛的应用。

《数据结构课程设计》赫夫曼编码实验报告

《数据结构课程设计》赫夫曼编码实验报告

目录一、概述 (1)二、系统分析 (1)三、概要设计 (2)四、详细设计 (4)4.1 赫夫曼树的建立 (4)4.1.1 选择选择parent 为0 且权值最小的两个根结点的算法 (5)4.1.2 统计字符串中字符的种类以及各类字符的个数 (7)4.1.3构造赫夫曼树 (8)4.2赫夫曼编码 (10)4.2.1赫夫曼编码算法 (10)4.2.2建立正文的编码文件 (11)4.3代码文件的译码 (12)五、运行与测试 (14)六、总结与心得 (14)参考文献 (15)附录 (15)一、概述本设计是对输入的一串电文字符实现赫夫曼编码,再对赫夫曼编码生产的代码串进行译码,输出电文字符串。

在当今信息爆炸时代,如何采用有效的数据压缩技术节省数据文件的存储空间和计算机网络的传送时间越来越引起人们的重视,赫夫曼编码正是一种应用广泛且非常有效的数据压缩技术。

二、系统分析赫夫曼编码的应用很广泛,利用赫夫曼树求得的用于通信的二进制编码成为赫夫曼编码。

树中从根到每个叶子都有一条路径,对路径上的各分支约定:指向左子树的分支表示“0”码,指向右子树的分支表示“1”码,取每条路径上的“0”或“1”的序列作为和每个叶子对应的字符的编码,这就是赫夫曼编码。

通常我们把数据压缩的过程称为编码,解压缩的过程称为解码。

电报通信是传递文字的二进制码形式的字符串,但在信息传递时,总希望总长度能尽可能短,即采用最短码。

假设每种字符在电文中出现的次数为W i ,编码长度为L i ,电文中有n 种字符,则电文编码总长为∑W i L i 。

若将此对应到二叉树上,W i 为叶节点的权,L i 为根节点到叶节点的路径长度。

那么,∑W i L i 恰好为二叉树上带权路径长度。

因此,设计电文总长最短的二进制前缀编码,就是以n 种子符出现的频率作权,构造一刻赫夫曼树,此构造过程成为赫夫曼编码。

根据设计要求和分析,要实现设计,必须实现以下方面的功能:(1)赫夫曼树的建立;(2)赫夫曼编码的生成;(3)编码文件的译码;三、概要设计程序由哪些模块组成以及模块之间的层次结构、各模块的调用关系;每个模块的功能。

(完整word版)数据结构课程设计(哈夫曼编码)

(完整word版)数据结构课程设计(哈夫曼编码)

目录目录 (1)1 课程设计的目的和意义 (3)2 需求分析 (5)3 系统设计 (6)(1)设计思路及方案 (6)(2)模块的设计及介绍 (6)(3)主要模块程序流程图 (9)4 系统实现 (14)(1)主调函数 (14)(2)建立HuffmanTree (14)(3)生成Huffman编码并写入文件 (18)(4)电文译码 (19)5 系统调试 (22)小结 (25)参考文献 (26)附录源程序 (27)1 课程设计的目的和意义在当今信息爆炸时代,如何采用有效的数据压缩技术来节省数据文件的存储空间和计算机网络的传送时间已越来越引起人们的重视。

哈夫曼编码正是一种应用广泛且非常有效的数据压缩技术。

哈夫曼编码的应用很广泛,利用哈夫曼树求得的用于通信的二进制编码称为哈夫曼编码。

树中从根到每个叶子都有一条路径,对路径上的各分支约定:指向左子树的分支表示“0"码,指向右子树的分支表示“1”码,取每条路径上的“0”或“1"的序列作为和各个对应的字符的编码,这就是哈夫曼编码。

通常我们把数据压缩的过程称为编码,解压缩的过程称为解码。

电报通信是传递文字的二进制码形式的字符串。

但在信息传递时,总希望总长度尽可能最短,即采用最短码。

作为软件工程专业的学生,我们应该很好的掌握这门技术。

在课堂上,我们能过学到许多的理论知识,但我们很少有过自己动手实践的机会!课程设计就是为解决这个问题提供了一个平台。

在课程设计过程中,我们每个人选择一个课题,认真研究,根据课堂讲授内容,借助书本,自己动手实践。

这样不但有助于我们消化课堂所讲解的内容,还可以增强我们的独立思考能力和动手能力;通过编写实验代码和调试运行,我们可以逐步积累调试C程序的经验并逐渐培养我们的编程能力、用计算机解决实际问题的能力。

在课程设计过程中,我们不但有自己的独立思考,还借助各种参考文献来帮助我们完成系统。

更为重要的是,我们同学之间加强了交流,在对问题的认识方面可以交换不同的意见.同时,师生之间的互动也随之改善,我们可以通过具体的实例来从老师那学到更多的实用的知识。

哈夫曼编码译码器数据结构C语言

哈夫曼编码译码器数据结构C语言

哈夫曼编码译码器数据结构C语言哈夫曼编码译码器数据结构C语言⒈简介本文档旨在介绍一个使用C语言实现的哈夫曼编码译码器的数据结构。

哈夫曼编码是一种用于数据压缩的算法,它通过将频率较高的字符用较短的编码表示,从而实现数据的压缩和解压缩。

⒉哈夫曼编码(Huffman Coding)基本概念⑴字符频率统计在进行哈夫曼编码之前,我们首先需要统计每个字符在待编码的数据中出现的频率。

通过遍历数据,记录每个字符的出现次数,我们可以得到一个字符频率的统计表。

⑵构建哈夫曼树通过字符频率的统计表,我们可以构建一个哈夫曼树。

哈夫曼树是一种二叉树,其中每个叶节点表示一个字符,而每个内部节点表示一个权重,即两个子节点的频率之和。

⑶哈夫曼编码在哈夫曼树构建完成后,我们可以根据树的结构每个字符的编码。

哈夫曼编码的特点是没有任何一个字符的编码是另一个字符编码的前缀,这种编码方式称为前缀编码。

⑷哈夫曼译码根据字符的哈夫曼编码,我们可以将编码后的数据进行解码,还原为原始的数据。

通过遍历哈夫曼树,从根节点开始,根据每个二进制位的取值进行向左或向右的移动,直至叶节点,然后获取该叶节点对应的字符。

⒊数据结构设计⑴结点结构定义一个哈夫曼树的结点结构,包含以下字段:●`char data`:字符●`int frequency`:字符的频率●`int is_leaf`:是否为叶节点●`struct Node left_child`:左子节点●`struct Node right_child`:右子节点⑵频率统计表使用一个数组或链表来记录每个字符的频率统计信息,包含以下字段:●`char data`:字符●`int frequency`:字符的频率⑶编码表使用一个数组或链表来记录每个字符的哈夫曼编码,包含以下字段:●`char data`:字符●`char code`:编码⒋算法流程⑴字符频率统计算法步骤:⒈初始化频率统计表为空。

⒉读取待编码的数据。

哈夫曼编码-数据结构-C程序

哈夫曼编码-数据结构-C程序

数据结构课程设计一、目的《数据结构》是一门实践性较强的软件基础课程,为了学好这门课程,必须在掌握理论知识的同时,加强上机实践。

本课程设计的目的就是要达到理论与实际应用相结合,使同学们能够根据数据对象的特性,学会数据组织的方法,能把现实世界中的实际问题在计算机内部表示出来,并培养基本的、良好的程序设计技能。

二、要求通过这次设计,要求在数据结构析逻辑特性和物理表示,数据结构的选择的应用、算法的设计及其实现等方面中深对课程基本内容的理解。

同时,在程序设计方法以及上机操作等基本技能和科学作风方面受到比较系统和严格的训练。

三、内容2.哈夫曼编码/译码器【问题描述】设计一个利用哈夫曼算法的编码和译码系统,重复地显示并处理以下项目,直到选择退出为止。

【基本要求】(1)初始化:键盘输入字符集大小n、n个字符和n个权值,建立哈夫曼树;(2)编码:利用建好的哈夫曼树生成哈夫曼编码;(3)输出编码;(4)设字符集及频度如下表:字符空格A B C D E F G H I J K L M频度186 64 13 22 32 103 21 15 47 57 1 5 32 20字符N O P Q R S T U V W X Y Z频度57 63 15 1 48 51 80 23 8 18 1 16 1【选做内容】(1)译码功能;(2)显示哈夫曼树;(3)界面设计的优化。

哈夫曼编写编译码一、问题描述利用哈夫曼编码进行通信可以大大提高信道利用率,这要求在发送端通过一个编码系统对待传输预先编码,在接收端将传来的数据进行译码。

对于双工通道,每端都需要一个完整的编/译码系统。

试为这样的信息收发站写一个哈夫曼码的编/译码系统。

二、概要设计1.哈夫曼树的定义:在一棵二叉树中,若带权路径长度达到最小,称这样的二叉树为最优二叉树,也称为哈夫曼树。

2.哈夫曼树的构造:假设有N个权值,则构造出的哈夫曼树有N个叶子结点。

N个权值分别设为W1,W2,……….Wn,则哈夫曼树的构造规则为:(1)将W1,W2,……….Wn看成有N棵树的森林;(2)在森林中选出两个根结点的权值最小的树合并,作为一棵新树的左,右子树,且新树的根结点为其左,右子树结点权值之和;(3)从森林中删除选取取的两面三刀棵树,并将新树加入森林;(4)重复(2)(3)步,直到森林中只剩一棵树为止,该树即为我们所求得的哈夫曼树。

用c语言实现哈夫曼编码

用c语言实现哈夫曼编码

用c语言实现哈夫曼编码哈夫曼编码是一种用于无损数据压缩的熵编码算法。

以下是一个简单的使用C语言实现哈夫曼编码的例子。

这个例子只实现了编码过程,没有实现解码过程。

c复制代码#include<stdio.h>#include<stdlib.h>#include<string.h>// 节点结构体typedef struct Node {char data;int freq;struct Node *left, *right;} Node;// 创建新节点Node* newNode(char data, int freq) {Node* node = (Node*) malloc(sizeof(Node));node->data = data;node->freq = freq;node->left = node->right = NULL;return node;}// 计算前缀和int getSum(Node* root) {if (!root) return0;return root->freq + getSum(root->left) + getSum(root->right);}// 创建哈夫曼树Node* createHuffmanTree(char data[], int freq[], int size) { if (size == 0) return NULL;Node *left = newNode(data[size-1], freq[size-1]);Node *right = createHuffmanTree(data, freq, size-1);Node *top = newNode(0, getSum(right));top->left = left;top->right = right;return top;}// 打印哈夫曼编码void printHuffmanCode(Node* root, int n, char code[]) {if (!root) return;if (root->data != 0) printf("%c: ", root->data);code[n] = root->data;printHuffmanCode(root->left, n+1, code);printHuffmanCode(root->right, n+1, code);}int main() {char data[] = {'a', 'b', 'c', 'd', 'e', 'f', 'g'};int freq[] = {5, 9, 12, 13, 16, 45};int size = sizeof(data)/sizeof(data[0]);Node* root = createHuffmanTree(data, freq, size);char code[256] = {0}; // 存放哈夫曼编码,初始为空字符串,表示没有编码,对应字符的编码为空字符串。

哈夫曼树编码c语言

哈夫曼树编码c语言

以下是C语言实现哈夫曼树编码的示例代码:```c#include <stdio.h>#include <stdlib.h>// 定义结构体表示节点struct TreeNode {int val;struct TreeNode *left;struct TreeNode *right;};// 创建新节点struct TreeNode* newNode(int val) {struct TreeNode* node = (struct TreeNode*)malloc(sizeof(struct TreeNode));node->val = val;node->left = NULL;node->right = NULL;return node;}// 计算权值和int calculateWeightSum(struct TreeNode* root) {if (root == NULL) {return 0;}return root->val + calculateWeightSum(root->left) + calculateWeightSum(root->right);}// 构建哈夫曼树struct TreeNode* buildHuffmanTree(int** freq, int size) {// 创建频率数组int arr[size];for (int i = 0; i < size; i++) {arr[i] = freq[i][0];}// 构建哈夫曼树struct TreeNode* root = NULL;int index = 0;while (index < size) {int min1 = INT_MAX, min2 = INT_MAX;int min1Index = -1, min2Index = -1;for (int i = 0; i < size; i++) {if (arr[i] < min1 && arr[i] != 0) {min1 = arr[i];min1Index = i;}if (arr[i] < min2 && arr[i] != 0) {min2 = arr[i];min2Index = i;}}// 创建新节点作为左右子树,并加入频率数组中arr[min1Index] = 0;arr[min2Index] = 0;struct TreeNode* left = newNode(min1);struct TreeNode* right = newNode(min2);left->left = right;right->right = left;// 将左右子树作为新的根节点,并更新频率数组和根节点指针if (root == NULL) {root = left;} else {struct TreeNode* parent = root;while (parent->left != NULL) {parent = parent->left;}parent->left = left;left->parent = parent;while (parent->right != NULL) {parent = parent->right;}parent->right = right;right->parent = parent;}index += 2; // 跳过左右子树,继续寻找下一对最小的节点构建子树,直到遍历完所有节点为止。

哈夫曼编码c语言代码

哈夫曼编码c语言代码

哈夫曼编码c语言代码1.统计数据中每个字符出现的次数。

2.根据每个字符出现的次数建立哈夫曼树。

3.根据哈夫曼树构建每个字符的编码,相同的字符具有不同的编码。

4.用编码替换原数据中的字符。

根据上述步骤,我们可以得到以下的C语言实现。

C语言实现哈夫曼编码在C语言中,我们可以使用结构体来表示哈夫曼树节点及其信息:```ctypedef struct node 。

char content;int freq;struct node某 left;struct node某 right;} node;```其中content表示节点所代表的字符,freq表示该字符在数据中出现的次数,left和right分别指向节点的左右子节点。

我们可以使用一个链表来存储所有的字符及其出现的次数:```ctypedef struct listNode 。

node某 n;struct listNode某 ne某t;} listNode;```这个链表可以通过遍历数据,统计每个字符出现的次数来构建。

我们可以使用一个堆来存储所有的树节点,每次从堆中取出频率最小的两个节点,构建一个新的节点,然后将这个新节点插入堆中。

重复这个过程直到堆中只剩下一个根节点,这个节点就是哈夫曼树的根节点。

```ctypedef struct heap 。

int size;node某某 nodes;} heap;```定义堆的时候,size表示堆中节点的数量,nodes是一个数组,存储所有的节点。

我们可以使用一棵二叉堆来实现堆的操作,即将频率最小的节点放在堆的顶部。

构建好哈夫曼树后,我们可以通过遍历树来给每个字符一个独一无二的编码。

编码的时候,我们可以使用一个栈来存储每个节点的信息,然后倒序输出栈中的内容来得到编码。

最后,我们可以使用编码替换原数据中的字符。

在解码的时候,我们只需要将编码反向遍历树即可还原原始数据。

总结。

哈夫曼编码详解(C语言实现)

哈夫曼编码详解(C语言实现)

哈夫曼编码详解(C语言实现)哈夫曼编码是一种常见的前缀编码方式,被广泛应用于数据压缩和传输中。

它是由大卫·哈夫曼(David A. Huffman)于1952年提出的,用于通过将不同的字符映射到不同长度的二进制码来实现数据的高效编码和解码。

1.统计字符频率:遍历待编码的文本,记录每个字符出现的频率。

2.构建哈夫曼树:根据字符频率构建哈夫曼树,其中出现频率越高的字符位于树的较低层,频率越低的字符位于树的较高层。

3.生成编码表:从哈夫曼树的根节点开始,遍历哈夫曼树的每个节点,为每个字符生成对应的编码。

在遍历过程中,从根节点到叶子节点的路径上的“0”表示向左,路径上的“1”表示向右。

4.进行编码:根据生成的编码表,将待编码的文本中的每个字符替换为对应的编码。

5.进行解码:根据生成的编码表和编码结果,将编码替换为原始字符。

下面是一个用C语言实现的简单哈夫曼编码示例:```c#include <stdio.h>#include <stdlib.h>#include <string.h>//定义哈夫曼树的节点结构体typedef struct HuffmanNodechar data; // 字符数据int freq; // 字符出现的频率struct HuffmanNode *left; // 左子节点struct HuffmanNode *right; // 右子节点} HuffmanNode;//定义编码表typedef structchar data; // 字符数据char *code; // 字符对应的编码} HuffmanCode;//统计字符频率int *countFrequency(char *text)int *frequency = (int *)calloc(256, sizeof(int)); int len = strlen(text);for (int i = 0; i < len; i++)frequency[(int)text[i]]++;}return frequency;//创建哈夫曼树HuffmanNode *createHuffmanTree(int *frequency)//初始化叶子节点HuffmanNode **leaves = (HuffmanNode **)malloc(256 * sizeof(HuffmanNode *));for (int i = 0; i < 256; i++)if (frequency[i] > 0)HuffmanNode *leaf = (HuffmanNode*)malloc(sizeof(HuffmanNode));leaf->data = (char)i;leaf->freq = frequency[i];leaf->left = NULL;leaf->right = NULL;leaves[i] = leaf;} elseleaves[i] = NULL;}}//构建哈夫曼树while (1)int min1 = -1, min2 = -1;for (int i = 0; i < 256; i++)if (leaves[i] != NULL)if (min1 == -1 , leaves[i]->freq < leaves[min1]->freq) min2 = min1;min1 = i;} else if (min2 == -1 , leaves[i]->freq < leaves[min2]->freq)min2 = i;}}}if (min2 == -1)break;}HuffmanNode *parent = (HuffmanNode*)malloc(sizeof(HuffmanNode));parent->data = 0;parent->freq = leaves[min1]->freq + leaves[min2]->freq;parent->left = leaves[min1];parent->right = leaves[min2];leaves[min1] = parent;leaves[min2] = NULL;}HuffmanNode *root = leaves[min1];free(leaves);return root;//生成编码表void generateHuffmanCode(HuffmanNode *root, HuffmanCode *huffmanCode, char *code, int depth)if (root->left == NULL && root->right == NULL)code[depth] = '\0';huffmanCode[root->data].data = root->data;huffmanCode[root->data].code = strdup(code);return;}if (root->left != NULL)code[depth] = '0';generateHuffmanCode(root->left, huffmanCode, code, depth + 1);}if (root->right != NULL)code[depth] = '1';generateHuffmanCode(root->right, huffmanCode, code, depth + 1);}//进行编码char *encodeText(char *text, HuffmanCode *huffmanCode)int len = strlen(text);int codeLen = 0;char *code = (char *)malloc(len * 8 * sizeof(char));for (int i = 0; i < len; i++)strcat(code + codeLen, huffmanCode[(int)text[i]].code);codeLen += strlen(huffmanCode[(int)text[i]].code);}return code;//进行解码char* decodeText(char* code, HuffmanNode* root) int len = strlen(code);char* text = (char*)malloc(len * sizeof(char)); int textLen = 0;HuffmanNode* node = root;for (int i = 0; i < len; i++)if (code[i] == '0')node = node->left;} elsenode = node->right;}if (node->left == NULL && node->right == NULL) text[textLen] = node->data;textLen++;node = root;}}text[textLen] = '\0';return text;int maichar *text = "Hello, World!";int *frequency = countFrequency(text);HuffmanNode *root = createHuffmanTree(frequency);HuffmanCode *huffmanCode = (HuffmanCode *)malloc(256 * sizeof(HuffmanCode));char code[256];generateHuffmanCode(root, huffmanCode, code, 0);char *encodedText = encodeText(text, huffmanCode);char *decodedText = decodeText(encodedText, root);printf("Original Text: %s\n", text);printf("Encoded Text: %s\n", encodedText);printf("Decoded Text: %s\n", decodedText);//释放内存free(frequency);free(root);for (int i = 0; i < 256; i++)if (huffmanCode[i].code != NULL)free(huffmanCode[i].code);}}free(huffmanCode);free(encodedText);free(decodedText);return 0;```上述的示例代码实现了一个简单的哈夫曼编码和解码过程。

霍夫曼编码c语言

霍夫曼编码c语言

霍夫曼编码c语言霍夫曼编码是一种用于数据压缩的编码技术,它通过重新组织数据中的符号来减少传输或存储数据所需的比特数。

在C语言中实现霍夫曼编码需要掌握数据结构、算法和编码理论的基础知识。

一、霍夫曼编码原理霍夫曼编码的基本原理是利用符号出现的频率来构建一个最优的编码方案,使得编码后的比特率最小。

在霍夫曼图中,每个符号对应一个唯一的路径,路径上的节点表示该符号可能出现的概率。

通过选择概率较大的路径,可以获得较短的编码,从而实现数据压缩。

二、C语言实现霍夫曼编码以下是一个简单的C语言实现霍夫曼编码的示例代码:```c#include<stdio.h>#include<stdlib.h>#include<stdbool.h>//定义霍夫曼树节点结构体typedefstructNode{charsymbol;//符号structNode*left;//左子节点structNode*right;//右子节点intfrequency;//符号频率}Node;//构建霍夫曼树函数Node*buildHuffmanTree(intfrequencies[],intn){//合并相同频率的节点for(inti=0;i<n-1;i++){for(intj=i+1;j<n;j++){if(frequencies[i]==frequencies[j]){ Node*temp=frequencies[i]; frequencies[i]=frequencies[j]; frequencies[j]=temp;mergeNodes(frequencies,i,j);}}}//构建霍夫曼树Node*root=NULL;for(inti=0;i<n;i++){if(root==NULL){root=frequencies[i];}else{Node*child=frequencies[i];child->left=root;root->right=child;root=child;}}returnroot;}//合并两个节点的函数voidmergeNodes(intfrequencies[],inti,intj){frequencies[i]=frequencies[j];//合并节点频率frequencies[j]=NULL;//移除多余节点}//输出霍夫曼编码函数voidprintCodes(Node*root,char*codes[],intindex){if(root==NULL){//如果节点为空,输出编码为空字符串printf("%s",codes[index]);return;}elseif(root->left!=NULL){//如果节点左子节点不为空,输出左子节点的编码作为前缀printCodes(root->left,codes,index*2+1);}elseif(root->right!=NULL){//如果节点右子节点不为空,输出右子节点的编码作为前缀(可用作解码的辅助信息)printCodes(root->right,codes,index*2+2);}else{//如果节点为叶子节点,输出节点的符号作为编码的前缀(去掉重复前缀)并输出当前编码的长度(作为该符号的出现次数)intfreq=root->frequency;//当前符号频率(去掉重复前缀后的频率)while(codes[index]!='\0'){//将前缀放入已使用的字符串数组中以供其他叶子节点使用,重复前缀使用最少的次数(去除重复)并输出当前编码长度和符号本身作为输出结果index--;//指针向后移动一位,直到指针指向'\0'字符为止(已使用的字符串数组)或遇到NULL字符为止(编码数组结束)并返回编码长度和符号本身作为输出结果供其他叶子节点使用和参考。

哈夫曼编码译码器数据结构C语言

哈夫曼编码译码器数据结构C语言

哈夫曼编码译码器数据结构C语言哈夫曼编码译码器数据结构C语言文档1.引言本文档介绍了一个基于哈夫曼编码的译码器的设计和实现。

哈夫曼编码是一种无损压缩算法,通过对出现频率较高的符号进行较短的编码,来减小数据的存储或传输所需的空间。

2.哈夫曼编码原理在哈夫曼编码中,使用一颗二叉树,将出现频率较高的符号表示为树的较浅的节点,而出现频率较低的符号表示为树的较深的节点。

通过遍历整个二叉树,可以得到每个符号对应的哈夫曼编码。

2.1 创建哈夫曼树首先,根据每个符号的出现频率,创建一颗包含所有符号的节点的最小堆。

然后,根据最小堆的特性,每次从最小堆中选取两个出现频率最低的节点,并合并为一个新节点。

重复这个过程,直到最小堆中只剩下一个节点,即哈夫曼树的根节点。

2.2 哈夫曼编码通过遍历哈夫曼树,可以得到每个符号对应的哈夫曼编码。

在遍历的过程中,左孩子表示编码中的“0”,右孩子表示编码中的“1”。

每次左移一个位,表示向左遍历,每次右移一个位,表示向右遍历。

3.数据结构设计下面介绍了本文档中所使用的各种数据结构和相关函数的设计。

3.1 结构定义```cstruct Node {char symbol。

int frequency。

struct Node leftChild。

struct Node rightChild。

}。

```3.2 方法定义```c// 创建哈夫曼树struct Node createHuffmanTree(char symbols, int frequencies, int size)// 哈夫曼编码表void generateHuffmanTable(struct Node root, char huffmanTable, char currentCode)// 哈夫曼编码char encode(char data, char huffmanTable)// 哈夫曼译码char decode(char encodedData, struct Node root)```4.实现细节在这个章节中,我们将会具体讨论各个方法的实现细节和使用示例。

c语言哈夫曼课程设计

c语言哈夫曼课程设计

c语言哈夫曼课程设计一、课程目标知识目标:1. 理解哈夫曼编码的基本原理,掌握哈夫曼树的结构特点及其构建方法;2. 学会运用C语言实现哈夫曼编码和解码过程;3. 了解哈夫曼编码在数据压缩中的应用及其优势。

技能目标:1. 能够运用所学知识,独立编写C语言程序构建哈夫曼树并进行编码和解码;2. 培养学生运用算法解决问题的能力,提高编程实践技能;3. 提高学生的逻辑思维能力和分析解决问题的能力。

情感态度价值观目标:1. 激发学生对计算机科学和信息技术的兴趣,培养良好的学习习惯;2. 培养学生的团队合作意识,提高沟通协作能力;3. 培养学生面对问题勇于探索、积极进取的精神。

本课程针对高中年级学生,结合C语言学科特点,充分考虑学生的认知水平、兴趣和实际需求,设计具有实用性、挑战性和趣味性的课程内容。

课程旨在帮助学生掌握哈夫曼编码的核心知识,提高编程实践能力,培养良好的学习态度和价值观,为后续计算机科学学习奠定基础。

通过本课程的学习,学生将能够独立完成哈夫曼编码相关程序的设计与实现,并在实际应用中发挥其优势。

二、教学内容1. 哈夫曼编码基本原理:介绍哈夫曼编码的概念、原理及其在数据压缩中的应用。

相关教材章节:第十四章 数据结构与算法 §5 哈夫曼编码2. 哈夫曼树的构建:讲解哈夫曼树的构建过程,包括选择、合并及构建哈夫曼树的方法。

相关教材章节:第十四章 数据结构与算法 §5 哈夫曼编码3. 哈夫曼编码与解码:介绍哈夫曼编码方法,以及如何利用哈夫曼树进行数据的编码和解码。

相关教材章节:第十四章 数据结构与算法 §5 哈夫曼编码4. C语言实现哈夫曼编码:教授如何利用C语言编写程序实现哈夫曼树的构建、编码和解码过程。

相关教材章节:第十四章 数据结构与算法 §6 C语言实现哈夫曼编码教学内容安排与进度:第一课时:哈夫曼编码基本原理介绍第二课时:哈夫曼树的构建方法及步骤第三课时:哈夫曼编码与解码方法第四课时:C语言实现哈夫曼编码(上)第五课时:C语言实现哈夫曼编码(下)及实践练习本教学内容旨在保证学生掌握哈夫曼编码相关知识,注重理论与实践相结合,使学生在学习过程中逐步提升编程能力和解决问题的能力。

哈夫曼编码译码器数据结构C语言

哈夫曼编码译码器数据结构C语言

哈夫曼编码译码器数据结构C语言哈夫曼编码译码器数据结构C语言引言哈夫曼编码是一种用于无损数据压缩的编码方式,它利用出现频率较高的字符使用较短的编码,而出现频率较低的字符使用较长的编码。

通过这种方式可以使得编码后的数据占据较少的存储空间。

本文将介绍如何使用C语言实现一个哈夫曼编码译码器的数据结构。

哈夫曼树哈夫曼树是哈夫曼编码的关键数据结构,它可以通过给定的字符频率构建出一棵树。

在哈夫曼树中,每个字符都有一个对应的叶子节点,而非叶子节点表示编码的中间过程。

具体构建哈夫曼树的步骤如下:1. 统计每个字符的出现频率。

2. 将每个字符及其频率构建成一个节点,并按照频率从小到大排序。

3. 从频率最小的两个节点开始,合并成一个新节点,并将新节点的频率设为两个节点频率之和。

4. 将新节点插入到节点列表中,保持节点列表有序。

5. 重复步骤3和步骤4,直到只剩下一个节点,这个节点就是哈夫曼树的根节点。

编码在构建了哈夫曼树之后,我们可以根据树的结构来进行编码。

对于每个字符,其编码是由根节点到对应叶子节点路径上的边来表示的。

具体编码的步骤如下:1. 从根节点开始,递归遍历哈夫曼树的每个节点。

2. 如果当前节点为叶子节点,记录下从根节点到该叶子节点所经过的路径上的边的取值(0表示左边,1表示右边),得到该字符的编码。

3. 对于每个字符,将其编码存储起来以便后续使用。

译码译码的过程与编码相反,我们可以根据编码来找到对应的字符。

具体译码的步骤如下:1. 从哈夫曼树的根节点开始,逐个读取待译码的数据。

2. 如果读取的数据为0,移动到左子节点;如果读取的数据为1,移动到右子节点。

3. 如果移动到了叶子节点,记录下该叶子节点对应的字符,并回到根节点。

4. 重复步骤2和步骤3,直到读取完毕所有的数据,得到原始的字符序列。

实现下面是一个用C语言实现的哈夫曼编码译码器的数据结构示例:```cinclude <stdio.h>typedef struct Node {char character;int frequency;struct Node left;struct Node right;} Node;typedef struct HuffmanTree {Node root;} HuffmanTree;HuffmanTree buildHuffmanTree(char characters, int frequencies, int size) {// 构建哈夫曼树的代码实现}void encode(HuffmanTree tree, char string, char encodedString) {// 编码的代码实现}void decode(HuffmanTree tree, char encodedString, char decodedString) {// 译码的代码实现}int mn() {// 测试代码}```总结通过本文,我们了解了哈夫曼编码译码器的数据结构及其在C 语言中的实现。

数据结构实验哈夫曼树及哈夫曼编码c语言

数据结构实验哈夫曼树及哈夫曼编码c语言

数据结构实验报告:哈夫曼树及哈夫曼编码一、实验目的1. 理解哈夫曼树及哈夫曼编码的概念和原理;2. 掌握C语言中哈夫曼树及哈夫曼编码的实现方法;3. 分析和讨论哈夫曼编码在实际应用中的优势和不足。

二、实验内容和步骤1. 哈夫曼树的构建1.1 通过C语言实现哈夫曼树的构建算法;1.2 输入一组权值,按哈夫曼树构建规则生成哈夫曼树;1.3 输出生成的哈夫曼树结构,并进行可视化展示。

2. 哈夫曼编码的实现2.1 设计哈夫曼编码的实现算法;2.2 对指定字符集进行编码,生成哈夫曼编码表;2.3 对给定字符串进行哈夫曼编码,并输出编码结果。

三、实验过程及结果1. 哈夫曼树的构建在C语言中,通过定义结构体和递归算法实现了哈夫曼树的构建。

根据输入的权值,依次选择权值最小的两个节点构建新的父节点,直至构建完成整棵哈夫曼树。

通过调试和可视化展示,确认了程序正确实现了哈夫曼树的构建。

2. 哈夫曼编码的实现经过分析和设计,利用哈夫曼树的特点实现了哈夫曼编码的算法。

根据生成的哈夫曼树,递归地生成字符对应的哈夫曼编码,并输出编码结果。

对指定的字符串进行了编码测试,验证了哈夫曼编码的正确性和有效性。

四、实验结果分析1. 哈夫曼编码在数据传输和存储中具有较高的压缩效率和可靠性,能够有效减少数据传输量和存储空间;2. 哈夫曼树及哈夫曼编码在通信领域、数据压缩和加密等方面有着广泛的应用和重要意义;3. 在实际应用中,哈夫曼编码的构建和解码算法需要较大的时间和空间复杂度,对于大规模数据的处理存在一定的局限性。

五、实验总结通过本次实验,深入理解了哈夫曼树及哈夫曼编码的理论知识,并掌握了C语言中实现哈夫曼树及哈夫曼编码的方法。

对哈夫曼编码在实际应用中的优势和局限性有了更深入的认识,这对今后的学习和工作有着积极的意义。

六、参考文献1. 《数据结构(C语言版)》,严蔚敏赵现军著,清华大学出版社,2012年;2. 《算法导论》,Thomas H. Cormen 等著,机械工业出版社,2006年。

哈夫曼编码的C语言实现

哈夫曼编码的C语言实现

哈夫曼编码的C语言实现一、大致思路输入信源符号的概率,构造哈夫曼树,从叶子结点到根结点进行编码二、编码实现#include <stdio.h>#define n 7 //leaf number#define m 2*n-1 //all numbertypedef struct{char ch;double weight;int left;int right;int parent;}Node;typedef struct{char ch;int codeis[50];int start;}Code;void HuffmanTree (Node node[],int number){int i,j,x1=0,x2=0;double m1,m2;for(i=0;i<n-1;i++){ //loop n-1m1=m2=1; //least probability p<1//m1 最小 m2第二小for(j=0;j<n+i;j++){if(node[j].weight <m1 && node[j].parent ==-1){m2=m1;x2=x1;m1=node[j].weight;x1=j;} //是最小的else if(node[j].weight <m2 &&node[j].parent ==-1){m2=node[j].weight;x2=j;}} //找结点node[x1].parent = number+i;node[x2].parent = number+i;node[number+i].weight = node[x1].weight + node[x2].weight;node[number+i].left = x1;node[number+i].right = x2;}//end for}int main(int argc, const char * argv[]) {double x[n]={0};printf("请输入%d个符号的概率",n);int i;for(i=0;i<n;i++){scanf("%lf",&x[i]);}Node node[2*n-1]; // 2*len-1 is the number of all nodefor(i=0;i<2*n-1;i++){node[i].weight = 0;node[i].left = -1;node[i].right = -1;node[i].parent = -1;} //initializefor(i=0;i<n;i++){node[i].weight=x[i];}Code code[n],tempcode; //save the code of leafHuffmanTree(node,n); //创建好了哈夫曼树//编码int p,c,j=0;for(i=0;i<n;i++){c=i;tempcode.start = n-1;p=node[c].parent;while(p!=-1){if(node[p].left == c)tempcode.codeis[tempcode.start] = 1; elsetempcode.codeis[tempcode.start] = 0; tempcode.start--;c=p;p=node[c].parent;} //end whilefor(j=tempcode.start+1;j<n;j++){code[i].codeis[j]=tempcode.codeis[j];}//保存下载刚才的结果code[i].start = tempcode.start;} //end forfor (i=0;i<n;i++){for (j=code[i].start+1;j<n;j++){printf("%d",code[i].codeis[j]);}printf("\n");}getchar();return 0;}三、总结1.创建了哈夫曼树,n是叶子结点数。

赫夫曼编码_数据结构(C语言版)_[共2页]

赫夫曼编码_数据结构(C语言版)_[共2页]

00010010101100 报文总长 14 位,对方接收时,可按二位一分进行译码。然而,在传送报文时,总是希 望其长度尽可能地短。如果对每个字符设计长度不等的编码,且让报文中出现次数较多的字 符采用尽可能短的编码,则传送报文的总长便可减少。如果设计如下的不等长编码:
A:0 B:00 C:1 D:01 则上述 7 个字符的报文为:
000011010
但是,这样的报文无法翻译,例如,传送过去的字符串中前 4 个字符的子串“0000”就
可有多种译法,或是“AAAA”,或是“ABA”,也可以是“BB”等。因此,若要设计长短不
等的编码,必须满足一个条件:任何一个字符的编码都不是另一个字符的编码的前缀,把满
足这个条件的编码称做前缀编码。
可以利用二叉树来设计二进制的前缀编码。假设有一棵如图 5.28 所示的二叉树,其 4 个
叶子结点分别表示 A、B、C、D 这 4 个字符,且约定左分支标记为 0,右分支标记为 1,则
根结点到每个叶子结点路径上的 0、1 序列即为相应字符的编码。
读者可以证明,如此得到的必为二进制前缀编码。由图 5.28 所得 A、
B、C、D 的二进制前缀编码分别为 0、10、110 和 111。
又如何得到使报文总长最短的二进制前缀编码呢?假设每种
字符在电文中出现的次数为wi,其编码长度为li,电文中只有n种字
n
∑ 符,则电文总长为 wili 。对应到二叉树上,若置wi为叶子结点的
图 5.28 前缀编码示例
i =1
n
∑ 权,li恰为从根到叶子的路径长度。则 wili 恰为二叉树上带权路径长度。由此可见,设计
i =1
报文总长最短的二进制前缀编码问题,就是以n种字符出现的频率作权设计一棵赫夫曼树的
  1. 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
  2. 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
  3. 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。

课程设计报告课程设计题目:赫夫曼编码系统****:**专业:计算机科学与技术班级:1120702学号:****************:***2012年06 月20 日目录一、设计要求------------------------------------2二、存储结构------------------------------------2三、设计思想------------------------------------21、设计包含的几个部分-----------------------22、流程图-----------------------------------3四、详细设计------------------------------------4五、算法复杂度分析------------------------------8六、显示结果------------------------------------9七、心得体会------------------------------------11八、附录:源程序代码----------------------------11一、设计要求赫夫曼树任务:建立建立最优二叉树函数要求:可以建立函数输入二叉树,实现赫夫曼树的编码和译码系统,重复地显示并处理编码/解码功能,直到选择退出为止。

二、存储结构:在本次课程设计中,每一个字符的信息用一个结构体存储,包含结点值、权值、双亲结点、左孩子结点、右孩子结点等数据。

赫夫曼码和所有字符都是用一个一维数组建立存储的,所以本次课程设计的存储结构是顺序存储。

三、设计思想哈夫曼编译码系统的主要功能是先建立哈夫曼树,然后利用建好的哈夫曼树生成哈夫曼编码后进行译码。

在通信中可以采用0和1的不同排列来表示不同的字符,称为二进制编码。

而赫夫曼树在数据编码中的应用是数据的最小冗余编码问题他是数据压缩学的基础。

若每个字符出现的频率相同,则可以采用等长的二进制编码,频率不同,采用不等长的二进制编码,频率达的字符采用位数较少的编码,频率小的采用位数较多的编码。

赫夫曼编码就是一种不等长的二进制编码,而赫夫曼树是一种最优二叉树,它的编码也是一种最优编码。

在赫夫曼树中,规定往左编码为0,往右编码为1,则得到叶子节点的编码为从根结点带叶子结点中所有路径中0和1的顺序排列。

(1)设计包含的几个方面:①赫夫曼树的构造假设有n个权值,则构造出的赫夫曼树有n个叶子结点。

n个权值分别为w1,w2,………wn,则赫夫曼树构造规则为:1、将w1,w2,…….wn,看成有n棵树的森林。

2、在森林中选出两个根结点最小的树合并,作为一棵新树的左右子书,且新树根结点权值为左右子树根结点权值之和。

3、从森林中删除选取的两棵树,并将新树加入森林。

4、重复2和3步骤,直到森林中只剩一棵树为止。

②赫夫曼编码要求电文的赫夫曼编码,必须先定义赫夫曼编码类型,根据设计要求和实际需要定义的类型如下:typedet struct {char ch; // 存放编码的字符char bits[N+1]; // 存放编码位串int len; // 编码的长度}CodeNode; // 编码结构体类型③代码文件的译码在通信中,若将字符用赫夫曼编码形式发送出去,对方接收到编码后将编码还原成字符。

译码的基本思想是:读文件中编码,并与原先生成的赫夫曼编码表比较,遇到相等时,即取出其对应的字符存入一个新串中。

(2)其主要流程图如图所示。

四、详细设计(1)①赫夫曼树的存储结构描述为:#define N 50 // 叶子结点数#define M 2*N-1 // 赫夫曼树中结点总数typedef struct {int weight; // 叶子结点的权值int lchild, rchild, parent; // 左右孩子及双亲指针}HTNode; // 树中结点类型typedef HTNode HuffmanTree[M+1];②哈弗曼树的算法void CreateHT(HTNode ht[],int n) //调用输入的数组ht[],和节点数n{int i,k,lnode,rnode;int min1,min2;for (i=0;i<2*n-1;i++)ht[i].parent=ht[i].lchild=ht[i].rchild=-1; //所有结点的相关域置初值-1 for (i=n;i<2*n-1;i++) //构造哈夫曼树{min1=min2=32767; //int的范围是-32768—32767lnode=rnode=-1; //lnode和rnode记录最小权值的两个结点位置for (k=0;k<=i-1;k++){if (ht[k].parent==-1) //只在尚未构造二叉树的结点中查找{if (ht[k].weight<min1) //若权值小于最小的左节点的权值{min2=min1;rnode=lnode;min1=ht[k].weight;lnode=k;}else if (ht[k].weight<min2){min2=ht[k].weight;rnode=k;}}}ht[lnode].parent=i;ht[rnode].parent=i; //两个最小节点的父节点是iht[i].weight=ht[lnode].weight+ht[rnode].weight; //两个最小节点的父节点权值为两个最小节点权值之和ht[i].lchild=lnode;ht[i].rchild=rnode; //父节点的左节点和右节点}}(2)哈弗曼编码void CreateHCode(HTNode ht[],HCode hcd[],int n){int i,f,c;HCode hc;for (i=0;i<n;i++) //根据哈夫曼树求哈夫曼编码{hc.start=n;c=i;f=ht[i].parent;while (f!=-1) //循序直到树根结点结束循环{if (ht[f].lchild==c) //处理左孩子结点hc.cd[hc.start--]='0';else //处理右孩子结点hc.cd[hc.start--]='1';c=f;f=ht[f].parent;}hc.start++; //start指向哈夫曼编码hc.cd[]中最开始字符hcd[i]=hc;}}void DispHCode(HTNode ht[],HCode hcd[],int n) //输出哈夫曼编码的列表{int i,k;printf(" 输出哈夫曼编码:\n");for (i=0;i<n;i++) //输出data中的所有数据,即a-z printf(" %c:\t",ht[i].data);for (k=hcd[i].start;k<=n;k++) //输出所有data中数据的编码{printf("%c",hcd[i].cd[k]);}printf("\n");}}void editHCode(HTNode ht[],HCode hcd[],int n) //编码函数{char string[MAXSIZE];int i,j,k;scanf("%s",string); //把要进行编码的字符串存入string数组中printf("\n输出编码结果:\n");for (i=0;string[i]!='#';i++) //#为终止标志{for (j=0;j<n;j++){if(string[i]==ht[j].data) //循环查找与输入字符相同的编号,相同的就输出这个字符的编码{for (k=hcd[j].start;k<=n;k++){printf("%c",hcd[j].cd[k]);}break; //输出完成后跳出当前for循环}}}}(3)哈弗曼译码void deHCode(HTNode ht[],HCode hcd[],int n) //译码函数{char code[MAXSIZE];int i,j,l,k,m,x;scanf("%s",code); //把要进行译码的字符串存入code数组中while(code[0]!='#')for (i=0;i<n;i++){m=0; //m为想同编码个数的计数器for (k=hcd[i].start,j=0;k<=n;k++,j++) //j为记录所存储这个字符的编码个数{if(code[j]==hcd[i].cd[k]) //当有相同编码时m值加1m++;}if(m==j) //当输入的字符串与所存储的编码字符串个数相等时则输出这个的data数据{printf("%c",ht[i].data);for(x=0;code[x-1]!='#';x++) //把已经使用过的code数组里的字符串删除{code[x]=code[x+j];}}}}(4)主函数void main(){int n=26,i;char orz,back,flag=1;char str[]={'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','q','r','s','t','u','v','w','x','y','z'}; //初始化int fnum[]={186,64,13,22,32,103,21,15,47,57,1,2,32,20,57,63,15,1,48,51,80,23,8,18,1,16}; //初始化HTNode ht[M]; //建立结构体HCode hcd[N]; //建立结构体for (i=0;i<n;i++) //把初始化的数据存入ht结构体中{ht[i].data=str[i];ht[i].weight=fnum[i];}while (flag) //菜单函数,当flag为0时跳出循环(5)显示部分源程序:{printf(" 欢迎使用赫夫曼编译系统\n");printf(" 制作人:章建\n");printf(" *************************************************\n");printf(" 1:显示编码\n ");printf(" 2:进行编码\n");printf(" 3:进行译码\n");printf(" 0:退出\n");printf(" *************************************************\n");printf(" 请输入选择的编号:");scanf("%c",&orz);switch(orz){case '1':system("cls"); //清屏函数CreateHT(ht,n);CreateHCode(ht,hcd,n);DispHCode(ht,hcd,n);printf("\n按任意键返回...");getch();system("cls");break;case '2':system("cls");printf("请输入要进行编码的字符串(以#结束,字符为小写英文字母):\n");CreateHT(ht,n);CreateHCode(ht,hcd,n);editHCode(ht,hcd,n);printf("\n按任意键返回...");getch();system("cls");break;case '3':system("cls");CreateHT(ht,n);CreateHCode(ht,hcd,n);DispHCode(ht,hcd,n);printf("请输入编码(以#结束):\n");deHCode(ht,hcd,n);printf("\n按任意键返回...");getch();system("cls");break;case '0':flag=0;printf(" 感谢您的使用!\n");break;default:system("cls");}}}五、算法复杂度分析:void editHCode(HTNode ht[],HCode hcd[],int n) //编码函数void deHCode(HTNode ht[],HCode hcd[],int n) //译码函数这两个被调函数里面都用了三重循环,其他的调用函数或者主函数都是一重或二重循环,所以算法复杂度为o(n^3)。

相关文档
最新文档