哈夫曼树的建立及哈弗曼编码的构造

哈夫曼树的建立及哈弗曼编码的构造
哈夫曼树的建立及哈弗曼编码的构造

《数据结构》课程设计报告完成日期:2012-07-11

\

目录

1 实验目的?????????????????????????????????????????????3

2 问题描述?????????????????????????????????????????????

3 3算法的思想与算法实现步骤?????????????????????????? 3

4 程序核心代码及主要设计??????????????????????????????4

4.1哈夫曼树节点的数据类型定义:?????????????????????4

4.2初始化哈夫曼树……???…???????…????????…????????5

4.3选权值最小函数???????????????????????????????????5

4.4创建哈夫曼树的函数:?????????????????????????????6

4.5打印输出哈夫曼树,字符,权值,以及它对应的编码:??6

4.6编码的重要哈夫曼树路径递归算法:??????????????????7

4.7对字符进行初始编码:????????????????????????…????7

4.8 encoding 编码功能:对输入字符进行编码?????????????7

4.9对输入的字符进行解码:????????????????????????…????8

4.10 主函数体???????????????????????…????????????????9

5 程序运行结果???????????????????----??????????????????10

6. 实验总结????????????????????????????????????????????13

1. 实验目的

掌握哈夫曼树的建立及哈夫曼编码的生成方法;首先输入字符和对应的权值,

打印输出哈夫曼树和字符的编码;然后输入一字符串,对其进行编码;最后输

入由0、1组成的字符串,实现对其的译码!

2. 问题描述

利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降

低传输成本。这要求在发送端通过一个编码系统对待传输数据预先编码,在接收

端将传来的数据进行译码(复原)。对于双工信道(即可以双向传输信息的信道),

每端都需要一个完整的编/译码系统。试为这样的信息收发站编写一个赫夫曼码

的编/译码系统。

用下表给出的字符集和频度的实际统计数据建立哈夫曼树,并实现以下报文的编

码和译码:“THIS PROGRAM IS MY FAVORITE”。

字符空格 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

3. 算法的思想与算法实现步骤

1)主要思想:

根据给定的字符和其中每个字符的频度,构造哈夫曼树,并输出字

符集中每个字符的哈夫曼编码.将给定的字符串根据其哈夫曼编码进行编码,并

进行相应的译码.

2)基本框架:

函数名属性功能

inithfmt(hfmt t) t[i].weight=0;t[i].lchild= -1;

t[i].rchild= -1; t[i].parent= -1; 对结构体htnode 初始化,实现父子结点的初始值

inputweight(hfmt t)/ int w;//w权值char k;//字符

t[i].key=k; t[i].weight=w; 自定义输入函数,输入对应的字符和权值。

selectmin(hfmt t,int i,int *p1,int *p2) long min1=999999;

long min2=999999;

每次选权值最小、次小的

结点使之成为新结点。

creathfmt(hfmt t) t[i].lchild=p1;t[i].rchild=p2;

t[i].weight=t[p1].weight+t[p2].

weight;

创建哈夫曼树的函数

printhfmt(hfmt t) printf("\t\t权值\t父母\t左孩

子\t右孩子\t字符\t");

打印哈夫曼树

hfmtpath(hfmt t,int i,int j) hfmtpath(t,i,j);if(t[b].lchild==a

) printf("0");else printf("1");

哈夫曼树编码路径的递

归算法.

phfmnode(hfmt t) printf("\t\t%c\t",t[i].key,t[i].we

对字符进行初始编码

ight); hfmtpath(t,i,j);

encoding(hfmt t) if(r[j]==t[i].key)hfmtpath(t,i,j); 对输入的电文进行编码decoding(hfmt t) j=2*n-2;//j从树的根节点开始对用户输入的密文进行

int main() hfmt ht; char flag; 主菜单输出

3)系统结构图(功能模块图)

4.程序核心代码及主要设计

1.哈夫曼树节点的数据类型定义:

代码:

typedef struct

{

int weight;

int lchild;

int rchild;

int parent;

char key;

}htnode;

2、void inithfmt(hfmt t)初始化哈夫曼树,处理 inputweight(hfmt t)函数得到的数据,按照哈夫曼规则建立2叉树。此函数块调用了selectmin()函数。

代码:

void inithfmt(hfmt t)//对结构体进行初始化

{

int i;

printf("\n请输入要设置的叶子结点个数n=");

scanf("%d",&n);

getchar();

for(i=0;i<2*n-1;i++)//对结构体进行初始化

{

t[i].weight=0;

t[i].lchild=-1;

t[i].rchild=-1;

t[i].parent=-1;

}

printf("\n");}

void inputweight(hfmt t)//输入函数

{

int w;//w表示权值

int i;

char k;//k表示获取的字符

for(i=0;i

{

printf("请输入第%d个字符:",i+1);

scanf("%c",&k);

getchar();

t[i].key=k;

printf("请输入第%d个字符的权值:",i+1);

scanf("%d",&w);

getchar();

t[i].weight=w; } }

3、selectmin(hfmt t,int i,int *p1,int *p2) //Select 函数,选出t树到a为止,权值最小且parent为0的2个节点. 代码:

void selectmin(hfmt t,int i,int *p1,int *p2)//选中两个权值最小的函数{

long min1=999999;

long min2=999999;

int j;

for(j=0;j<=i;j++)//选择最小权值字符的下标返回

if(t[j].parent==-1)

if(min1>t[j].weight)

{

min1=t[j].weight;

*p1=j;

}

for(j=0;j<=i;j++)//选择次小权值字符的下标还回

if(t[j].parent==-1)

if(min2>t[j].weight && j!=(*p1))//注意 j!=(*p1))

{

min2=t[j].weight;

*p2=j; } }

4、创建哈夫曼树的函数

代码:

void creathfmt(hfmt t)//

{

int i,p1,p2;

inithfmt(t);

inputweight(t);

for(i=n;i<2*n-1;i++)

{

selectmin(t,i-1,&p1,&p2);

t[p1].parent=i;

t[p2].parent=i;

t[i].lchild=p1;

t[i].rchild=p2;

t[i].weight=t[p1].weight+t[p2].weight; }}

5、打印输出哈夫曼树,字符,权值,以及它对应的编码

代码:

void printhfmt(hfmt t)

{

int i;

printf(" *******由哈夫曼编码建立的图表结构如下:*******\n");

printf("\t\t权值\t父母\t左孩子\t右孩子\t字符\t");

for(i=0;i<2*n-1;i++)

{

printf("\n");

printf("\t\t%d\t%d\t%d\t%d\t%c",t[i].weight,t[i].parent,t[i].lchild,t

[i].rchild,t[i].key); }

printf("\n\n"); }

6、编码的重要哈夫曼树路径递归算法

代码:

void hfmtpath(hfmt t,int i,int j)

{

int a,b;

a=i;

b=j=t[i].parent;

if(t[j].parent!=-1)

{ i=j;

hfmtpath(t,i,j); }

if(t[b].lchild==a)

printf("0");

else

printf("1");}

7、对字符进行初始编码

代码:

void phfmnode(hfmt t)//

{

int i,j,a;

printf(" ***所得哈夫曼编码为***\n"); for(i=0;i

{

j=0;

printf("\n");

printf("\t\t%c\t",t[i].key,t[i].weight);

hfmtpath(t,i,j); }

printf("\n\n"); }

8、encoding

编码功能:对输入字符进行编码

void encoding(hfmt t)//对用户输入的电文进行编码

{

char r[1000];//用来存储输入的字符串

int i,j;

printf("\n\n请输入需要编码的字符:");

gets(r);

printf("编码结果为:");

for(j=0;r[j]!='\0';j++)

for(i=0;i

if(r[j]==t[i].key)

hfmtpath(t,i,j);

printf("\n"); }

9、decoding

译码功能:输入0-1字符组成的字符串,然后对其解码输出对应的字符!

void decoding(hfmt t)//对用户输入的密文进行译码

{

char r[100];

int i,j,len;

j=2*n-2;//j初始从树的根节点开始

printf("\n\n请输入需要译码的字符串:");

gets(r);

len=strlen(r);

printf("译码的结果是:");

for(i=0;i

{

if(r[i]=='0')

{ j=t[j].lchild;

if(t[j].lchild==-1)

{

printf("%c",t[j].key);

j=2*n-2; } }

else if(r[i]=='1')

{ j=t[j].rchild;

if(t[j].rchild==-1)

{

printf("%c",t[j].key);

j=2*n-2; } } }

printf("\n\n"); }

10、主函数:

int main()

{

int i,j;

hfmt ht;

char flag;

printf(" |----------------------|\n"); printf(" |信计1001--王向前--11号|\n"); printf(" |**********************|\n"); printf(" | 哈夫曼编码课程设计 |\n"); printf(" |**********************|\n"); printf(" |设计完成时间:2012/7/10|\n"); printf(" |----------------------|\n"); while(1){

printf("********************初始化&&打印&&编码&&译码&&退出*********************\n");

printf(" |【1】初始化\n");

printf(" |【2】打印\n");

printf(" |【3】编码\n");

printf(" |【4】译码\n");

printf(" |【0】退出\n");

printf("\n请输入您的选择:");

flag=getchar();

getchar();

switch(flag)

{

case '1':

creathfmt(ht);break;

case '2':

{

printhfmt(ht);

phfmnode(ht); }

break;

case '3':

encoding(ht);break;

case '4':

decoding(ht);break;

case '0':

exit(0);break;

default:

printf("您的输入有误,请重新输入。\n"); }}} 5.程序运行结果及图形界面

6.实验总结(实验结果分析、实验心得体会)

1、算法结果分析

本程序实现了通过字符的不同权值来建立哈夫曼树来进行字符的编码,再用图表输出哈夫曼树,然后根据所得编码进行文件编码和文件译码。从功能来看,基本上符合实验要求的程序功能,能较好的应用于实际生活中,对于信息的传递,和英文字母的译码和解码有很好的用处!但就从哈夫曼编码—译码器的功能而言还需改进。

2、实验心得:

通过编写程序,实现哈夫曼树的建立及哈弗曼编码的构造上学到不少细节问题解决的方法,积累了独立思考问题和解决问题的些许能力。

贪心算法构造哈夫曼树

软件02 1311611006 张松彬利用贪心算法构造哈夫曼树及输出对应的哈夫曼编码 问题简述: 两路合并最佳模式的贪心算法主要思想如下: (1)设w={w0,w1,......wn-1}是一组权值,以每个权值作为根结点值,构造n棵只有根的二叉树 (2)选择两根结点权值最小的树,作为左右子树构造一棵新二叉树,新树根的权值是两棵子树根权值之和 (3)重复(2),直到合并成一颗二叉树为 一、实验目的 (1)了解贪心算法和哈夫曼树的定义(2)掌握贪心法的设计思想并能熟练运用(3)设计贪心算法求解哈夫曼树(4)设计测试数据,写出程序文档 二、实验内容 (1)设计二叉树结点数据结构,编程实现对用户输入的一组权值构造哈夫曼树(2)设计函数,先序遍历输出哈夫曼树各结点3)设计函数,按树形输出哈夫曼树 代码: #include #include #include #include typedef struct Node{ //定义树结构 int data; struct Node *leftchild; struct Node *rightchild; }Tree; typedef struct Data{ //定义字符及其对应的频率的结构 int data;//字符对应的频率是随机产生的 char c; }; void Initiate(Tree **root);//初始化节点函数 int getMin(struct Data a[],int n);//得到a中数值(频率)最小的数 void toLength(char s[],int k);//设置有k个空格的串s void set(struct Data a[],struct Data b[]);//初始化a,且将a备份至b char getC(int x,struct Data a[]);//得到a中频率为x对应的字符 void prin(struct Data a[]);//输出初始化后的字符及对应的频率 int n; void main() { //srand((unsigned)time(NULL));

实验六 哈夫曼树及哈夫曼编码

#include #include #include #define n 6 /* 叶子数目*/ #define m 2*n-1 /* 结点总数*/ #define Maxval 1 /* 最大权值*/ typedef char datatype; typedef struct //定义为结构类型 { float weight; //权值 datatype data; int lchild, rchild, parent; } hufmtree; hufmtree tree[m]; typedef struct { char bits[n]; /* 编码数组位串,其中n为叶子结点数目*/ int start; /* 编码在位串的起始位置*/ datatype data; } codetype; codetype code[n]; HUFFMAN(hufmtree tree[ ]) { int i, j, p1,p2; char ch; float small1,small2,f; for( i=0; i

哈夫曼树编码译码实验报告(DOC)

数据结构课程设计设计题目:哈夫曼树编码译码

目录 第一章需求分析 (1) 第二章设计要求 (1) 第三章概要设计 (2) (1)其主要流程图如图1-1所示。 (3) (2)设计包含的几个方面 (4) 第四章详细设计 (4) (1)①哈夫曼树的存储结构描述为: (4) (2)哈弗曼编码 (5) (3)哈弗曼译码 (7) (4)主函数 (8) (5)显示部分源程序: (8) 第五章调试结果 (10) 第六章心得体会 (12) 第七章参考文献 (12) 附录: (12)

在当今信息爆炸时代,如何采用有效的数据压缩技术节省数据文件的存储空间和计算机网络的传送时间已越来越引起人们的重视,哈夫曼编码正是一种应用广泛且非常有效的数据压缩技术。哈夫曼编码是一种编码方式,以哈夫曼树—即最优二叉树,带权路径长度最小的二叉树,经常应用于数据压缩。哈弗曼编码使用一张特殊的编码表将源字符(例如某文件中的一个符号)进行编码。这张编码表的特殊之处在于,它是根据每一个源字符出现的估算概率而建立起来的(出现概率高的字符使用较短的编码,反之出现概率低的则使用较长的编码,这便使编码之后的字符串的平均期望长度降低,从而达到无损压缩数据的目的)。哈夫曼编码的应用很广泛,利用哈夫曼树求得的用于通信的二进制编码称为哈夫曼编码。树中从根到每个叶子都有一条路径,对路径上的各分支约定:指向左子树的分支表示“0”码,指向右子树的分支表示“1”码,取每条路径上的“0”或“1”的序列作为和各个叶子对应的字符的编码,这就是哈夫曼编码。哈弗曼译码输入字符串可以把它编译成二进制代码,输入二进制代码时可以编译成字符串。 第二章设计要求 对输入的一串电文字符实现哈夫曼编码,再对哈夫曼编码生成的代码串进行译码,输出电文字符串。通常我们把数据压缩的过程称为编码,解压缩的过程称为解码。电报通信是传递文字的二进制码形式的字符串。但在信息传递时,总希望总长度能尽可能短,即采用最短码。假设每种字符在电文中出现的次数为Wi,编码长度为Li,电文中有n种字符,则电文编码总长度为∑WiLi。若将此对应到二叉树上,Wi为叶结点的权,Li为根结点到叶结点的路径长度。那么,∑WiLi 恰好为二叉树上带权路径长度。因此,设计电文总长最短的二进制前缀编码,就是以n种字符出现的频率作权,构造一棵哈夫曼树,此构造过程称为哈夫曼编码。设计实现的功能: (1) 哈夫曼树的建立; (2) 哈夫曼编码的生成; (3) 编码文件的译码。

哈夫曼树的编码与译码

目录 一、摘要 (3) 二、题目 (3) 三、实验目的 (3) 四、实验原理 (3) 五、需求分析 (4) 5.1实验要求 (4) 5.2实验内容 (4) 六、概要设计 (4) 6.1所实现的功能函数 (4) 6.2主函数 (5) 6.3 系统结构图 (6) 七、详细设计和编码 (6) 八、运行结果 (12) 九、总结 (15) 9.1调试分析 (15) 9.2 心得体会 (15) 参考文献 (16)

一、摘要 二、题目 哈夫曼树的编码与译码 三、实验目的 (1)熟悉对哈夫曼的应用以及构造方法,熟悉对树的构造方式的应用; (2)进一步掌握哈夫曼树的含义; (3)掌握哈夫曼树的结构特征,以及各种存储结构的特点以及使用范围; (4)熟练掌握哈夫曼树的建立和哈夫曼编码方法; (5)提高分析问题、解决问题的能力,进一步巩固数据结构各种原理与方法; (6)掌握一种计算机语言,可以进行数据算法的设计。 四、实验原理 哈夫曼(Huffman)编码属于长度可变的编码类,是哈夫曼在1952年提出的一种编码方法,即从下到上的编码方法。同其他码词长度一样,可区别的不同码词的生成是基于不同符号出现的不同概率。生成哈夫曼编码算法基于一种称为“编码树”(coding tree)的技术。算法步骤如下: (1)初始化,根据富豪概率的大小按由大到小顺序对符号进行排序; (2)把概率最小的两个符号组成一个新符号(节点),即新符号的概率等于这两个符号概率之和; (3)重复第(2)步,直到形成一个符号为止(树),其概率最后等于1; (4)从编码树的根开始回溯到原始的符号,并将每一下分支赋值1,上分支赋值0; 译码的过程是分解电文中字符串,从根出发,按字符“0”或者“1”确定找做孩 子或右孩子,直至叶子节点,便求得该子串相应的字符。

哈夫曼树的建立与操作

实验六哈夫曼树的建立与操作 一、实验要求和实验内容 1、输入哈夫曼树叶子结点(信息和权值) 2、由叶子结点生成哈夫曼树内部结点 3、生成叶子结点的哈夫曼编码 4、显示哈夫曼树结点顺序表 二、详细代码(内包含了详细的注释): #include using namespace std; typedef char Elemtype; struct element { int weight; Elemtype date; element* lchild,*rchild; }; class HuffmanTree { public: HuffmanTree()//构造函数 { cout<<"请输入二叉树的个数"<>count; element *s=new element[count];//s为指向数组的指针,保存指向数组的地址 for(int i=0;i>s[i].weight;

cout<<"输入第"<>s[i].date; s[i].lchild=NULL; s[i].rchild=NULL; }//以上为初始化每一个结点 element * *m=new element*[count];//m为指向数组成员的地址的指针,保存【指向数组成员地址的指针】的地址 for(int i=0;iweightweight; return1=i; } } for(int i=0;iweightweight>a) { b=m[i]->weight; return2=i; } } q=new element;//构建一棵新树 q->weight=m[return1]->weight+m[return2]->weight; q->lchild=m[return1]; q->rchild=m[return2]; m[return1]=q; m[return2]=NULL; //用新树替换原来的两子树,并置空一个数 } boot=q;//把最后取得的哈夫曼树的头结点即q赋值给boot

实验四 哈夫曼树与哈夫曼编码

实验四哈夫曼树与哈夫曼编码 一、实验目的 1、使学生熟练掌握哈夫曼树的生成算法。 2、熟练掌握哈夫曼编码的方法。 二、实验内容 [问题描述] 已知n个字符在原文中出现的频率,求它们的哈夫曼编码。[基本要求] 1. 初始化:从键盘读入n个字符,以及它们的权值,建立Huffman 树。(具体算法可参见教材P147的算法6.12) 2. 编码:根据建立的Huffman树,求每个字符的Huffman 编码。 对给定的待编码字符序列进行编码。 [选作内容] 1. 译码:利用已经建立好的Huffman树,对上面的编码结果译码。 译码的过程是分解电文中的字符串,从根结点出发,按字符’0’和’1’确定找左孩子或右孩子,直至叶结点,便求得该子串相应的字符。 4. 打印 Huffman树。 [测试数据] 利用教材P.148 例6-2中的数据调试程序。可设8种符号分别为A,B,C,D,E,F,G,H。编/译码序列为“CFBABBFHGH”(也可自己设定数据进行测试)。

三、算法设计 1、主要思想:******************赫夫曼树的构造 ********************** (1) 由给定的 n 个权值{w1, w2, …, wn},构造具有 n 棵二 叉树的森林 F ={T1, T2, …, Tn },其中每棵二叉树 Ti 只有一个带权为 wi 的根结点, 其左、右子树均为空。 (2) 在 F 中选取两棵根结点的权值最小的二叉树, 作为 左、右子树构造一棵新的二叉树。置新的二叉树的根结点的权值为其左、右子树上根结点的权值之和。 (3)在 F 中删去这两棵二叉树, 把新的二叉树加入F。 (4)重复(2)和(3), 直到 F 中仅剩下一棵树为止。 ****************************霍夫曼编码***************************** 主要用途是实现数据压缩。由于赫夫曼树中没有度为1的节点,则一棵有n个叶子结点的赫夫曼树共有2n-1个结点,可以存储在一个大小为2n-1的一维数 组中。由于在构成赫夫曼树之后,为求编码需从叶子结点出发走一条从叶子到根的路径;而为译码需从根出发走一条从根到叶子的路径。则对每个结点而言,既须知双亲的信息,又需知孩子结点的信息。 2、本程序包含三个模块 1)主函数 Int main() { 先输入结点总数; 分别输入各个结点; 调用建立哈夫曼树函数; 调用编码函数读入建立的哈夫曼树进行编码 } 3、元素类型、结点类型和指针类型 typedef struct //定义新数据类型即结点结构

数据结构哈夫曼树的实现

#include #include #include #include using namespace std; typedef struct { unsigned int weight; unsigned int parent,lchild,rchild,ch; }HTNode,*HuffmanTree; //动态分配数组存储哈夫曼树 typedef char *HuffmanCode; //动态分配数组存储哈夫曼编码表 int m,s1,s2; HuffmanTree HT; void Select(int n){ //选择两个权值最小的结点 int i,j; for(i=1;i<=n;i++){ if(!HT[i].parent){ s1 = i;break; } } for(j=i+1;j<=n;j++){ if(!HT[j].parent){ s2 = j;break; } } for(i=1;i<=n;i++){ if((HT[s1].weight>HT[i].weight)&&(!HT[i].parent)&&(s2!=i)){ s1=i; } } for(j=1;j<=n;j++){ if((HT[s2].weight>HT[j].weight)&&(!HT[j].parent)&&(s1!=j)) s2=j; } } void HuffmanCoding(HuffmanCode HC[], int *w, int n) { // w存放n个字符的权值(均>0),构造哈夫曼树HT,// 并求出n个字符的哈夫曼编码HC int i, j; char *cd; int p; int cdlen; int start; if (n<=1) return;

哈夫曼编码算法实现完整版

实验三树的应用 一.实验题目: 树的应用——哈夫曼编码 二.实验内容: 利用哈夫曼编码进行通信可以大大提高信道的利用率,缩短信息传输的时间,降低传输成本。根据哈夫曼编码的原理,编写一个程序,在用户输入结点权值的基础上求哈夫曼编码。 要求:从键盘输入若干字符及每个字符出现的频率,将字符出现的频率作为结点的权值,建立哈夫曼树,然后对各个字符进行哈夫曼编码,最后打印输出字符及对应的哈夫曼编码。 三、程序源代码: #include #include #include #include typedef struct{ char data; int weight; int parent,lchild,rchild; }HTNode,*HuffmanTree; typedef char * * HuffmanCode; void Select(HuffmanTree &HT,int n,int m) {HuffmanTree p=HT; int tmp; for(int j=n+1;j<=m;j++) {int tag1,tag2,s1,s2; tag1=tag2=32767; for(int x=1;x<=j-1;x++) { if(p[x].parent==0&&p[x].weights2) //将选出的两个节点中的序号较小的始终赋给s1 { tmp=s1; s1=s2; s2=tmp;} p[s1].parent=j;

哈夫曼编码与译码的实现

数据结构课程设计评阅书

2011—2012学年第一学期 专业:信息管理与信息系统学号: 1021024016 姓名:万永馨 课程设计名称:数据结构课程设计 设计题目:哈夫曼编码与译码的实现 完成期限:自 2012 年 2 月 20 日至 2012 年 3 月 2 日共 2 周 设计依据、要求及主要内容(可另加附页): 该设计题目将按以下要求完成: 哈夫曼编码与译码是信息传输中应用的经典算法,运用C或VC++结合数据结构等基础知识,按 以下要求编程实现各种进制的转换。 任务要求:1)阐述设计思想,画出流程图;2)需要对哈夫曼编码/译码的相关原理有所了解,设计数 据结构,建立必要的信息数据文件(最好存储成外部文件),并分析完成用户所需的基本操作功能;3)实现给定信息的编码和译码功能;4)应有较好的界面设计,说明程序测试方法;5)按照格式要 求完成课程设计说明书。 设计要求: 1)问题分析和任务定义:根据设计题目的要求,充分地分析和理解问题,明确问题要求做什么?(而不是怎么做?)限制条件是什么?确定问题的输入数据集合。 2)逻辑设计:对问题描述中涉及的操作对象定义相应的数据类型,并按照以数据结构为中心的 原则划分模块,定义主程序模块和各抽象数据类型。逻辑设计的结果应写出每个抽象数据类型的定 义(包括数据结构的描述和每个基本操作的功能说明),各个主要模块的算法,并画出模块之间的调 用关系图; 3)详细设计:定义相应的存储结构并写出各函数的伪码算法。在这个过程中,要综合考虑系统 功能,使得系统结构清晰、合理、简单和易于调试,抽象数据类型的实现尽可能做到数据封装,基 本操作的规格说明尽可能明确具体。详细设计的结果是对数据结构和基本操作做出进一步的求精, 写出数据存储结构的类型定义,写出函数形式的算法框架; 4)程序编码:把详细设计的结果进一步求精为程序设计语言程序。同时加入一些注解和断言, 使程序中逻辑概念清楚; 5)程序调试与测试:能够熟练掌握调试工具的各种功能,设计测试数据确保程序正确。调试正 确后,认真整理源程序及其注释,形成格式和风格良好的源程序清单和结果; 6)结果分析:程序运行结果包括正确的输入及其输出结果和含有错误的输入及其输出结果。算 法的时间、空间复杂性分析; 7)编写课程设计报告; 以上要求前三个阶段的任务完成后,将设计说明书的草稿交指导老师面审,审查合格方可进入 后续阶段的工作。设计工作结束,经指导老师验收合格后将设计说明书装订,并答辩。

哈夫曼树建立、哈夫曼编码算法的实现

#include /*2009.10.25白鹿原*/ #include /*哈夫曼树建立、哈夫曼编码算法的实现*/ #include typedef char* HuffmanCode;/*动态分配数组,存储哈夫曼编码*/ typedef struct { unsigned int weight ; /* 用来存放各个结点的权值*/ unsigned int parent, LChild,RChild ; /*指向双亲、孩子结点的指针*/ }HTNode, * HuffmanTree; /*动态分配数组,存储哈夫曼树*/ void select(HuffmanTree *ht,int n, int *s1, int *s2) { int i; int min; for(i=1; i<=n; i++) { if((*ht)[i].parent == 0) { min = i; i = n+1; } } for(i=1; i<=n; i++) { if((*ht)[i].parent == 0) { if((*ht)[i].weight < (*ht)[min].weight) min = i; } } *s1 = min; for(i=1; i<=n; i++) { if((*ht)[i].parent == 0 && i!=(*s1)) { min = i; i = n+1; } } for(i=1; i<=n; i++) { if((*ht)[i].parent == 0 && i!=(*s1)) {

if((*ht)[i].weight < (*ht)[min].weight) min = i; } } *s2 = min; } void CrtHuffmanTree(HuffmanTree *ht , int *w, int n) { /* w存放已知的n个权值,构造哈夫曼树ht */ int m,i; int s1,s2; m=2*n-1; *ht=(HuffmanTree)malloc((m+1)*sizeof(HTNode)); /*0号单元未使用*/ for(i=1;i<=n;i++) {/*1-n号放叶子结点,初始化*/ (*ht)[i].weight = w[i]; (*ht)[i].LChild = 0; (*ht)[i].parent = 0; (*ht)[i].RChild = 0; } for(i=n+1;i<=m;i++) { (*ht)[i].weight = 0; (*ht)[i].LChild = 0; (*ht)[i].parent = 0; (*ht)[i].RChild = 0; } /*非叶子结点初始化*/ /* ------------初始化完毕!对应算法步骤1---------*/ for(i=n+1;i<=m;i++) /*创建非叶子结点,建哈夫曼树*/ { /*在(*ht)[1]~(*ht)[i-1]的范围内选择两个parent为0且weight最小的结点,其序号分别赋值给s1、s2返回*/ 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 outputHuffman(HuffmanTree HT, int m) { if(m!=0) {

完整word版数据结构课程设计:电文编码译码哈夫曼编码

福建农林大学计算机与信息学院 数据结构课程设计 设计:哈夫曼编译码器 姓名:韦邦权 专业:2013级计算机科学与技术 学号:13224624 班级:13052316 完成日期:2013.12.28

1 哈夫曼编译码器 一、需求分析 在当今信息爆炸时代,如何采用有效的数据压缩技术节省数据文件的存储空间和计算机网络的传送时间已越来越引起人们的重视,哈夫曼编码正是一种应用广泛且非常有效的数据压缩技术。哈夫曼编码是一种编码方式,以哈夫曼树—即最优二叉树,带权路径长度最小的二叉树,经常应用于数据压缩。哈夫曼编码使用一张特殊的编码表将源字符(例如某文件中的一个符号)进行编码。这张编码表的特殊之处在于,它是根据每一个源字符出现的估算概率而建立起来的(出现概率高的字符使用较短的编码,反之出现概率低的则使用较长的编码,这便使编码之后的字符串的平均期望长度降低,从而达到无损压缩数据的目的)。哈夫曼编码的应用很广泛,利用哈夫曼树求得的用于通信的二进制编码称为哈夫曼编码。树中从根到每个叶子都有一条路径,对路径上的各分支约定:指向左子树的分支表示“0”码,指向右子树的分支表示“1”码,取每条路径上的“0”或“1”的序列作为和

各个叶子对应的字符的编码,这就是哈夫曼编码。哈夫曼译码输入字符串可以把它编译成二进制代码,输入二进制代码时可以编译成字符串。 二、设计要求 对输入的一串电文字符实现哈夫曼编码,再对哈夫曼编码生成的2 代码串进行译码,输出电文字符串。通常我们把数据压缩的过程称为编码,解压缩的过程称为解码。电报通信是传递文字的二进制码形式的字符串。但在信息传递时,总希望总长度能尽可能短,即采用最短码。假设每种字符在电文中出现的次数为Wi,编码长度为Li,电文中有n种字符,则电文编码总长度为∑WiLi。若将此对应到二叉树上,Wi为叶结点的权,Li为根结点到叶结点的路径长度。那么,∑WiLi 恰好为二叉树上带权路径长度。因此,设计电文总长最短的二进制前缀编码,就是以n种字符出现的频率作权,构造一棵哈夫曼树,此构造过程称为哈夫曼编码。设计实现的功能: (1) 哈夫曼树的建立; (2) 哈夫曼编码的生成; (3) 编码文件的译码。 三、概要设计 哈夫曼编\译码器的主要功能是先建立哈夫曼树,然后利用建好的哈夫曼树生成哈夫曼编码后进行译码。 在数据通信中,经常需要将传送的文字转换成由二进制字符0、1组成的二进制串,称之为编码。构造一棵哈夫曼树,规定哈夫曼树中的左分之代表0,右分支代表1,则从根节点到每个叶子节点所经过的

哈夫曼树的编码和译码

#include"stdafx.h" #include"stdio.h" #include"conio.h" #include #include #include using namespace std; #define maxbit 100 #define Maxvalue 2000//最大权值整数常量#define Maxleaf 100//最大叶子结点数 #define size 300//0、串数组的长度 static int n;//实际的叶子结点数 struct HNodeType { int weight; int parent; int lchild; int rchild; int ceng;//结点相应的层数 char ch;//各结点对应的字符 }; struct HCodeType { int bit[maxbit];//存放编码的数组 int start;//编码在数组中的开始位置}; static HNodeType *HuffNode;//定义静态指针HNodeType *init()//初始化静态链表 { HuffNode=new HNodeType[2*n-1]; for(int i=0;i<2*n-1;i++) { HuffNode[i].weight=0; HuffNode[i].parent=-1; HuffNode[i].lchild=-1; HuffNode[i].rchild=-1; HuffNode[i].ceng=-1; HuffNode[i].ch='0'; } return HuffNode; }

实验四 哈夫曼树与哈夫曼编码

实验四哈夫曼树与哈夫曼编码 一、实验内容 [问题描述] 已知n个字符在原文中出现的频率,求它们的哈夫曼编码。[基本要求] 1. 初始化:从键盘读入n个字符,以及它们的权值,建立Huffman 树。(具体算法可参见教材P147的算法6.12) 2. 编码:根据建立的Huffman树,求每个字符的Huffman 编码。 对给定的待编码字符序列进行编码。 二、概要设计 算法设计: 要是实现哈夫曼树的操作,首先创建一个哈夫曼树,在创建哈夫曼树的时候,对哈夫曼树的叶子和非叶子结点进行初始化,而在建立哈夫曼树时,最难的该是选择权值最小的两个顶点,然后两个结点的权值和作为新的权值,再选择两个权值最小的作为新的两个结点创建一个小的二叉树的子树;创建哈夫曼树后,进行编码,在编码过程中,先找到根,然后遍历,左孩子用0标记,右孩子用1标记,最后将编码好的哈夫曼树进行输出,就可以知道哈夫曼树的编码了。 流程图:

算法:

模块: 在分析了实验要求和算法分析之后,将程序分为四个功能函数,分别如下: 首先建立一个哈夫曼树和哈夫曼编码的存储表示: typedef struct { int weight; int parent,lchild,rchild; char elem; }HTNode,*HuffmanTree;//动态分配数组存储赫夫曼树 typedef char **HuffmanCode;//动态分配数组存储赫夫曼编码表CrtHuffmanTree(HuffmanTree *ht , int *w, int n):w存放n个字符的权值,构造哈夫曼树HT。先将叶子初始化,再将非叶子结点初始化,然后构造哈夫曼树。 构造哈夫曼树: for(i=n+1;i<=m;++i) {//在HT[1……i]选择parent为0且weight最小的两个Select(HT,i-1,&s1,&s2);

数据结构课程设计哈夫曼编码

题目:哈夫曼编码器 班级:031021班姓名:李鑫学号:03102067 完成日期:2011/12 1. 问题描述 利用赫夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。这要求在发送端通过一个编码系统对待传输数据预先编码,在接收端将传来的数据进行译码(复原)。对于双工信道(即可以双向传输信息的信道),每端都需要一个完整的编/译码系统。试为这样的信息收发站编写一个赫夫曼码的编/译码系统。 2.基本要求 一个完整的系统应具有以下功能: (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 中。 3.测试 (1)利用教科书例6-2中的数据调试程序。 (2) 用下表给出的字符集和频度的实际统计数据建立赫夫曼树,并实现以下报文的编码和译码:“THIS PROGRAME IS MY FA VORITE”。 字符 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 4.实现提示 (1) 编码结果以文本方式存储在文件Codefile中。 (2) 用户界面可以设计为“菜单”方式:显示上述功能符号,再加上“Q”,表示退出运行Quit。请用户键入一个选择功能符。此功能执行完毕后再显示此菜单,直至某次用户选择了“Q”为止。 (3) 在程序的一次执行过程中,第一次执行I,D或C命令之后,赫夫曼树已经在内存了,不必再读入。每次执行中不一定执行I命令,因为文件hfmTree可能早已建好。

哈夫曼树及其操作-数据结构实验报告(2)

电子科技大学 实验报告 课程名称:数据结构与算法 学生姓名:陈*浩 学号:************* 点名序号: *** 指导教师:钱** 实验地点:基础实验大楼 实验时间: 2014-2015-2学期 信息与软件工程学院

实验报告(二) 学生姓名:陈**浩学号:*************指导教师:钱** 实验地点:科研教学楼A508实验时间:一、实验室名称:软件实验室 二、实验项目名称:数据结构与算法—树 三、实验学时:4 四、实验原理: 霍夫曼编码(Huffman Coding)是一种编码方式,是一种用于无损数据压缩的熵编码(权编码)算法。1952年,David A. Huffman在麻省理工攻读博士时所发明的。 在计算机数据处理中,霍夫曼编码使用变长编码表对源符号(如文件中的一个字母)进行编码,其中变长编码表是通过一种评估来源符号出现机率的方法得到的,出现机率高的字母使用较短的编码,反之出现机率低的则使用较长的编码,这便使编码之后的字符串的平均长度、期望值降低,从而达到无损压缩数据的目的。 例如,在英文中,e的出现机率最高,而z的出现概率则最低。当利用霍夫曼编码对一篇英文进行压缩时,e极有可能用一个比特来表示,而z则可能花去25个比特(不是26)。用普通的表示方法时,每个英文字母均占用一个字节(byte),即8个比特。二者相比,e使用了一般编码的1/8的长度,z则使用了3倍多。倘若我们能实现对于英文中各个字母出现概率的较准确的估算,就可以大幅度提高无损压缩的比例。 霍夫曼树又称最优二叉树,是一种带权路径长度最短的二叉树。所谓树的带权路径长度,就是树中所有的叶结点的权值乘上其到根结点的路径长度(若根结点为0层,叶结点到根结点的路径长度为叶结点的层数)。树的路径长度是从树根到每一结点的路径长度之和,记为WPL=(W1*L1+W2*L2+W3*L3+...+Wn*Ln),N个权值Wi(i=1,2,...n)构成一棵有N个叶结点的二叉树,相应的叶结点的路径长度为Li(i=1,2,...n)。 可以证明霍夫曼树的WPL是最小的。

贪心法构造哈夫曼树

实验报告 ( 2013 / 2014 学年第二学期) 学院贝尔学院 学生姓名任晓强 班级学号 Q12010218 指导教师季一木 指导单位计算机软件教学中心 日期 2014年3月12日

实验一:贪心算法构造哈夫曼树 问题简述: 两路合并最佳模式的贪心算法主要思想如下: (1)设w={w0,w1,......w }是一组权值,以每个权值作为根结点值,构造n棵只有根的 n-1 二叉树 (2)选择两根结点权值最小的树,作为左右子树构造一棵新二叉树,新树根的权值是两棵子树根权值之和 (3)重复(2),直到合并成一颗二叉树为止 一、实验目的 (1)了解贪心算法和哈夫曼树的定义 (2)掌握贪心法的设计思想并能熟练运用 (3)设计贪心算法求解哈夫曼树 (4)设计测试数据,写出程序文档 二、实验内容 (1)设计二叉树结点数据结构,编程实现对用户输入的一组权值构造哈夫曼树 (2)设计函数,先序遍历输出哈夫曼树各结点 (3)设计函数,按树形输出哈夫曼树 三、程序源代码 #include #include #include #include typedef struct Node{ //定义树结构 int data; struct Node *leftchild; struct Node *rightchild;

}Tree; typedef struct Data{ //定义字符及其对应的频率的结构int data;//字符对应的频率是随机产生的 char c; }; void Initiate(Tree **root);//初始化节点函数 int getMin(struct Data a[],int n);//得到a中数值(频率)最小的数void toLength(char s[],int k);//设置有k个空格的串s void set(struct Data a[],struct Data b[]);//初始化a,且将a备份至b char getC(int x,struct Data a[]);//得到a中频率为x对应的字符void prin(struct Data a[]);//输出初始化后的字符及对应的频率 int n; void main() { //srand((unsigned)time(NULL)); Tree *root=NULL,*left=NULL,*right=NULL,*p=NULL; int min,num; int k=30,j,m; struct Data a[100]; struct Data b[100]; int i;

数据结构哈夫曼编码实验报告

数据结构实验报告 ――实验五简单哈夫曼编/译码的设计与实现 本实验的目的是通过对简单哈夫曼编/译码系统的设计与实现来熟练掌握树型结 构在实际问题中的应用。此实验可以作为综合实验,阶段性实验时可以选择其中的几个功能来设计和实现。 一、【问题描述】 利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行 译码,此实验即设计这样的一个简单编/码系统。系统应该具有如下的几个功能: 1、接收原始数据。 从终端读入字符集大小n,以及n个字符和n个权值,建立哈夫曼树,并将它存于文件nodedata.dat 中。 2、编码。 利用已建好的哈夫曼树(如不在内存,则从文件nodedata.dat中读入),对文件中的正 文进行编码,然后将结果存入文件code.dat中。 3、译码。利用已建好的哈夫曼树将文件code.dat中的代码进行译码,结果存入文件textfile.dat 中。 4、打印编码规则。 即字符与编码的一一对应关系。 二、【数据结构设计】 1、构造哈夫曼树时使用静态链表作为哈夫曼树的存储。 在构造哈夫曼树时,设计一个结构体数组HuffNode保存哈夫曼树中各结点的信息,根 据二叉树的性质可知,具有n个叶子结点的哈夫曼树共有2n-1个结点,所以数组HuffNode 的大小设置为2n-1,描述结点的数据类型为: typedef struct { int weight;//结点权值 int pare nt; int lchild; int rchild; char inf; }HNodeType; 2、求哈夫曼编码时使用一维结构数组HuffCode作为哈夫曼编码信息的存储。 求哈夫曼编码,实质上就是在已建立的哈夫曼树中,从叶子结点开始,沿结点的双亲链 域回退到根结点,没回退一步,就走过了哈夫曼树的一个分支,从而得到一位哈夫曼码值,由于一个字符的哈夫曼编码是从根结点到相应叶子结点所经过的路径上各分支所组成的0、1序列,因此先得到的分支代码为所求编码的低位码,后得到的分支代码位所求编码的高位码,所以设计如下数据类型: #defi ne MAXBIT 10 typedef struct

哈夫曼树和哈夫曼编码(数据结构程序设计)

课程设计 (数据结构) 哈夫曼树和哈夫曼编码 二○○九年六月二十六日课程设计任务书及成绩评定

课题名称表达式求值哈夫曼树和哈夫曼编码 Ⅰ、题目的目的和要求: 巩固和加深对数据结构的理解,通过上机实验、调试程序,加深对课本知识的理解,最终使学生能够熟练应用数据结构的知识写程序。 (1)通过本课程的学习,能熟练掌握几种基本数据结构的基本操作。 (2)能针对给定题目,选择相应的数据结构,分析并设计算法,进而给出问题的正确求解过程并编写代码实现。 Ⅱ、设计进度及完成情况 Ⅲ、主要参考文献及资料 [1] 严蔚敏数据结构(C语言版)清华大学出版社 1999

[2] 严蔚敏数据结构题集(C语言版)清华大学出版社 1999 [3] 谭浩强 C语言程序设计清华大学出版社 [4] 与所用编程环境相配套的C语言或C++相关的资料 Ⅳ、成绩评定: 设计成绩:(教师填写) 指导老师:(签字) 二○○九年六月二十六日

目录 第一章概述 (1) 第二章系统分析 (2) 第三章概要设计 (3) 第四章详细设计及实现代码 (8) 第五章调试过程中的问题及系统测试情况 (12) 第六章结束语 (13) 参考文献 (13)

第一章概述 课程设计是实践性教学中的一个重要环节,它以某一课程为基础,可以涉及和课程相关的各个方面,是一门独立于课程之外的特殊课程。课程设计是让同学们对所学的课程更全面的学习和应用,理解和掌握课程的相关知识。《数据结构》是一门重要的专业基础课,是计算机理论和应用的核心基础课程。 数据结构课程设计,要求学生在数据结构的逻辑特性和物理表示、数据结构的选择和应用、算法的设计及其实现等方面,加深对课程基本内容的理解。同时,在程序设计方法以及上机操作等基本技能和科学作风方面受到比较系统和严格的训练。 在这次的课程设计中我选择的题目是表达式求值和哈夫曼树及哈夫曼编码。这里我们介绍一种简单直观、广为使用的算法,通常称为“算符优先法”。哈夫曼树又称最优树,是一类带权路径长度最短的树,有着广泛的应用。 功能:表达式求值以栈为存储结构,实现输入的表达式的求值; 哈夫曼树和哈夫曼编码是实现最优二叉树的构造,并能通过最优二叉树进行编码,应用到电文中,并以此来译码。 利用键盘,输入相应的数值,通过程序实现表达式的求值;再利用键盘,输入各个顶点,通过程序构造最优二叉树以及为此编码。

2020年最新数据结构哈夫曼编码实验报告

数据结构实验报告 ――实验五简单哈夫曼编 / 译码的设计与实现 本实验的目的是通过对简单哈夫曼编 / 译码系统的设计与实现来熟练掌握树型结构在实际问题中的应用。此实验可以作为综合实验,阶段性实验时可以选择其中的几个功能来设计和实现。 一、【问题描述】 利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。 但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行译码,此实验即设计这样的一个简单编 / 码系统。系统应该具有如下的几个功能 1、接收原始数据。 从终端读入字符集大小 n ,以及 n 个字符和 n 个权值,建立哈夫曼树,并将它存于文件 nodedata.dat 中。 2 、编码。 利用已建好的哈夫曼树(如不在内存,则从文件 nodedata.dat 中读入),对文件中的正文进行编码,然后将结果存入文件 code.dat 中。 3 、译码。利用已建好的哈夫曼树将文件code.dat 中的代码进行译码,结果存入文件 textfile.dat 中。 4、打印编码规则。 即字符与编码的一一对应关系。 二、【数据结构设计】 1、构造哈夫曼树时使用静态链表作为哈夫曼树的存储。 在构造哈夫曼树时,设计一个结构体数组 HuffNode 保存哈夫曼树中各结点的信息,根据二叉树的性质可知,具有 n 个叶子结点的哈夫曼树共有 2n-1 个结点,所以数组 HuffNode 的大小设置为 2n-1 ,描述结点的数据类型为 typedef struct {

int weight;// 结点权值 int parent; int lchild; int rchild; char inf; }HNodeType; 2 、求哈夫曼编码时使用一维结构数组 HuffCode 作为哈夫曼编码信息的存储。 求哈夫曼编码,实质上就是在已建立的哈夫曼树中,从叶子结点开始,沿结点的双亲链域回退到根结点,没回退一步,就走过了哈夫曼树的一个分支,从而得到一位哈夫曼码值,由于一个字符的哈夫曼编码是从根结点到相应叶子结点所经过的路径上各分支所组成的、 序列,因此先得到的分支代码为所求编码的低位码,后得到的分支代码位所求编码的高位码,所以设计如下数据类型 #define MAXBIT 1 typedef struct HaffNode[i].parent=-1; HaffNode[i].parent=-1; HaffNode[i].parent=-1; HaffNode[i].parent=-1; { { int bit[MAXBIT]; int start; }HcodeType; 3 、文件 nodedata.dat 、code.dat 和 textfile.dat 。

相关文档
最新文档