哈夫曼树

哈夫曼树
哈夫曼树

*******************

实践教学

*******************

兰州理工大学

计算机与通信学院

2007年春季学期

算法与数据结构课程设计

题目:赫夫曼编译码器设计

专业班级:软件工程05-1班

姓名:张龙

学号:05350507

指导教师:王燕

成绩:

目录

摘要 (1)

前言 (2)

正文 (3)

1.采用类C语言定义相关的数据类型 (3)

2.各模块的伪码算法 (7)

3.函数的调用关系图 (13)

4.调试分析 (13)

5.测试结果 (14)

6.源程序(带注释) (14)

总结 (20)

参考文献 (20)

附件Ⅰ部分源程序代码 (21)

摘要

哈夫曼编译码器主要用于通信领域,能够实现数据的快速,有效的传输。它利用哈夫曼树对数据进行编码,形成前缀编码,实现数据的有效压缩存放。然后又通过某种遍历实现译码,从而达到快速远距离通信的目的。

关键词:哈夫曼树;前缀编码;译码

前言

利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行译码(复原)。对于双工信道(即可以双向传输信息的信道),每端都需要一个完整的编/译码系统。试为这样的信息收发站写一个哈夫曼码的编/译码系统。通过该题目的设计过程,可以加深理解树及二叉树的逻辑结构、存储结构,掌握树及二叉树上基本运算的实现。进一步理解和熟练掌握课本中所学的各种数据结构,学会如何把学到的知识用于解决实际问题,培养学生的动手能力。

正文

1.采用类c语言定义相关的数据类型

(1)结构体定义

typedef struct

{ int weight;

char ch;

int parent,lchild,rchild;

}HTNode,*HuffmanTree; //动态分配数组存贮哈夫曼树。

typedef struct

{

char ch;

char *chs;

}HuffmanCode;

typedef struct

{

char ch;

int weight;

}sw;

typedef struct

{

HuffmanTree HT;

HuffmanCode *HC;

}huf;//哈夫曼树结构体。

从HT[i-1]选择parent为零且weight最小的两个节点,分别编号为n1,n2. (2)调用函数

1)在给定权值中选择权值最小的两个节点。

void select(HTNode * HT,int n,int *n1,int *n2)

{

int i=1; int n3;

while(HT[i].parent!=0)

i++;

*n1=i;

i++;

while(HT[i].parent!=0) i++;

*n2=i;

if(HT[*n1].weight

{ n3=*n1;*n1=*n2;*n2=n3;}

for(i++;i<=n;i++)

{

if(HT[i].parent==0)

{ if(HT[i].weight

*n1=i;

else if(HT[i].weight

*n2=i;

}

}

}

2)进行哈夫曼编码。

huf * HuffmanCoding(HuffmanTree HT,HuffmanCode *HC,sw *w,int n,huf *HUF)

//w存放n个字符的权值(均>0),构造哈夫曼树HT,并求出n个字符的哈夫曼编码HC.

{int m,i,s1,s2,start,c,f;

HuffmanTree p;

char *cd;

if(n<=1) return 0;

m=2*n-1;

HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));

//零号单元未用。

for(p=HT+1,i=1;i<=n;i++,p++,w++)

{p->weight=w->weight;p->ch=w->ch;p->parent=0;p->lchild=0;p->rchild=0;} for(;i<=m;i++,p++)

{p->weight=0;p->ch='^';p->parent=0;p->lchild=0;p->rchild=0;}

for(i=n+1;i<=m;i++)//建立哈夫曼树。

{

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;

}

//为哈夫曼编码审请空间。

HC=(HuffmanCode *)malloc((n+1)*sizeof(char));

cd=(char *)malloc(n*sizeof(char));

cd[n-1]='\0';

for(i=1;i<=n;i++)

{ start=n-1;

for(c=i,f=HT[i].parent;f!=0;c=f,f=HT[f].parent)

if(HT[f].lchild==c)cd[--start]='0';

else cd[--start]='1';

HC[i].ch=HT[i].ch;

HC[i].chs=(char*)malloc((n-start)*sizeof(char));

strcpy(HC[i].chs,&cd[start]);

printf("%c %-10s\n",HC[i].ch,HC[i].chs);

}

HUF->HT=HT;

HUF->HC=HC;

return HUF;

}

char * convert(char *chars,char *chars1,HuffmanCode *hc,int n) {

char *p=chars; int i;

strcpy(chars1,"");

while(*p)

{

i=1; while(hc[i].ch!=*p&&i<=n) i++;

strcat(chars1,hc[i].chs); p++;

}

printf("the chars translate are:%s\n",chars1);

return chars1;

}

3)译码。

void transcode(HuffmanTree ht,char *chars2,char*chars3) {

int i=1,p; char *q=chars2;char *r=chars3;

while(ht[i].parent!=0) i++;

p=i;

while(*q)

{

while(ht[p].lchild!=0 && *q)

{

if(*q=='0')

p=ht[p].lchild;

else p=ht[p].rchild;

q++;

}

if(ht[p].lchild==0)

{*r=ht[p].ch;r++;}

p=i;

}

*r='\0';

printf("the chars are:");

puts(chars3);

}

}

void input(int *n,sw *w)

{

int i;

printf("input the mount of char:");

scanf("%d",n);

for(i=1;i<=*n;i++,w++)

{printf("input the %dth char and weight:",i);

fflush(stdin);

scanf("%c%d",&w->ch,&w->weight);

4)主函数。

void main()

{HTNode HT;

HuffmanCode HC,*hc;

HuffmanTree ht;

huf *HUF,huf2;

int n;

sw w[40];

char ch,inchar[500],outchar[1000];

char *abc;

char *p=inchar;

input(&n,w);

HUF=HuffmanCoding(&HT,&HC,w,n,&huf2);

printf("input chars to translate:");

fflush(stdin);//清除流,解决输入干扰

ch=getchar();

while(ch!='#')

{*p=ch;

p++;

ch=getchar();

}

*p='\0';

hc=HUF->HC;

ht=HUF->HT;

abc=convert(inchar,outchar,hc,n);

transcode(ht,abc,outchar);

}

2.各模块的伪码算法

1)节点结构体定义

typedef struct

int weight;

char ch;

int parent,lchild,rchild;

}HTNode,*HuffmanTree; //动态分配数组存贮哈夫曼树。

2)哈夫曼编码结构体定义。

typedef struct

{

char ch;

char *chs;

}HuffmanCode;

3)根节点结构体定义。

typedef struct

{

char ch;

int weight;

}sw;

4)哈夫曼树结构体定义。

typedef struct

{

HuffmanTree HT;

HuffmanCode *HC;

}huf;

4)从HT[i-1]选择parent为零且weight最小的两个节点,分别编号为n1,n2. void select(HTNode * HT,int n,int *n1,int *n2)

{

int i=1; int n3;

while(HT[i].parent!=0)

i++;

*n1=i;

i++;

while(HT[i].parent!=0) i++;

*n2=i;

if(HT[*n1].weight

{ n3=*n1;*n1=*n2;*n2=n3;}

for(i++;i<=n;i++)

{

if(HT[i].parent==0)

{ if(HT[i].weight

*n1=i;

else if(HT[i].weight

*n2=i;

}

}

}

5)w存放n个字符的权值(均>0),构造哈夫曼树HT,并求出n个字符的哈夫曼编码HC.

huf * HuffmanCoding(HuffmanTree HT,HuffmanCode *HC,sw *w,int n,huf *HUF)

{int m,i,s1,s2,start,c,f;

HuffmanTree p;

char *cd;

if(n<=1) return 0;

m=2*n-1;

HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));

//零号单元未用。

for(p=HT+1,i=1;i<=n;i++,p++,w++)

{p->weight=w->weight;p->ch=w->ch;p->parent=0;p->lchild=0;p->rchild=0;} for(;i<=m;i++,p++)

{p->weight=0;p->ch='^';p->parent=0;p->lchild=0;p->rchild=0;}

6)建立哈夫曼树。

for(i=n+1;i<=m;i++)

{

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;

}

//为哈夫曼编码审请空间。

HC=(HuffmanCode *)malloc((n+1)*sizeof(char));

cd=(char *)malloc(n*sizeof(char));

cd[n-1]='\0';

for(i=1;i<=n;i++)

{ start=n-1;

7)求哈夫曼编码。

for(c=i,f=HT[i].parent;f!=0;c=f,f=HT[f].parent)

if(HT[f].lchild==c)cd[--start]='0';

else cd[--start]='1';

HC[i].ch=HT[i].ch;

HC[i].chs=(char*)malloc((n-start)*sizeof(char));

strcpy(HC[i].chs,&cd[start]);

printf("%c %-10s\n",HC[i].ch,HC[i].chs);

}

HUF->HT=HT;

HUF->HC=HC;

return HUF;

}

char * convert(char *chars,char *chars1,HuffmanCode *hc,int n) {

char *p=chars; int i;

strcpy(chars1,"");

while(*p)

{

i=1; while(hc[i].ch!=*p&&i<=n) i++;

strcat(chars1,hc[i].chs); p++;

}

printf("the chars translate are:%s\n",chars1);

return chars1;

}

8)求哈夫曼编码的译码。

void transcode(HuffmanTree ht,char *chars2,char*chars3)

{

int i=1,p; char *q=chars2;char *r=chars3;

while(ht[i].parent!=0) i++;

p=i;

while(*q)

{

while(ht[p].lchild!=0 && *q)

{

if(*q=='0')

p=ht[p].lchild;

else p=ht[p].rchild;

q++;

}

if(ht[p].lchild==0)

{*r=ht[p].ch;r++;}

p=i;

}

*r='\0';

printf("the chars are:"); /*打印出译码后的字符*/

puts(chars3);

}

}

void input(int *n,sw *w)

{

int i;

/*输入要编码的字符数量*/

printf("input the mount of char:");

scanf("%d",n);

for(i=1;i<=*n;i++,w++)

{printf("input the %dth char and weight:",i);

fflush(stdin);

/*输入字符和权值*/

scanf("%c%d",&w->ch,&w->weight);

}

}

void main()

{HTNode HT;

HuffmanCode HC,*hc;

HuffmanTree ht;

huf *HUF,huf2;

int n;

sw w[40];

char ch,inchar[500],outchar[1000];

char *abc;

char *p=inchar;

input(&n,w);

HUF=HuffmanCoding(&HT,&HC,w,n,&huf2);/*输入要译码的字符

printf("input chars to translate:");

fflush(stdin);//清除流,解决输入干扰

ch=getchar();

while(ch!='#')

{*p=ch;

p++;ch=getchar()

}

*p='\0';hc=HUF->HC;ht=HUF->HT;

abc=convert(inchar,outchar,hc,n);

transcode(ht,abc,outchar);}

3.函数的调用关系图

4.调试分析

a、调试中遇到的问题及对问题的解决方法

1.对*和&的作用分不清,看书过程中应注意这方面的问题。

2.对于算法不是很清楚,应该先弄清楚算法,再去调试程序。

b、算法的时间复杂度和空间复杂度

1.算法的时间复杂度为O(n);

2.算法的空间复杂度不仅要考虑程序本身所要占用空间,还要考虑对数据进行

操作所需要的辅助空间。

5.测试结果

6.源程序(带注释)

#include

#include

#include

#include

/*节点定义*/

typedef struct

{

int weight;

char ch;

int parent,lchild,rchild;

}HTNode,*HuffmanTree;

/*动态分配数组存贮哈夫曼树*/

typedef struct

{

char ch;

char *chs;

}HuffmanCode;

typedef struct

{

char ch;

int weight;

}sw;

typedef struct

{

HuffmanTree HT;

HuffmanCode *HC;

}huf; /*哈夫曼树结构体*/

/*从HT[i-1]选择parent为零且weight最小的两个节点,分别编号为n1,n2.*/ void select(HTNode * HT,int n,int *n1,int *n2)

{

int i=1; int n3;

while(HT[i].parent!=0)

i++;

*n1=i;

i++;

while(HT[i].parent!=0) i++;

*n2=i;

if(HT[*n1].weight

{ n3=*n1;*n1=*n2;*n2=n3;}

for(i++;i<=n;i++)

{

if(HT[i].parent==0)

{ if(HT[i].weight

*n1=i;

else if(HT[i].weight

*n2=i;

}

}

}

huf * HuffmanCoding(HuffmanTree HT,HuffmanCode *HC,sw *w,int n,huf *HUF)

/*w存放n个字符的权值(均>0),构造哈夫曼树HT,并求出n个字符的哈夫曼编码HC.*/

{int m,i,s1,s2,start,c,f;

HuffmanTree p;

char *cd;

if(n<=1) return 0;

m=2*n-1;

HT=(HuffmanTree)malloc((m+1)*sizeof(HTNode));

for(p=HT+1,i=1;i<=n;i++,p++,w++)

{p->weight=w->weight;p->ch=w->ch;p->parent=0;p->lchild=0;p->rchild=0;} for(;i<=m;i++,p++)

{p->weight=0;p->ch='^';p->parent=0;p->lchild=0;p->rchild=0;}

for(i=n+1;i<=m;i++) /*建立哈夫曼树*/

{

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;

}

HC=(HuffmanCode *)malloc((n+1)*sizeof(char));

/*为哈夫曼编码审请空间*/

cd=(char *)malloc(n*sizeof(char));

cd[n-1]='\0';

for(i=1;i<=n;i++)

{ start=n-1;

for(c=i,f=HT[i].parent;f!=0;c=f,f=HT[f].parent)

if(HT[f].lchild==c)cd[--start]='0';

else cd[--start]='1';

HC[i].ch=HT[i].ch;

HC[i].chs=(char*)malloc((n-start)*sizeof(char));

strcpy(HC[i].chs,&cd[start]);

printf("%c %-10s\n",HC[i].ch,HC[i].chs);

}

HUF->HT=HT;

HUF->HC=HC;

return HUF;

}

char *convert(char *chars,char *chars1,HuffmanCode *hc,int n) {

char *p=chars; int i;

while(*p)

{

i=1; while(hc[i].ch!=*p&&i<=n) i++;

strcat(chars1,hc[i].chs); p++;

}

printf("the chars translate are:%s\n",chars1);

return chars1;

}

/*译码*/

void transcode(HuffmanTree ht,char *chars2,char*chars3)

{

int i=1,p; char *q=chars2;char *r=chars3;

while(ht[i].parent!=0) i++;

p=i;

while(*q)

{

while(ht[p].lchild!=0 && *q)

{

if(*q=='0')

p=ht[p].lchild;

else p=ht[p].rchild;

q++;

}

if(ht[p].lchild==0)

{*r=ht[p].ch;r++;}

p=i;

}

*r='\0';

printf("the chars are:");

/*打印出译码后的字符*/ puts(chars3);

}

void input(int *n,sw *w)

{

int i;

/*输入要编码的字符数量*/

printf("input the mount of char:");

scanf("%d",n);

for(i=1;i<=*n;i++,w++)

{printf("input the %dth char and weight:",i);

fflush(stdin);

/*输入字符和权值*/

scanf("%c%d",&w->ch,&w->weight);

}

}

void main()

{HTNode HT;

HuffmanCode HC,*hc;

HuffmanTree ht;

huf *HUF,huf2;

int n;

sw w[40];

char ch,inchar[500],outchar[1000];

char *abc;

char *p=inchar;

input(&n,w);

HUF=HuffmanCoding(&HT,&HC,w,n,&huf2);

printf("input chars to translate:");

贪心算法构造哈夫曼树

软件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 #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;

哈夫曼树及其应用(完美版)

数据结构课程设计设计题目:哈夫曼树及其应用 学院:计算机科学与技术 专业:网络工程 班级:网络 131 学号:1308060312 学生姓名:谢进 指导教师:叶洁 2015年7 月12 日

设计目的: 赫夫曼编码的应用很广泛,利用赫夫曼树求得的用于通信的二进制编码称为赫夫曼编码。树中从根到每个叶子都有一条路径,对路径上的各分支约定:指向左子树的分支表示“0”码,指向右子树的分支表示“1”码,取每条路径上的“0”或“1”的序列作为和各个叶子对应的字符的编码,这就是赫夫曼编码。哈弗曼译码输入字符串可以把它编译成二进制代码,输入二进制代码时可以编译成字符串。 1、熟悉树的二叉树的存储结构及其特点。 2、掌握建立哈夫曼树和哈夫曼编码的方法。 设计内容: 欲发一封内容为AABBCAB ……(共长 100 字符,字符包括A 、B 、C 、D 、E 、F六种字符),分别输入六种字符在报文中出现的次数(次数总和为100),对这六种字符进行哈夫曼编码。 设计要求: 对输入的一串电文字符实现赫夫曼编码,再对赫夫曼编码生成的代码串进行译码,输出电文字符串。通常我们把数据压缩的过程称为编码,解压缩的过程称为解码。电报通信是传递文字的二进制码形式的字符串。但在信息传递时,总希望总长度能尽可能短,即采用最短码。假设每种字符在电文中出现的次数为Wi,编码长度为Li,电文中有n种字符,则电文编码总长度为∑WiLi。若将此对应到二叉树上,Wi为叶结点的权,Li为根结点到叶结点的路径长度。那么,∑WiLi 恰好为二叉树上带权路径长度。因此,设计电文总长最短的二进制前缀编码,就是以n种字符出现的频率作权,构造一棵赫夫曼树,此构造过程称为赫夫曼编码。设计实现的功能: 1.以二叉链表存储, 2.建立哈夫曼树; 3.求每个字符的哈夫曼编码并显示。

哈夫曼树的建立与操作

实验六哈夫曼树的建立与操作 一、实验要求和实验内容 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

数据结构课程设计-哈夫曼树

嘉应学院计算机学院 实验报告 课程名称:数据结构课程设计 开课学期:2017-2018学年第2学期 班级: 指导老师: 实验题目:哈夫曼树 学号: 姓名: 上机时间:

一、实验目的 本实验的目的是通过对简单的哈夫曼编/译码系统的设计与实现来熟练掌握树形结构在实际问题中的应用。 二、实验问题描述 利用哈夫曼编码进行通信可以大大提高通信利用率,缩短信息传输时间,降低传输成本。但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行译码,此试验即设计这样的一个简单的编/译码系统。系统应该具备如下的几个功能。 1、求出各个叶子节点的权重值 输入一个字符串,统计其中各个字母的个数和总的字母个数。 2、构造哈夫曼树 统计出的字母种类为叶子结点个数,每个字母个数为相应的权值,建立哈夫曼树。 3、打印哈弗曼树的功能模块 按照一定形式打印出哈夫曼树。 4、编码 利用已经建立好的哈夫曼树进行编码。 5、译码 根据编码规则对输入的代码进行翻译并将译码。 三、实验步骤 1、实验问题分析 (1)设计一个结构体数组保存字母的类型和个数。 { ; 字母的种类 ; 字母的个数 }; (2)在构造哈夫曼树时,设计一个结构体数组保存哈夫曼树中各结点

的信息,根据二叉树的性质可知,具有n个结点的哈夫曼树共有21个结点,所以数组大小设置为21,描述结点的数据类型为: { ; 权值 ; 双亲 ; 左孩子 ; 右孩子 }; []; 定义此类型的数组 (3)求哈夫曼编码,实质上是在已经建立的哈夫曼树中,从叶子结点开始,沿着结点的双亲链表域退回到根节点,每退回一步,就走过了哈夫曼树的一个分支,从而得到一位哈夫曼值,由于一个字符的哈夫曼编码是从根结点所经过的路径上各分支所组成的0、1序列,因此先得到的分支代码为所求编码的低位码,后得到的分支代码为所求编码的高位码,所以设计如下的数据类型: 10; { []; 每个结点的哈夫曼编码 ; 开始位置 }; (4)设置全局变量。 s; 为输入的字符串 0; 记录输入的字符串中字母的种类,即叶子结点个数 0; 记录字符串中字母的总个数 []叶子结点类型 2、功能(函数)设计 (1)统计字母种类和个数模块 此模块的功能为从键盘接受一个字符串,统计字符串中字母种类即结 点个数,每种字母出现次数即各叶子结点的权值。全局变量s保存输 入的字符串,将种类和个数保存到[]中。 函数原型:() 如输入的字符串是“”则显示如下。

哈工大数据结构大作业——哈夫曼树生成、编码、遍历

一、问题描述 1.用户输入字母及其对应的权值,生成哈夫曼树; 2.通过最优编码的算法实现,生成字母对应的最优0、1编码; 3.先序、中序、后序遍历哈夫曼树,并打印其权值。 二、方法思路 1.哈夫曼树算法的实现 §存储结构定义 #define n 100 /* 叶子树*/ #define m 2*(n) –1 /* 结点总数*/ typedef struct { /* 结点型*/ double weight ; /* 权值*/ int lchild ; /* 左孩子链*/ int rchild ; /* 右孩子链*/ int parent; /* 双亲链*/ 优点? }HTNODE ; typedef HTNODE HuffmanT[ m ] ; /* huffman树的静态三叉链表表示*/ 算法要点 1)初始化:将T[0],…T[m-1]共2n-1个结点的三个链域 均置空( -1 ),权值为0; 2)输入权值:读入n 个叶子的权值存于T的前n 个单元 T[0],…T[n], 它们是n 个独立的根结点上的权值; 3)合并:对森林中的二元树进行n-1次合并,所产生的新 结点 依次存放在T[i](n<=i<=m-1)。每次合并分两步: (1) 在当前森林中的二元树T [0],…T[i-1]所有结点中 选取权值 最小和次最小的两个根结点T[p1]和T[p2]作为合并对象,这 里0<= p1,p2<= i –1; (2) 将根为T[p1]和T[p2]的两株二元树作为左、右子树 合并为一 株新二元树,新二元树的根结点为T[i]。即 T[p1].parent =T[p2].parent = i ,T[i].lchild= p1,

数据结构哈夫曼树和代码

#include #include #include #define N 50 //叶?子哩?结á点?数簓 #define M 2*N-1 //树骸?中D结á点?总哩?数簓 typedef struct { char data; //结á点?值μ int weight; //权ü?重? int parent; //双?亲×结á点? int lchild; //左哩?孩¢子哩?结á点? int rchild; //右 ?孩¢子哩?结á点? } HTNode; typedef struct { char cd[N]; //存?放?哈t夫え?曼?码? int start; } HCode; HTNode ht[M]; HCode hcd[N]; int n; void CreateHT(HTNode ht[],int n) { int i,k,lnode,rnode; int min1,min2; for (i=0;i<2*n-1;i++) //所ù有瓺结á点?的?相à关?域 ?置?初?值μ0 ht[i].parent=ht[i].lchild=ht[i].rchild=0; printf("哈t夫え?曼?树骸?初?态?为a:\n"); printf("data weight parent lchild rchild\n"); for (i=0;i<2*n-1;i++) { printf("%-6c %-6d %-6d %-6d %-6d\n",ht[i].data,ht[i].weight,ht[i].parent,ht[i].lchild, ht[i].rchild); } for (i=n;i<2*n-1;i++) //构1造ì哈t夫え?曼?树骸? {

武汉理工大学数据结构与算法综合实验哈夫曼树(1)

学生学号Xxx实验课成绩 学生实验报告书 实验课程名称数据结构与算法综合实验 开课学院计算机科学与技术学院 指导教师姓名xxx 学生姓名xxx 学生专业班级xxxx 2015--2016学年第2学期

实验课程名称:数据结构与算法综合实验 实验项目名称二叉树与赫夫曼图片压缩报告成绩 实验者xx专业班级xxx组别 同组者完成日期2016年5月 2日第一部分:实验分析与设计(可加页) 一、实验目的和要求 1.目的 掌握树的存储结构 掌握二叉树的三种遍历方法 掌握 Huffman树、Huffman编码等知识和应用 使用 C++、文件操作和 Huffman算法实现“图片压缩程序”专题编程。 2.要求 针对一幅 BMP 格式的图片文件,统计 256 种不同字节的重复次数,以每种字 节重复次数作为权值,构造一颗有 256 个叶子节点的哈夫曼二叉树。 利用上述哈夫曼树产生的哈夫曼编码对图片文件进行压缩。 压缩后的文件与原图片文件同名,加上后缀.huf (保留原后缀),如 pic.bmp 压 缩后 pic.bmp.huf 二、分析与设计 依据上述的实验目的与要求,可导出实现的二叉树与赫夫曼图片压缩软件的流程为: ① 读取图片文件、统计权值 ②生成 Huffman树 ③生成 Huffman编码 ④ 压缩图片文件 ⑤ 保存压缩的文件 1.数据结构的设计 记录统计 256种不同字节的重复次数使用整型数组。 int weight[256] = { 0 }; 二叉树的存储结构。使用结构体存储节点,使用数组存储树的节点,使用静态二叉链表方 式存储二叉树。 Huffman编码存储结构 struct HTNode { int weight;//权值

哈夫曼树的实验报告1

一、需求分析 1、本演示程序实现Haffman编/译码器的作用,目的是为信息收发站提供一个编/译系统, 从而使信息收发站利用Haffman编码进行通讯,力求达到提高信道利用率,缩短时间,降低成本等目标。系统要实现的两个基本功能就是:①对需要传送的数据预先编码; ②对从接收端接收的数据进行译码; 2、本演示程序需要在终端上读入n个字符(字符型)及其权值(整形),用于建立Huffman 树,存储在文件hfmanTree.txt中;如果用户觉得不够清晰还可以打印以凹入表形式显示的Huffman树; 3、本演示程序根据建好的Huffman树,对文件的文本进行编码,结果存入文件CodeFile 中;然后利用建好的Huffman树将文件CodeFile中的代码进行译码,结果存入文件TextFile中;最后在屏幕上显示代码(每行50个),同时显示对CodeFile中代码翻译后的结果; 4、本演示程序将综合使用C++和C语言; 5、测试数据: (1)教材例6-2中数据:8个字符,概率分别是0.05,0.29,0.07,0.08,0.14,0.23,0.03, 0.11,可将其的权值看为5,29,7,8,14,23,3,11 (2)用下表给出的字符集和频度的实际统计数据建立Haffman树,并实现以下报文的编码和 一、概要设计 1、设定哈夫曼树的抽象数据类型定义 ADT Huffmantree{ 数据对象:D={a i| a i∈Charset,i=1,2,3,……n,n≥0} 数据关系:R1={< a i-1, a i >| a i-1, a i∈D, i=2,3,……n} 基本操作: Initialization(&HT,&HC,w,n,ch) 操作结果:根据n个字符及其它们的权值w[i],建立Huffman树HT,用字符数组ch[i]作为中间存储变量,最后字符编码存到HC中; Encodeing(n) 操作结果:根据建好的Huffman树,对文件进行编码,编码结果存入到文件CodeFile 中 Decodeing(HT,n) 操作结果:根据已经编译好的包含n个字符的Huffman树HT,将文件的代码进行翻译,结果存入文件TextFile中 } ADT Huffmantree

哈夫曼树及应用

常熟理工学院微课教学比赛教学设计 1、课程基本信息 课程名称:哈夫曼树及应用所属课程:数据结构与算法 课程所属专业:软件工程适用专业:计算机类 选用教材:严蔚敏,吴伟明编著《数据结构(C语言版)》北京:清华大学出版社,2007 主讲人:周思林时长:15分钟 所属学校:常熟理工学院所属院系:计算机科学与工程学院 2.教学背景 《数据结构与算法》课程是计算机类专业的学科基础课程,本节微课“哈夫曼树及应用”属于数据结构课程中的“树与二叉树”章节中的重点及难点。 2.1《数据结构与算法》课程简介及特点 《数据结构与算法》课程是计算机类专业的学科基础课程,同时也是计算机类专业的核心课程。课程的主要目标是使学生理解和掌握基本数据结构的概念、经典算法的思想及实现方法,具备为应用所涉及的数据选择适当的逻辑结构、存储结构及其相应的操作算法的能力。数据结构与算法课程的学习也是复杂程序设计的训练过程,通过算法设计和实践,培养学生的数据抽象和复杂程序设计能力。 《数据结构与算法》课程由线性结构、树形结构、图状结构三种逻辑结构和查找、排序算法为主体,结合应用型本科院校特点,通过实践理解和掌握基本数据结构与算法,在实践中提高学生的专业素养和专业技能。 2.2本节微课课程特点 “树与二叉树——哈夫曼树及应用”是《数据结构与算法》课程中第六章“树与二叉树”的核心内容之一,同时也是该章节的教学难点。 本节微课采用案例驱动法进行教学,调动学生的学习积极性,引导学生发现问题、思考问题、解决问题,利用形象的多媒体动画展示案例的执行过程,将哈夫曼树及编码复杂的程序结构趣味化、形象化。由发送报文问题引入课程,循序渐进的介绍哈夫曼树的概念、逻辑特性、存储结构和算法实现,使学生掌握哈夫曼树及编码的基本概念和算法,提升学生的程序设计及逻辑思维能力。 3.教学设计 3.1教学目的 通过本节微课的学习,培养学生以下几个方面的能力: (1)理解哈夫曼树的应用范围和场景,并能灵活运用; (2)掌握哈夫曼树及编码的概念、求解算法基本思想,针对实例,能构造哈夫曼树,求解哈夫

哈夫曼树解压与压缩

哈夫曼树的压缩与解压 1.算法简要描述 1.哈夫曼算法 1.哈弗曼算法是根据给定的n个权值{w1,w2,w3.......wn},构造由n棵 二叉树构成的深林F={T1,T2,。。。。Tn},其中每个二叉树Ti分别都是只 含有一个权值wi的根结点,其左右子树为空(i=1,,,,,,2)。 2.在深林F中选取其根结点的权值最小的两棵二叉树,分别作其左右子树 构造一颗新的二叉树,并置这棵新的二叉树根结点的权值为其左右子树 的根结点之和。 3.从F中删去这两棵二叉树,同时刚新生成的二叉树加入到深林F中。 4.重复2,3,步骤,直至深林F中只含有一颗二叉树为止。 2.哈夫曼树的实现 函数String EnCode(Char Type ch):表示哈夫曼树已存在,返回字符ch的编码。 函数LinkListUnCode(String strCode):表示对哈夫曼树进行译码,返回编码前的字符序列。根据算法可以看出,在具有n个结点权值的哈夫曼树的构造过程中,每次都是从F中删去两棵树,增加一棵树,即每次结束后减少一棵树,经过n-1次处理后,F中就只剩下一棵树了。另外,每次合并都要产生一个新的结点,合并n-1次后共产生了n-1个新结点,并且这n-1个新节点都是具有左右子树的分支结点。则最终得到的哈夫曼树中共有2n-1个结点,并且其中没有度为1的分支结点,最后一次产生的新结点就是哈夫曼树的根结点。

源代码中创建了一个哈夫曼树结点类,其中有数据成员weight,parent,leftChild,rightChild分别代表了权值,双亲,左孩子,右孩子。 在哈夫曼树类中有数据成员*nodes,*LeafChars,*LeafCharCodes,curPos,num,分别用来存储结点信息,叶结点字符信息,叶结点字符编码信息,译码时从根结点到叶结点路径的当前结点,叶结点个数。哈夫曼树类中含有多个函数,有构造函数,析构函数等。由函数HuffmanTree(CharType ch[],WeightType w[],int n)来构造由字符,权值,和字符个数构造哈夫曼树,在根据哈夫曼算法很容易实现哈夫曼类的函数以及构造函数。在在算法中,求叶结点字符的编码时,需要从叶结点出发走一条从高叶结点到根结点的路径,而编码却是从根结点出发到叶结点的路径,由左分支为编码0,右分支为编码1,得到的编码,因此从叶结点出发到根结点的路径得到的编码是实际编码的逆序,并且编码长度不确定,又由于可以再线性链表中构造串,因此将编码的信息储存在一个线性立案标准,每得到一位编码都将其插入在线性链表的最前面。 在求某个字符的编码是由函数EnCode(CharType ch)来求,返回字符编码。在进行译码时,用一个线性链表存储字符序列,由函数Decode(String strCode)来求,对编码串strCode进行译码,返回编码前的字符序列。函数Compress()用哈夫曼编码压缩文件。函数Decompress()解压缩用哈夫曼编码压缩的文件。 在主函数中有两个选项,一个是选择编码压缩,一个是解压。在函数中使用了文件输入输出流,我们可以选择要压缩的文件名输入,在选出压缩文件保存的地方和文件类型,将压缩所得到的文件存储在另一个文件中,解压也是如此。

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

#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) {

贪心法构造哈夫曼树

实验报告 ( 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;

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

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

实验报告(二) 学生:**浩学号:*************指导教师:钱** 实验地点:科研教学楼A508实验时间:2015.5.7 一、实验室名称:软件实验室 二、实验项目名称:数据结构与算法—树 三、实验学时: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是最小的。

哈夫曼算法的实现及应用

摘要:哈夫曼树是带权路径长度(WPL)最小的二叉树,通过对哈夫曼算法的研究,提出一种求取哈夫曼树带权路径长度的计算方法和应用。 关键词:哈夫曼算法、二叉树、WPL、编码 1 引言: 哈夫曼树是一种特殊的二叉树,又称最优二叉树:假设有一组(无序)实数{w1,w2,w3,w4,…,wm},现要构造一棵以wi(i=1,2,3,4…,m)为权的m个外部结点的扩充二叉树,使得带权的外部路径长度WPL最小。满足这一要求的扩充二叉树就称为哈夫曼树或最优二叉树。若l表示从根到第i个外部结点的路径长度,m为外部结点的个数,wi 为第i个外部结点的权值,则有WPL=∑wili(0 #include #define MAXINT 50 #define MAXNUM 50 /* 数组w中最多容纳的元素个数,注意m<=MAXNUM */ #define MAXNODE 100 /* 哈夫曼树中的最大结点数,注意2*m-1

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

数据结构实验报告 ――实验五简单哈夫曼编/译码的设计与实现 本实验的目的是通过对简单哈夫曼编/译码系统的设计与实现来熟练掌握树型结 构在实际问题中的应用。此实验可以作为综合实验,阶段性实验时可以选择其中的几个功能来设计和实现。 一、【问题描述】 利用哈夫曼编码进行通信可以大大提高信道利用率,缩短信息传输时间,降低传输成本。但是,这要求在发送端通过一个编码系统对待传数据预先编码,在接收端将传来的数据进行 译码,此实验即设计这样的一个简单编/码系统。系统应该具有如下的几个功能: 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

c++数据结构实验哈夫曼树

c++数据结构实验哈夫曼树

数据结构实验报告 1.实验要求 i.实验目的: (1)掌握二叉树基本操作的实现方法 (2)掌握二叉树基本操作的实现方法 (3)了解哈夫曼树的思想和相关概念 (4)学习使用二叉树解决实际问题的能力 (5)熟悉C++语言的基本编程方法,掌握集成编译环境的调试方法,熟练改错方法。 (6)熟悉设计算法的过程 (7)进一步掌握指针、异常处理的使用 ii.实验内容: 利用二叉树结构实现赫夫曼编/解码器。 基本要求: 1、初始化(Init):能够对输入的任意长度 的字符串s进行统计,统计每个字符的频 度,并建立赫夫曼树 2、建立编码表(CreateTable):利用已经 建好的赫夫曼树进行编码,并将每个字符

的编码输出。 3、编码(Encoding):根据编码表对输入 的字符串进行编码,并将编码后的字符串 输出。 4、译码(Decoding):利用已经建好的赫 夫曼树对编码后的字符串进行译码,并输 出译码结果。 5、打印(Print):以直观的方式打印赫夫 曼树(选作) 6、计算输入的字符串编码前和编码后的 长度,并进行分析,讨论赫夫曼编码的压 缩效果。 测试数据: I love data Structure, I love Computer.I will try my best to study data structure. 提示: 1、用户界面可以设计为“菜单”方式:能够进行交互。 2、根据输入的字符串中每个字符出现 的次数统计频度,对没有出现的

字符一律不用编码。 iii.代码要求: 1、必须要有异常处理,比如删除空链表时需要抛出异常; 2、保持良好的编程的风格: 代码段与段之间要有空行和缩近 标识符名称应该与其代表的意义一致 函数名之前应该添加注释说明该函数的功能 关键代码应说明其功能 3、递归程序注意调用的过程,防止栈溢出2. 程序分析 树形结构是一种非线性结构可以用结点之间的分支来表示层次关系,二叉树是每个结点最多两个子树的有序树,十分适合计算机处理问题,而哈夫曼树是一种特殊的二叉树,它将权值大的数据放在了离根较近的结点处,这样使得带权路径长度最短,是非常好的存储方式。 2.1 存储结构 1.结点结构的存储方式:

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

数据结构实验报告 实验名称:实验3——树(哈夫曼编/解码器) 学生姓名: 班级: 班内序号: 学号: 日期:2011年12月5日 1.实验要求 利用二叉树结构实现哈夫曼编/解码器。 基本要求: 1、初始化(Init):能够对输入的任意长度的字符串s进行统计,统计每个字符的频 度,并建立哈夫曼树 2、建立编码表(CreateTable):利用已经建好的哈夫曼树进行编码,并将每个字符的 编码输出。 3、编码(Encoding):根据编码表对输入的字符串进行编码,并将编码后的字符串输 出。 4、译码(Decoding):利用已经建好的哈夫曼树对编码后的字符串进行译码,并输出 译码结果。 5、打印(Print):以直观的方式打印哈夫曼树(选作) 计算输入的字符串编码前和编码后的长度,并进行分析,讨论哈夫曼编码的压缩效果。 并用I love data Structure, I love Computer。I will try my best to study data Structure.进行测试。 2. 程序分析 哈夫曼树结点的存储结构包括双亲域parent,左子树lchild,右子树rchild,还有字符word,权重weight,编码code 对用户输入的信息进行统计,将每个字符作为哈夫曼树的叶子结点。统计每个字符出现的次数作为叶子的权重,统计次数可以根据每个字符不同的ASCII码,根据叶子结点的权重建立一个哈夫曼树。 建立每个叶子的编码从根结点开始,规定通往左子树路径记为0,通往右子树路径记为1。由于编码要求从根结点开始,所以需要前序遍历哈夫曼树,故编码过程是以前序遍历二叉树为基础的。同时注意递归函数中能否直接对结点的编码域进行操作。 编码信息只要遍历字符串中每个字符,从哈夫曼树中找到相应的叶子结点,取得相应的编码。最后再将所有找到的编码连接起来即可。 译码则是将编码串从左到右逐位判别,直到确定一个字符。这就是哈夫曼树的逆过程。

数据结构实验报告(哈夫曼树)

数据结构实验报告实验题目:Huffman编码与解码 姓名: 学号: 院系:

实验名称: Huffman编码与解码实验 问题描述: 本实验需要以菜单形式完成以下功能: 1.输入电文串 2.统计电文串中各个字符及其出现的次数 3.构造哈弗曼树 4.进行哈弗曼编码 5.将电文翻译成比特流并打印出来 6.将比特流还原成电文 数据结构的描述: 逻辑结构: 本实验可用二叉树实现,其逻辑结构为一对二的形式,即一个结点对应两个结点。在实验过程中我们也应用到了栈的概念。 存储结构: 使用结构体来对数据进行存储: typedef struct { int weight; int parent,lc,rc; }HTNode,*HuffmanTree; typedef struct LNode { char *elem; int stacksize; int top; }SqStack; 在main函数里面定义一个哈弗曼树并实现上述各种功能。 程序结构的描述: 本次实验一共构造了10个函数: 1.void HuffTree(HuffmanTree &HT,int n[],int mun); 此函数根据给定的mun个权值构建哈弗曼树,n[]用于存放num个权值。 2.void Select(HuffmanTree &HT,int n,int i,int &s1,int &s2);

此函数用于在HT[1,i-1]中选择parent为0且weight为最小的两个结点,其下标分别为s1,s2. 3.void HuffmanCoding(HuffmanTree HT,char **&HC,int n); 此函数从哈弗曼树HT上求得n 个叶子结点的哈弗曼编码并存入数组HC中。 4.void Coding(HuffmanTree HT,char **HC,int root,SqStack &S); 此函数用于哈弗曼编码,先序遍历哈弗曼树HT,求得每个叶子结点的编码字符串,存入数组HC,S为一个顺序栈,用来记录遍历路径,root是哈弗曼数组HT中根结点的位置下标。 5.void InitStack(SqStack &S); 此函数用于初始化一个栈。 6.void Pop(SqStack &S,char e); 此函数为出栈操作。 7.void Push(SqStack &S,char e); 此函数为进栈操作。 8.int StackLength(SqStack S); 此函数用于求栈长,返回一个int型的值。 9.int Find(char a,char s[],int num); 此函数用于查找字符a在电文串中的位置。 10.int Recover(HuffmanTree HT,char **HC,char string[],char a[],char b[],int n); 此函数用于将比特流还原成电文。 调试分析: 输入任意一个字符串,如输入welcometoustc:运行结果如下:

相关文档
最新文档