数据结构课程设计报告.docx

上传人:b****5 文档编号:6486440 上传时间:2023-01-06 格式:DOCX 页数:23 大小:106.44KB
下载 相关 举报
数据结构课程设计报告.docx_第1页
第1页 / 共23页
数据结构课程设计报告.docx_第2页
第2页 / 共23页
数据结构课程设计报告.docx_第3页
第3页 / 共23页
数据结构课程设计报告.docx_第4页
第4页 / 共23页
数据结构课程设计报告.docx_第5页
第5页 / 共23页
点击查看更多>>
下载资源
资源描述

数据结构课程设计报告.docx

《数据结构课程设计报告.docx》由会员分享,可在线阅读,更多相关《数据结构课程设计报告.docx(23页珍藏版)》请在冰豆网上搜索。

数据结构课程设计报告.docx

数据结构课程设计报告

一、《数据结构》课程设计

实验报告

●1.问题分析

1.1【基本要求】:

建立双向链表,并进行插入,查找,删除等操作。

1.2【分析过程】:

先通过创建函数建立双向链表,由文本文件提供数据。

可以调用查找函数,查找与e值相同的结点是否存在;也可以通过插入函数,在第i个结点前插入值为e的结点,并且调节指针的变化;也可以调用删除函数,删除第i个结点,调节好指针,最后通过保存函数保留数据到文本文件中。

●2.数据结构描述

#include

#include

usingnamespacestd;

typedefstructdulnode{

intdata;

structdulnode*prior;

structdulnode*next;

}dulnode,*dulinklist;

●3.算法设计

3.1算法1:

创建双向链表

statuscreate_dul(dulinklist&l)/*利用尾插法建立头带头结点的双向链表*/

{

l=(dulinklist)malloc(sizeof(dulnode));/*生成头结点*/

l->prior=NULL;

l->next=NULL;/*头结点的指针域初始值为空*/

l->data=-1;

q=l;/*尾指针初始指向头结点*/

FILE*fp;/*定义文件指针的形式*/

if((fp=fopen("F:

\\test1.txt","r+"))==NULL)/*打开文本文件*/

{

printf("cannotopenfile!

\n");

exit(0);

}

intn;

fscanf(fp,"%d",&n);

for(i=0;i

{

p=(dulinklist)malloc(sizeof(dulnode));

fscanf(fp,"%d",&p->data);/*在文件读取结点的数据*/

p->next=NULL;/*新结点指针域为空*/

p->prior=q;

q->next=p;/*尾结点指针域指向新结点*/

q=p;/*q指针后移,始终指向尾指针*/

}

fclose(fp);/*关闭文本文件*/

 

}

 

3.2算法2:

双向链表的查找

staduslocateelem_dul(dulinklistl,elemtypee)/*查找双线链表中第一个值为e的结点位置*/

{

p=l->next;/*p指向第一个结点*/

j=1;/*j表示结点位置*/

while((p->data!

=e)&&p){

p=p->next;

++j;

}/*寻找第一个值为e的结点位置*/

if(!

p)return-1;

elsereturn1;

}

 

3.3算法3:

双向链表的插入

statuslistinsert_dul(dulinklist&l,inti,elemtypee)/*在双向链表l中的第i个位置之前插入新结点s*/

{

p=l;/*p指向头结点*/

j=0;/*j表示结点位置*/

while(p&&(j

p=p->next;

++j;

}/*寻找第i-1个结点位置*/

if(!

p||j>i-1)returnERROR;/*在l中确定插入位置,p=NULL或j>i-1时,即插入位置不合法*/

if(!

(s=(dulinklist)malloc(sizeof(dulnode))))returnERROR;/*动态生成新结点失败,则返回错误*/

s->data=e;/*给新结点的数据域赋值*/

s->next=p->next;

p->next->prior=s;

s->prior=p;

p->next=s;/*在双向链表中插入新结点时指针的变化*/

return0;

}

3.4算法4:

双向链表的删除

statuslistdelete_dul(dulinklist&l,inti,elemtype&e)/*在双向链表l中,删除第i个结点*/

{

p=l->next;/*p指向第一个结点*/

intj=1;/*j表示结点位置*/

while(p&&(j

p=p->next;

++j;

}/*寻找第i个结点*/

if(!

p||j>i)returnERROR;/*在l中确定第i个元素的位置指针p,p=NULL,即第i个元素不存在*/

e=p->data;/*把指针p的数据域的值赋给e*/

p->prior->next=p->next;

p->next->prior=p->prior;/*在双向链表中删除结点时指针的变化*/

free(p);/*把结点p删掉*/

return0;

}

 

●4.程序清单

#include

#include

usingnamespacestd;

typedefstructdulnode{

intdata;/*数据域*/

structdulnode*prior;/*指向前驱的指针域*/

structdulnode*next;/*指向后继的指针域*/

}dulnode,*dulinklist;

voidcreate_dul(dulinklist&l)/*利用尾插法建立头带头结点的双向链表*/

{

dulinklistp,q;

inti;

l=(dulinklist)malloc(sizeof(dulnode));/*生成头结点*/

l->prior=NULL;

l->next=NULL;/*头结点的指针域初始值为空*/

l->data=-1;

q=l;/*尾指针初始指向头结点*/

FILE*fp;/*定义文件指针的形式*/

if((fp=fopen("H:

\\test1.txt","r+"))==NULL)/*打开文本文件*/

{

printf("cannotopenfile!

\n");

exit(0);

}

intn;

fscanf(fp,"%d",&n);

for(i=0;i

{

p=(dulinklist)malloc(sizeof(dulnode));

fscanf(fp,"%d",&p->data);/*在文件读取结点的数据*/

p->next=NULL;/*新结点指针域为空*/

p->prior=q;

q->next=p;/*尾结点指针域指向新结点*/

q=p;/*q指针后移,始终指向尾指针*/

}

fclose(fp);/*关闭文本文件*/

}

 

dulinklistlistinsert_dul(dulinklist&l,inti,inte)/*在双向链表l中的第i个位置之前插入新结点s*/

{

dulinklistp,s;

p=l;/*p指向头结点*/

intj=0;/*j表示结点位置*/

while(p&&(j

p=p->next;

++j;

}/*寻找第i-1个结点位置*/

if(!

p||j>i-1)returnNULL;/*在l中确定插入位置,p=NULL或j>i-1时,即插入位置不合法*/

if(!

(s=(dulinklist)malloc(sizeof(dulnode))))returnNULL;/*动态生成新结点失败,则返回错误*/

s->data=e;/*给新结点的数据域赋值*/

s->next=p->next;

p->next->prior=s;

s->prior=p;

p->next=s;/*在双向链表中插入新结点时指针的变化*/

return0;

}

dulinklistlistdelete_dul(dulinklist&l,inti,int&e)/*在双向链表l中,删除第i个结点*/

{

dulinklistp;

p=l->next;/*p指向第一个结点*/

intj=1;/*j表示结点位置*/

while(p&&(j

p=p->next;

++j;

}/*寻找第i个结点*/

if(!

p||j>i)returnNULL;/*在l中确定第i个元素的位置指针p,p=NULL,即第i个元素不存在*/

e=p->data;/*把指针p的数据域的值赋给e*/

p->prior->next=p->next;

p->next->prior=p->prior;/*在双向链表中删除结点时指针的变化*/

free(p);/*把结点p删掉*/

return0;

}

intlocateelem_dul(dulinklistl,inte)/*查找双线链表中第一个值为e的结点位置*/

{

dulinklistp;

intj;

p=l->next;/*p指向第一个结点*/

j=1;/*j表示结点位置*/

while((p->data!

=e)&&p){

p=p->next;

++j;

}/*寻找第一个值为e的结点位置*/

if(!

p)

return-1;/*返回第一个值为e的结点位置*/

else

return1;

}

voidprint_dul(dulinklistl)/*打印双向链表l*/

{

dulinklistp;

p=l;/*p指向头结点*/

while(p){

printf("%d",p->data);

p=p->next;

}/*把双向链表中的数据都打印出来*/

}

voidsave_dul(dulinklistl)

{

FILE*fp;

if((fp=fopen("H:

\\test2.txt","w+"))==NULL)

{

printf("cannotopenfile!

\n");

exit(0);

}

while(l)

{

fprintf(fp,"%d",l->data);

l=l->next;

}

}

voidmain(){

dulinklistl;

inti,e,x;

intpos;

create_dul(l);/*调用双向链表建立函数*/

print_dul(l);/*调用双向链表的打印函数*/

while

(1){

printf("inputxtochoose(1.查找,2.插入,3.删除,4.0ver):

\n");

scanf("%d",&x);

switch(x){

case1:

printf("\npleaseinputthedatayouwanttolocate:

\n");

scanf("%d",&e);/*输入要查找的值*/

pos=locateelem_dul(l,e);/*调用双向链表的查找函数*/

if(pos==-1)printf("Thedataisnotfound!

\n");

elseprintf("Thedataisfound!

\n");break;

case2:

printf("pleaseinputthepositionyouwanttoinsert:

\n");

scanf("%d",&i);/*输入要插入的位置*/

printf("pleaseinputthedatayouwanttoinsert:

\n");

scanf("%d",&e);/*输入新结点的数据*/

listinsert_dul(l,i,e);/*调用双向链表的插入函数*/

print_dul(l);break;/*调用双向链表的打印函数*/

case3:

printf("\npleaseinputthepositionyouwanttodelete:

\n");

scanf("%d",&i);/*输入要删除结点的位置*/

listdelete_dul(l,i,e);/*调用双向链表的删除函数*/

print_dul(l);break;/*调用双向链表的打印函数*/

case4:

save_dul(l);

exit(0);

}

}

}

 

●5.程序运行结果

 

●6.总结:

通过此次数据结构的课程设计,我对程序的编程,编译,执行等有了更深的认识。

理解到思路对于一个程序的重要性,在整个设计过程中,遇到了很多不同的问题,但通过尝试,努力和老师的帮助最终都解决了,感到很有成就感。

从中,我意识到程序的成功不仅仅是消除语法上的错误,而且还要执行成功。

缺乏完整的思路,尽管语法正确,程序还是无法执行。

数据结构的设计考验的不仅仅是我们对书本知识的理解,还考验了我们分析事物时思维的逻辑紧密性,加深并巩固了我对数据结构的认识。

总的来说,这次的数据结构课程设计加深了我对数据结构的认识,也学到了相关的知识,并且巩固了课堂上所学的知识,还锻炼了实践的应用操作能力,感受颇深,也收获了成功的喜悦。

 

一、《哈夫曼编码器》课程设计

实验报告

设计目的

 

1、利用学过的数据结构知识设计一个简单的哈夫曼编/译码器系统。

2、了解并掌握数据结构与算法的设计方法,具备初步的独立分析和设计能力;

3、初步掌握软件开发过程的问题分析、系统设计、程序编码、测试等基本方法和技能;

4、提高综合运用所学的理论知识和方法独立分析和解决问题的能力;

5、训练用系统的观点和软件开发一般规范进行软件开发,培养软件工作者所应具备的科学的工作方法和作风。

 

2

需求分析

2.1、选题的意义和背景

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

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

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

2.2、基本要求

(1)初始化:

键盘输入字符集大小n、n个字符和n个权值,建立哈夫曼树;

(2)编码:

利用建好的哈夫曼树生成哈夫曼编码;

(3)输出编码;

(4)设字符集及频度如下表:

字符

ABCDEFGHIJKLM

频度

1866413223210321154757153220

字符

NOPQRSTUVWXYZ

频度

5763151485180238181161

2.3、运行环境及开发工具

本程序采用VisualC++6.0编程实现。

3

概要设计

3.1设计思想

本程序的主要功能是实现对用户输入的字符编码,然后再把编码结果翻译成原字符。

但在进行这些操作之前必须做一项工作,就是创建Huffman树。

哈夫曼树又称最优二叉树,是一种带权路径长度最短的二叉树。

所谓树的带权路径长度,就是树中所有的叶结点的权值乘上其到根结点的路径长度(若根结点为0层,叶结点到根结点的路径长度为叶结点的层数)。

树的带权路径长度记为WPL=(W1*L1+W2*L2+W3*L3+...+Wn*Ln),N个权值Wi(i=1,2,...n)构成一棵有N个叶结点的二叉树,相应的叶结点的路径长度为Li(i=1,2,...n)。

可以证明哈夫曼树的WPL是最小的。

哈夫曼在上世纪五十年代初就提出这种编码时,根据字符出现的概率来构造平均长度最短的编码。

它是一种变长的编码。

在编码中,若各码字长度严格按照码字所对应符号出现概率的大小的逆序排列,则编码的平均长度是最小的。

 

4

3.2程序框图及流程图

 

3.3方法及原理

3.3.1 创建Huffman树

本文创建Huffman树是在顺序链表的基础上进行的,建树原理如下:

1、根据给定的n个权值{w1,w2,w3,……,wn},构造具有n棵二叉树的森林F={T1,T2,T3,……,Tn},其中每棵二叉树Ti只有一个带权值wi的根结点,其左右子树均为空。

2、重复以下步骤,直到F中仅剩下一棵树为止:

(1)在F中选取两棵根结点的权值最小的二叉树,作为左右子树构造一棵新的二叉树。

使新的二叉树的根结点的权值为其左右子树上根结点的权值之和。

(2)在F中删去这两棵二叉树,把新的二叉树加入F。

最后得到的就是Huffman树。

3.3.2编码

编码操作需在建立好Huffman树的基础上进行。

二叉树的叶子结点标记字符,由根结点沿着二叉树路径下行,左分支标记为0,右分支标记为1,则每条从根结点到叶子结点的路径唯一表示了该叶结点的二进制编码。

编码的时候,我们采用从叶子结点向上回溯的方法编码,如果当前结点是其父结点的左孩子,则编码为0,如果是右孩子,则编码为1,如此回溯,直到父结点为空时,该字符的编码就结束了,对应编码结构中的编码数组就是该字符的编码。

如此操作,直到所有叶子结点都扫描一遍为止,即编码结束。

3.4主要的数据结构

3.4.1Huffman结点结构

Huffman结点结构是本程序的基本结构,所有操作都在此上进行。

其中包括存储字符的元素data,字符的权值weight,以及左右孩子指针和父指针。

typedefstruct

{

charch;//结点值

intweight;//权值

intparent;//父结点指针

intlchild;//左孩子结点指针

intrchild;//右孩子结点指针

}huffnode;

 

详细设计

4.1创建Huffman树

4.1.1功能描述

Huffman树是整个程序的核心部分,是编码译码操作的前提。

哈夫曼树又称最优二叉树,是一种带权路径长度最短的二叉树。

根据字符出现的概率来构造平均长度最短的编码。

它是一种变长的编码。

在编码中,若各码字长度严格按照码字所对应符号出现概率的大小的逆序排列,则编码的平均长度是最小的。

4.1.2算法原理

首先根据用户输入创建n棵子树的森林,然后对所有子树扫描,找出权值最小的两个子树,把它们合并成一棵新的子树,同时把它们的权值之和作为新树的权值。

把这两棵子树删掉,再把新树加如到森林中,然后再扫描出权值最小的两棵子树,接着进行同样的操作,直到只剩下一棵树即为Huffman树。

4.1.3算法流程

 

7

4.2编码

4.2.1功能描述

编码的功能就是把字符转换成二进制数来存储

4.2.2算法原理

编码的时候,我们采用从叶子结点向上回溯的方法编码,如果当前结点是其父结点的左孩子,则编码为0,如果是右孩子,则编码为1,如此回溯,直到父结点为空时,该字符的编码就结束了,对应编码结构中的编码数组就是该字符的编码。

如此操作,直到所有叶子结点都扫描一遍为止,即编码结束。

 

4.2.3算法流程

4.4源程序

#include

#include

#include

#include

#include

typedefstruct{//哈夫曼树的结构体

charch;

intweight;//权值

intparent,lchild,rchild;

}htnode,*hfmtree;

typedefchar**hfmcode;

voidSelect(hfmtree&HT,inta,int*p1,int*p2)//Select函数,选出HT树到a为止,权值最小且parent为0的2个节点

{

inti,j,x,y;

for(j=1;j<=a;++j){

if(HT[j].parent==0){

x=j;

break;

}

}

for(i=j+1;i<=a;++i){

if(HT[i].weight

x=i;//选出最小的节点

}

}

for(j=1;j<=a;++j){

if(HT[j].parent==0&&x!

=j)

{

y=j;

break;

}

}

for(i=j+1;i<=a;++i)

{

if(HT[i].weight

=i)

{

y=i;//选出次小的节点

}

}

if(x>y){

*p1=y;

*p2=x;

}

else

{

*p1=x;

*p2=y;

}

}

voidhfmcoding(hfmtree&HT,hfmcode&HC,intn)//构建哈夫曼树HT,并求出n个字符的哈夫曼编码HC

{

inti,start,c,f,m,w;

intp1,p2;

char*cd,z;

if(n<=1){

return;

}

m=2*n-1;

HT=(hfmtree)malloc((m+1)*sizeof(htnode));

for(i=1;i<=n;++i)//初始化n个叶子结点

{

printf("请输入第%d字符信息和权值:

",i);

scanf("%c%d",&z,&w);

while(getchar()!

='\n')

{

continue;

}

HT[i].ch=z;

HT[i].weight=w;

HT[i].parent=0;

HT[i].lchild=0;

HT[i].rchild=0;

}

for(;i<=m;++i)//初始化其余的结点

{

HT[i].ch='0';

HT[i].weight=0;

HT[i].parent=0;

HT[i].lchild=0;

HT[i].rchild=0;

}

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

{

Select(HT,i-1,&p1,&p2);

HT[p1].parent=i;HT[p2].parent=i;

HT[i].lchild=p1;HT[i].rchild=p2;

HT[i].weight=HT[p1].weight+HT[p2].weight;

}

HC=(hfmcode)malloc((n+1)*sizeof(char

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

当前位置:首页 > 医药卫生 > 临床医学

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

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