计算机0806 陈明龙 0909082103DS课程设计.docx
- 文档编号:7562431
- 上传时间:2023-01-25
- 格式:DOCX
- 页数:62
- 大小:467.97KB
计算机0806 陈明龙 0909082103DS课程设计.docx
《计算机0806 陈明龙 0909082103DS课程设计.docx》由会员分享,可在线阅读,更多相关《计算机0806 陈明龙 0909082103DS课程设计.docx(62页珍藏版)》请在冰豆网上搜索。
计算机0806陈明龙0909082103DS课程设计
中南大学
课程设计实验报告
课程名称:
《数据结构课程设计》
设计题目:
数据结构相关算法的演示系统
(1)
院系:
信息科学与工程学院
班级:
计算机类0806班
姓名:
陈明龙
学号:
03
完成日期:
2010.7.
一、需求分析…………………………………3
二、概要设计…………………………………4
三、详细设计…………………………………6
四、调试分析…………………………………21
五、测试结果…………………………………23
六、课程设计总结……………………………33
七、参考文献…………………………………34
八、附录………………………………………34
一、需求分析:
设计一个数据结构相关算法的演示系统,主要实现的功能如下:
1:
顺序表的插入、删除和合并等基本操作;
2:
利用插入运算建立链表;实现链表的插入、删除、计数、输出及有序链表的合并;
3:
串的模式匹配(包括求next值和nextval值)。
基于以上要求,可以在设计系统的时候,在主界面设计三个大模块,即是按照要求来划分模块,每个模块实现不同的功能要求,第一个模块就实现线性表的相关操作,第二个模块就实现链表的相关操作,第三个模块就实现串的相关操作。
(一):
在第一个模块中,即是顺序表的相关操作中,主要能实现顺序表的循环插入赋值,插入、删除和合并等基本操作,顺序表的元素可以是数字也可以是字符等,但是在程序中已经定义ElemType为int型,故输入的形式为整数,采用的是动态存储分配(初始定义LIST_INIT_SIZE100),当输入的元素过多内存不足是会自动添加(LISTINCREMENT10),当然输出的也是整数,第一个模块根据功能分为几个小菜单项,以下是测试数据:
顺序表的初始化,输入1、2、3、4以‘00’结束,输出为:
初始化后的顺序表元素为NO.01,NO.02,NO.03,NO.04,当然元素个数没有限制,但是单个的元素值限制,因为一个int型数据通常用两个字节存放,即是16位二进制,当输入的数值超过这个范围是计算机打印出乱码,此时可以选择重新输入数据。
在顺序表的插入操作中,要求你输入插入的位置和插入的值,例如在上面初始化的基础上,在第4个位置插入4,结果为:
插入元素后的顺序表元素为NO.01,NO.02,NO.03,NO.04,当插入的位置大于了已有的表长度,则系统会提醒输入错误,请重新输入!
删除操作和插入操作一样,首先选择要删除的元素位置,例删除第二个元素,结果为:
删除操作后顺序表的元素是NO.01,NO.03,NO.04,同样的当所选择的位置大于了当前已有的长度,则系统提起输入错误,请重新输入!
!
在顺序表的合并操作中,主要是把两个元素值非递减排列的线性表合并为一个,并且合并后的顺序表值也是非递减的,输入另外一个顺序表的元素,例输入4、5、6,结果为:
合并后的顺序表元素为NO.01,NO.02,NO.03,NO.04,、NO.05,NO.06,当所输入的元素值不是按非递减的顺序,例两表的元素分别为6、2、1和8、4、3时,结果为6、2、1、8、4、3,并无顺序。
(二):
在第二个大模块中,主要实现的是链表的初始化,插入,删除,计数,查询和有序链表的合并功能,并且有检错和改错的能力,和线性表的一样,定义的数据类型为int型,故所输入的也是整数,元素个数不限,但是单个的元素值有限,链表不需要为其开辟一块内存空间,是非随机存储的存储结构,以下是测试数据:
在链表的初始化中,要求先输入要插入的元素个数,如3个分别是3、2、1,并逆序插入,结果为:
初始化后的链表的值为1、2、3,链表长度为3,和线性表一样当所输入的元素值超过int型的字节后,就会出现乱码,该模块中对链表的计数是结合在每一个功能中,当对链表进行操作后可以自动返回链表的长度即是计数功能,此时可以重新输入元素在进行下面的操作。
在链表的插入功能中,可以根据已有的链表选择插入的位置和插入值,例在初始化的基础上在第4个位置插入4,结果为:
插入成功,插入后链表的元素为1、2、3、4,链表长度为4,如果输入的位置大于了已有的链表长度,那么系统会提醒输入错误,请重新输入插入的位置和元素值,或者可以键入‘0’直接返回上一级菜单。
删除功能和插入功能基本上一致,首先也是要输入要删除的元素位置,例删除第3号元素,结果为:
删除成功,删除后链表的元素为1、2、4,链表长度为3,当所输入的位置大于当前的链表长度即不存在该位置,系统提示不存在该节点,请重新输入要删除的位置,如不想删除操作了,可键入‘0’返回上一级菜单。
选择了链表的合并功能后,系统会提示初始化另外一个链表,输入元素个数和元素值,该合并功能也是按元素的非递减进行合并,合并后的链表元素也是按非递减的顺序排列,例输入3个元素,分别为6、5、4逆序插入,结果为:
Lb链表的初始化元素为4、5、6,合并后的链表Lc的元素为1、2、4、4、5、6,链表长度为6,当输入的元素没有按照非递减排列时,合并后的元素也没有顺序,例La链表的元素为2、1、5,Lb的为4、5、9,结果为合并后的链表Lc元素为4、5、2、1、5、9,链表长度为6。
该模块中最后的功能是查找功能,系统提供两种查找,一种是按位置查找,一种是按元素的值来查找,先选择按位置查查,首先输入所要查找的位置,例输入5,结果是:
要查找的数存在是5,当输入的位置不存在时系统提醒:
该链表中不存在该节点,并要求重新输入节点位置,例输入8是,结果:
该链表中不存在第8个结点,请重新输入所要查找的位置。
按元素的值查找中,输入想要查找的元素,例输入6,结果为:
要查找的数存在,位置是第6个,如果输入的元素不存在,例输入10,结果为:
要查找的数不存在,请重新输入(或者按0返回上级菜单)。
(三)在第三个模块中,是串的模式匹配相关操作,包括简单模式匹配和KMP模式匹配,和next与nextval的值的求取,此模块中定义的数据元素是字符型,故输入的都是字符,输出时若是求匹配那么返回的是布尔型即是成功或者不成功,如果是求取next和nextval值那么返回的是整型数字,以下是测试的数据:
选择简单模式匹配,输入主串‘ababcabcacbab’,输入模式串‘abcac’,简单匹配lndex的结果为:
比较次数6次,模式串t在主串中的位置从第六个字符开始,匹配成功!
选择KMP算法匹配,输入主串‘ababcabcacbab’,输入模式串‘abcac’,KMP_lndex的结果为:
比较次数为3,模式串t在主串s中的位置从第六个字符开始,匹配成功;修正后的KMP算法匹配后的结果是比较次数为6,模式串t在主串中的位置从第六个字符开始,匹配成功!
求取next值,输入模式串,例‘abaabcac’,结果为:
next[1]=0,next[2]=1,next[3]=1,next[4]=2,next[5]=2,next[6]=3,next[7]=1,next[8]=2.
求取nextval值,输入字符‘aaaab’,结果为nextval[1]=0,nextval[2]=0,nextval[3]=0,nextval[4]=0,nextval[5]=4.
二、概要设计:
(一)系统子程序及其功能设计:
本系统共有24个子程序,各个子程序的功能如下所示:
(1)StatusInitList_Sq(SqList*L)//顺序表的初始化,给顺序表分配存储空间,返回值1
(2)StatusListInsert_Sq(SqList*L,inti,ElemTypee)//顺序表的插入操作,在第i个位置插入元素e,返回值1
(3)StatusIsListFull(SqList*L)//如果顺序表的存储空间满了,给顺序表增加存储空间,返回值1
(4)StatusListPrint_Sq(SqList*L)//打印顺序表的所有元素,返回值1
(5)intListDelete_Sq(SqList*L,inti)//删除顺序表中第i个位置上的元素,返回值1
(6)StatusMergeList_Sq(SqListLa,SqListLb,SqList*Lc)//将La与Lb两个顺序表的元素合并为Lc顺序表,返回值1
(7)StatusCreat_List(Link_List&L,ElemTypen)//初始化链表,并插入元素值,返回值1
(8)StatusInsert_List(Link_List&L,inti,ElemTypee)//在链表第i个位置之前插入元素e,返回值1
(9)StatusDelete_List(Link_List&L,inti,ElemType&e)//删除链表第i个位置的元素,返回值1
(10)StatusMerge_List(Link_ListLa,Link_ListLb,Link_List&Lc)//合并La与Lb两个链表为Lc链表,返回值1
(11)StatusPrint_List(Link_ListL)//打印链表的所有元素,返回值1
(12)StatusGetElem_L(Link_ListL,inti,ElemType&e)//返回链表中第i个位置上的元素,返回值1
(13)Statussearch(Link_List&L,intn)//遍历链表,如果有元素与n相同则返回其位置,返回值1
(14)Statusgetlength(Link_ListL)//返回链表的长度,,返回值1
(15)intIndex(charS[MAXSIZE],charT[MAXSIZE],intpos,int&time)//返回子串T在主串S中第pos个字符之后的位置,并数比较次数,返回值1
(16)intIndex_KMP(charS[MAXSIZE],charT[MAXSIZE],intpos,int&time,int(&next)[MAXSIZE])//返回子串T在主串S中第pos个字符之后的位置,并数比较次数,返回值1
(17)voidget_next(charT[MAXSIZE],intnext[MAXSIZE])//求模式串T的next函数值并存入数组next
(18)voidget_nextval(charT[MAXSIZE],intnextval[MAXSIZE])//求模式串T的nextval函数值并存入数组nextval
(19)voidstring_adjust_S(charS[MAXSIZE])//对输入的主串S长度进行调整
(20)string_adjust_T(charT[MAXSIZE])//对输入的字符串T长度进行调整
(21)intfunction_1()//顺序表功能实现的函数,包括顺序表操作的子界面
(22)intfunction_2()//链表功能实现的函数,包括链表操作的子界面
(23)intfunction_3()//串的模式匹配功能函数,包括串的操作子界面
(24)intmain()//主函数,包括主界面,和对功能函数的调用
(二)数据类型的定义
(1)线性表的动态分配顺序存储结构:
#defineLIST_INIT_SIZE100//线性表存储空间的初始分配量
#defineLISTINCREMENT10//线性表存储空间的分配增量
typedefstruct{
ElemType*elem;//存储空间基址
intlength;//当前长度
intlistsize;//当前分配的存储容量
}SqList;
(2)链表的存储结构:
typedefstructLnode{
ElemTypedata;//链表数据类型
structLnode*next;//定义链表节点
}LNode,*Link_List;
(3)串的抽象数据类型的定义:
ADTString{
数据对象:
D={ai|ai∈CharacterSet,i=1,2,……,n,n>=0}
数据关系:
R1={
基本操作:
Index(S,T,pos)//返回子串T在主串S中第pos个字符之后的位置,并数比较次数,返回值1
Index_KMP(charS[MAXSIZE],charT[MAXSIZE],intpos,int&time,int(&next)[MAXSIZE])//返回子串T在主串S中第pos个字符之后的位置,并数比较次数,返回值1
get_next(charT[MAXSIZE],intnext[MAXSIZE])//求模式串T的next函数值并存入数组next
nextval(charT[MAXSIZE],intnextval[MAXSIZE])//求模式串T的nextval函数值并存入数组nextval
(三)主程序的流程以及各程序模块之间的层次(调用)关系
进入系统主程序后,会提醒进行选择功能模块,本系统按照要求共分三个大模块:
1:
顺序表的相关操作;2:
链表的相关操作;3:
串的模式匹配,每个模块之间互不影响,模块与模块之间的转换由主函数main()来调用,每个模块又由几个小程序功能组成,每个小功能实现后可以退回到当前模块菜单,整个系统的退出在main()函数中,键入0退出系统,主程序和三大模块的主要流程如下所示:
三、详细设计
系统主要子程序详细设计如下:
(1)主函数,设定用户操作界面以及颜色和调用工作区功能函数
intmain(){
system("color70");
while
(1){
printf("\t☆==☆==☆==☆==☆==☆==☆==☆==☆==☆==☆==☆==☆==☆==☆\n");
printf("\t☆\t\t\t\t\t\t\t☆\n");
printf("\t||\t\t\t\t\t\t\t||\n");
printf("\t☆\t\t§欢迎进入数据结构演示系统§\t\t☆\n");
printf("\t||\t\t\t\t\t\t\t||\n");
printf("\t☆\t\t\t\t\t\t\t☆\n");
printf("\t☆\t\t1:
顺序表的相关操作演示\t\t\t☆\n");
printf("\t||\t\t\t\t\t\t\t||\n");
printf("\t☆\t\t\t\t\t\t\t☆\n");
printf("\t||\t\t2:
链表的相关操作演示\t\t\t||\n");
printf("\t☆\t\t\t\t\t\t\t☆\n");
printf("\t||\t\t\t\t\t\t\t||\n");
printf("\t☆\t\t3:
串的相关操作演示\t\t\t☆\n");
printf("\t||\t\t\t\t\t\t\t||\n");
printf("\t☆\t\t0:
退出系统\t\t\t\t☆\n");
printf("\t||\t\t\t\t\t\t\t||\n");
printf("\t☆==☆==☆==☆==☆==☆==☆==☆==☆==☆==☆==☆==☆==☆==☆\n");
intchoose;
printf("\t请选择要实现的功能:
");
scanf("%d",&choose);
system("CLS");
switch(choose){
case1:
function_1();break;
case2:
function_2();break;
case3:
function_3();break;
case0:
return1;
default:
printf("\n输入错误,请重新输入!
!
\n");break;
}
}
}
(2)第一大模块的功能函数function_1(),里面包括顺序表的操作界面和对顺序表功能函数的调用,主要结构还是运用了switch,case语句来进行选择,
intfunction_1(){
SqListLa,Lb,Lc;
intk=1,c=1,i,a,num;
printf("\t\t☆==☆==☆==☆==☆==☆==☆==☆☆☆\n");
printf("\t\t\t\t\t\t\t\n");
printf("\t\t\t☆§欢迎进入顺序表操作界面§\t☆\n");
printf("\t\t\t\t\t\t\t\t\n");
while
(1){
printf("\t\t\t☆1:
顺序表的初始化\t☆\n");
printf("\t\t\t\t\t\t\t\t\n");
printf("\t\t\t||2:
顺序表的插入\t||\n");
printf("\t\t\t\t\t\t\t\t\n");;
printf("\t\t\t☆3:
顺序表的删除\t☆\n");
printf("\t\t\t\t\t\t\t\t\n");
printf("\t\t\t||4:
顺序表的合并\t||\n");
printf("\t\t\t\t\t\t\t\t\n");
printf("\t\t\t☆0:
返回上级菜单\t☆\n");
intchoose;
printf("\n\t\t请选择对顺序表的操作:
");
scanf("%d",&choose);
system("CLS");
switch(choose){
case1:
printf("顺序表La的初始化,给La输入数值,以00为结束:
\n");
InitList_Sq(&La);
while
(1)
{
scanf("%d",&num);
if(num==00)
break;
ListInsert_Sq(&La,k,num);
k++;
}
printf("初始化后的La顺序表的元素为:
\n");
ListPrint_Sq(&La);break;
case2:
printf("初始化后的La顺序表的元素为:
\n");
ListPrint_Sq(&La);
printf("请选择要插入的位置和插入值:
");
scanf("%d%d",&i,&a);getchar();
while(i>k){printf("\n输入错误,请重新输入\n");scanf("%d%d",&i,&a);}
//getchar();
ListInsert_Sq(&La,i,a);
printf("插入操作后的La顺序表的元素为:
\n");
ListPrint_Sq(&La);
break;//顺序表的插入
case3:
printf("插入操作后的La顺序表的元素为:
\n");
ListPrint_Sq(&La);
printf("请选择要删除的位置:
");
scanf("%d",&i);
while(i-1>La.length-1){printf("\n输入错误,请重新输入\n");scanf("%d",&i);}
ListDelete_Sq(&La,i);
printf("\n删除操作后顺序表的值为:
\n");
ListPrint_Sq(&La);getchar();
break;//顺序表的删除
case4:
InitList_Sq(&Lb);
printf("顺序表Lb的初始化,给Lb输入数值,以00为结束:
\n");
while
(1){
scanf("%d",&num);getchar();
if(num==00)
break;
ListInsert_Sq(&Lb,c,num);
c++;
}
printf("初始化后的Lb顺序表的元素为:
\n");
ListPrint_Sq(&Lb);
MergeList_Sq(La,Lb,&Lc);
printf("合并后的Lc顺序表的元素为:
\n");
ListPrint_Sq(&Lc);printf("请选择要删除的位置:
");
scanf("%d",&i);
while(i-1>Lc.length-1){printf("\n输入错误,请重新输入\n");scanf("%d",&i);}ListDelete_Sq(&Lc,i);
printf("\n删除操作后顺序表的值为:
\n");
ListPrint_Sq(&Lc);getchar();
continue;//顺序表的合并
case0:
return1;
default:
printf("\n输入错误,请重新输入!
!
\n");break;
}
}
}
以下是第一个模块中调用到的算法:
StatusInitList_Sq(SqList*L){
L->elem=(ElemType*)malloc(LIST_INIT_SIZE*sizeof(ElemType));
L->length=0;//空表长度为0
L->listsize=LIST_INIT_SIZE;//初始存储容量
return1;
}//InitList_Sq;//初始化线性表
顺序表的初始化算法,采用的是动态分配存储结构。
StatusListInsert_Sq(SqList*L,inti,ElemTypee){
//在顺序线性表L中第i个位置之前插入新的元素e,
ElemType*newbase,*p,*q;
if(i<1||i>L->length+1)returnERROR;//i值不合法
if(L->length>=L->listsize){//当前存储空间已满,增加分配
newbase=(ElemType*)realloc(L->elem,(L->listsize+LISTINCREMENT)*sizeof(ElemType));
if(!
newbase)exit(OVERFLOW);//存储分配失败
L->elem=newbase;//新基址
L->listsize+=LISTINCREMENT;//增加存储容量
}
q=&(L->elem[i-1]);//q为插入位置
for(p=&(L->elem[L->length-1]);p>=q;--p){
*(p+1)=*p;}//插入位置及之后的元素右移
*q=e;//插入e
++L->length;//表长增1
return1;
}//ListInsert_Sq
顺序表的插入算法,首先判断插入位置,如果溢出返回ERR
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 计算机0806 陈明龙 0909082103 DS课程设计 计算机 0806 DS 课程设计