数据结构课程设计哈夫曼编码问题的设计和实现.docx

上传人:b****3 文档编号:3826236 上传时间:2022-11-25 格式:DOCX 页数:21 大小:163.73KB
下载 相关 举报
数据结构课程设计哈夫曼编码问题的设计和实现.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

数据结构课程设计哈夫曼编码问题的设计和实现

成绩

课程设计说明书(论文)

题目哈夫曼编码问题的设计和实现

课程名称数据结构课程设计

院(系、部、中心)

专业

班级

学生姓名

学号

设计地点

指导教师

 

设计起止时间:

2008年6月2日至2008年6月6日

 

1问题描述

题目内容

哈夫曼编码问题的设计和实现

输入一个英文字符串,对该字符串中各字符个数进行统计取得各字符的出现次数;以其出现次数作为关键字建立哈夫曼树并进行编码,最后输出各个字符对应的码值。

基本要求

要求:

设计存储结构、基本算法(主要采用程序流程图体现);完成基本算法的实现代码;设计测试输入数据对程序进行测试,分析输出结果数据、算法的时间复杂度分析,如有改进算法则提出算法的改进方法。

测试数据

测试数据三组:

AAAABBBCCD(判断连续的字符串是否可行)

AABBAABCDC(判断间段的字符串是否可行)

AAAABBBCCD(判断含空格的字符串是否可行)

2需求分析

程序的基本功能

该程序大体上有两个功能:

1.输入任何一个字符串后,该程序能统计不同字符串的个数,并以不同字符串的个数作为权值。

2.已知不同字母的权值,以该权值作为叶结点,构造一棵带权路径最小的树,对该树从叶结点到根结点路径分支遍历,经过一个分支就得到一位夫曼编码值。

(规定哈夫曼树中的左分支为0,右分支为1,则从根结点到每个叶结点所经过的分支对应的0和1组成的序列便为该结点对应字符的编码)

输入值、输出值以及输入输出形式

输入值:

AAAABBBCCD

输出值:

W=4C=0

W=3C=10

W=2C=111

W=1C=110

输入值:

AABBAABCDC

输出值:

W=4C=0

W=3C=10

W=2C=111

W=1C=110

输入值:

AAAABBBCCD

输出值:

W=4C=11

W=1C=010

W=3C=10

W=2C=00

W=1C=011

各个模块的功能要求

1.统计模块

任意输入一个字符串,不论字母是否相联,字符串中是否含空格都能统计出不同字母的个数。

2.建立哈夫曼树模块

以统计的字符串个数作为权值,利用仿真存储结构,建立带权路径最小的树。

其中对结点的存储需要六个域,分别是weight域,flag域,parent域,leftChild域,rightChild域。

weight域是对权值的存放,flag域是一个标志域,flag=0时表示该结点尚未加入到哈夫曼树中,flag=1时表示该结点已加入到哈夫曼树中。

3.哈夫曼编码模块

从哈夫曼树的叶结点到根结点路径分支逐步遍历,每经过一个分支就得到一位哈夫曼编码。

哈夫曼编码也利用仿真存储结构。

4.主函数模块

从屏幕上输入字符串,调用函数,输出每个字母的权值与编码。

3概要设计

所需的ADT,每个程序中使用的存储结构设计说明(如果指定存储结构请写出该存储结构的定义)

抽象数据类型集合:

在该程序中未用到抽象数据类型,主要用到的数据类型为:

int,char。

在哈夫曼树的建立与哈夫曼树的编码中用到仿真存储

主程序流程以及模块调用关系

输入字符串——〉调用count函数——〉申请内存空间——〉调用Haffman

——〉调用HaffmanCode——〉输出权值与编码。

各个模块的算法设计说明

1.主函数模块

 

n

y

 

y

n

n

y

 

主函数中利用gets输入一个字符串,调用count函数统计不同字母的个数,在调用

Haffman函数建立哈夫曼树,然后调用HaffmanCode函数进行编码,如果成功,输出权

值与编码,否则退出。

2.

统计函数

 

y

N

y

y

 

N

Y

 

统计函数在统计不同字符个数时先利用一个for循环遍历所有的字母,每遍历一个不同字母前令temp=1,然后用一个for循环将其后的字母与之比较,若相等则temp++,且将该字母从字符串中删除,否则从下一个字母遍历。

如此循环直到字符串结束。

3.Haffman函数

 

n

 

yn

n

y

 

n

y

n

y

 

y

 

Haffman函数主要以仿真结构存储信息,开始对每个域开始赋值,再根据不同的情况对每个域的值进行修改,如此循环下去,直到每个域的值修改完全。

4.HffmanCode函数

 

n

 

y

n

 

nny

y

 

HaffmanCode函数主要以仿真结构存储信息,由叶结点向根结点遍历,从数据域start域开始编码,bit数组存放编码,其编码为0,1序列.。

4详细设计

数据类型

typedefstruct

{

intweight;/*权值*/

intflag;/*标记*/

intparent;/*双亲结点下标*/

intleftChild;/*左孩子下标*/

intrightChild;/*右孩子下标*/

}HaffNode;/*哈夫曼树的结点结构*/

typedefstruct

{

intbit[MaxN];/*数组*/

intstart;/*编码的起始下标*/

intweight;/*字符的权值*/

}Code;/*哈夫曼编码结构*/

intweight[16];/*用于存放权值*/

chars[30];/*存放字符串*/

函数调用

 

5各个算法实现的源程序

1.字符串统计源程序:

intcount(char*s,int*weight,intn)

{

inti,j,temp,k=0,p;

for(i=0;i

='\0';i++)

{

temp=1;

for(j=0;j

{

if(s[j]==s[i]&&i!

=j)

{

temp++;

for(p=j;p

s[p]=s[p+1];

n--;

j--;

}

}

weight[k++]=temp;/*temp作为权值赋给weight数组*/

}

returni;/*返回权值个数*/

}

2.哈夫曼树建立源程序

voidHaffman(intweight[],intn,HaffNodehaffTree[])

/*建立叶结点个数为n,权值数组为weight的哈夫曼树haffTree*/

{

inti,j,m1,m2,x1,x2;

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

{

if(i

haffTree[i].weight=weight[i];

else

haffTree[i].weight=0;

haffTree[i].parent=0;

haffTree[i].flag=0;

haffTree[i].leftChild=-1;

haffTree[i].rightChild=-1;

}

/*构造哈夫曼树haffTree的n-1个非叶结点*/

for(i=0;i

{

m1=m2=MaxValue;

x1=x2=0;

for(j=0;j

{

if(haffTree[j].weight

{

m2=m1;

x2=x1;

m1=haffTree[j].weight;

x1=j;

}

else

if(haffTree[j].weight

{

m2=haffTree[j].weight;

x2=j;

}

}

/*将找出的两颗权值最小的子树合并为一棵子树*/

haffTree[x1].parent=n+i;

haffTree[x2].parent=n+i;

haffTree[x1].flag=1;

haffTree[x2].flag=1;

haffTree[n+i].weight=haffTree[x1].weight+haffTree[x2].weight;

haffTree[n+i].leftChild=x1;

haffTree[n+i].rightChild=x2;

}

}

 

3.哈夫曼树编码函数

voidHaffmanCode(HaffNodehaffTree[],intn,CodehaffCode[])

/*由n个结点的哈夫曼树haffTree构造哈夫曼编码haffCode*/

{

Code*cd=(Code*)malloc(sizeof(Code));

inti,j,child,parent;

/*求n个结点的哈夫曼编码*/

for(i=0;i

{

cd->start=n-1;

cd->weight=haffTree[i].weight;

child=i;

parent=haffTree[child].parent;

/*由叶结点向上直到根结点*/

while(parent!

=0)

{

if(haffTree[parent].leftChild==child)

cd->bit[cd->start]=0;/*左孩子分支编码0*/

else

cd->bit[cd->start]=1;/*左孩子分支编码1*/

cd->start--;

child=parent;

parent=haffTree[child].parent;

}

for(j=cd->start+1;j

haffCode[i].bit[j]=cd->bit[j];/*保存每个叶结点的编码*/

haffCode[i].start=cd->start;/*保存不等长编码的起始位置*/

haffCode[i].weight=cd->weight;/*保存相应字符的权值*/

}

}

 

6调试分析

测试数据与输出结果与2.2结果相同。

对过函数的分析:

1.count函数:

最坏情况下时间复杂度为O(n*n*n),调试时必须给定字符串的长度,否则会输出乱码,这很不方便。

只要在条件语句中加上”s[i]!

='\0'”,就能解决。

同时对入含空格的字符串不能正确统计,因为输入字符串是以scanf的形式输入,scanf遇到空格自动结束,将scanf改为gets即可,出现gets(s);

2.Haffman函数在最坏情况下计算的次数为2*n-1+(3*n-3)*n/2时间复杂度最坏情况下为O(n*n);Haffman函数在书写时要注意定义变量的位置。

3.HaffmanCode函数在最坏情况下计算的次数为n*(3*n-1),时间复杂度为O(n*n);HaffmanCode函数在书写时要注意定义变量的位置。

4.主函数的时间复杂度又输入的字符串决定。

曾在主函数中将printf("输入:

\n");get(s),n=count(s,weight,30)放在Haffman(weight,n,myHaffTree);HaffmanCode(myHaffTree,n,myHaffCode)前面,出现很多问题,像“HaffNodeundefine”,”seeundeclearHaffNode”等,调整后没有问题。

主函数的时间复杂度由输入的字符串决定。

算法改进设想:

由于统计函数时间复杂度较高,是否降低其时间复杂度?

统计函数中用到三个循环,一个用于遍历所有字符,一个用于寻找相同字符,一个用于删除相同字符。

而且三个循环嵌套,如果能减少循环的次数或者是由较少的循环嵌套,就能降低时间复杂度了。

7使用说明

在写源程序前先将所要用到的函数都写好,以“”保存起来。

再书写主函数,保存到相同的位置。

在vc环境下,用“Build”里面的“complie”,进行编译,运行。

利用Debug中的F5,F10,F9,F11设置断点等进行调试。

8测试结果

 

 

 

 

9源程序

包含哈夫曼树和图,以哈夫曼树为主要。

图在压缩文件中

哈夫曼树

#include

#include

#defineMaxValue10000

#defineMaxBit4

#defineMaxN10

typedefstruct

{

intweight;/*权值*/

intflag;/*标记*/

intparent;/*双亲结点下标*/

intleftChild;/*左孩子下标*/

intrightChild;/*右孩子下标*/

}HaffNode;/*哈夫曼树的结点结构*/

 

typedefstruct

{

intbit[MaxN];/*数组*/

intstart;/*编码的起始下标*/

intweight;/*字符的权值*/

}Code;/*哈夫曼编码结构*/

voidHaffman(intweight[],intn,HaffNodehaffTree[])

/*建立叶结点个数为n,权值数组为weight的哈夫曼树haffTree*/

{

inti,j,m1,m2,x1,x2;

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

{

if(i

haffTree[i].weight=weight[i];

else

haffTree[i].weight=0;

haffTree[i].parent=0;

haffTree[i].flag=0;

haffTree[i].leftChild=-1;

haffTree[i].rightChild=-1;

}

/*构造哈夫曼树haffTree的n-1个非叶结点*/

for(i=0;i

{

m1=m2=MaxValue;

x1=x2=0;

for(j=0;j

{

if(haffTree[j].weight

{

m2=m1;

x2=x1;

m1=haffTree[j].weight;

x1=j;

}

else

if(haffTree[j].weight

{

m2=haffTree[j].weight;

x2=j;

}

}

/*将找出的两颗权值最小的子树合并为一棵子树*/

haffTree[x1].parent=n+i;

haffTree[x2].parent=n+i;

haffTree[x1].flag=1;

haffTree[x2].flag=1;

haffTree[n+i].weight=haffTree[x1].weight+haffTree[x2].weight;

haffTree[n+i].leftChild=x1;

haffTree[n+i].rightChild=x2;

}

}

 

voidHaffmanCode(HaffNodehaffTree[],intn,CodehaffCode[])

/*由n个结点的哈夫曼树haffTree构造哈夫曼编码haffCode*/

{

Code*cd=(Code*)malloc(sizeof(Code));

inti,j,child,parent;

/*求n个结点的哈夫曼编码*/

for(i=0;i

{

cd->start=n-1;

cd->weight=haffTree[i].weight;

child=i;

parent=haffTree[child].parent;

/*由叶结点向上直到根结点*/

while(parent!

=0)

{

if(haffTree[parent].leftChild==child)

cd->bit[cd->start]=0;/*左孩子分支编码0*/

else

cd->bit[cd->start]=1;/*左孩子分支编码1*/

cd->start--;

child=parent;

parent=haffTree[child].parent;

}

for(j=cd->start+1;j

haffCode[i].bit[j]=cd->bit[j];/*保存每个叶结点的编码*/

haffCode[i].start=cd->start;/*保存不等长编码的起始位置*/

haffCode[i].weight=cd->weight;/*保存相应字符的权值*/

}

}

intcount(char*s,int*weight,intn)

{

inti,j,temp,k=0,p;

for(i=0;i

='\0';i++)

{

temp=1;

for(j=0;j

{

if(s[j]==s[i]&&i!

=j)

{

temp++;

for(p=j;p

s[p]=s[p+1];

n--;

j--;

}

}

weight[k++]=temp;

}

returni;

}

voidmain()

{

inti,j,n;

intweight[16];

chars[30];

 

HaffNode*myHaffTree;

Code*myHaffCode;

printf("************输入字符串************\n");

gets(s);

n=count(s,weight,30);

myHaffTree=(HaffNode*)malloc(sizeof(HaffNode)*(2*n+1));

myHaffCode=(Code*)malloc(sizeof(Code)*n);

if(n>MaxN)

{

printf("给出的n越界,修改MaxN!

\n");

exit

(1);

}

 

Haffman(weight,n,myHaffTree);

HaffmanCode(myHaffTree,n,myHaffCode);

/*输出每个叶结点的哈夫曼编码*/

for(i=0;i

{

printf("W=%dC=",myHaffCode[i].weight);

for(j=myHaffCode[i].start+1;j

printf("%d",myHaffCode[i].bit[j]);

printf("\n");

}

}

 

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

当前位置:首页 > PPT模板 > 卡通动漫

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

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