数据结构课程设计两个链表合并星Word格式文档下载.docx
- 文档编号:17931792
- 上传时间:2022-12-12
- 格式:DOCX
- 页数:18
- 大小:64.67KB
数据结构课程设计两个链表合并星Word格式文档下载.docx
《数据结构课程设计两个链表合并星Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《数据结构课程设计两个链表合并星Word格式文档下载.docx(18页珍藏版)》请在冰豆网上搜索。
Lb,Linklist&
Lc){
//已知单线性链表La和Lb的元素按值非递减排列。
//归并La和Lb得到新的线性表Lc,Lc的数据元素也按非递减排列。
InitList(Lc);
i=j=1;
k=0;
La_len=Listlength(La);
Lb_len=ListLength(Lb);
While((i<
=La_len)&
&
(j<
=Lb_len)){//La和Lb均非空
Getelem(La,i,ai);
Getelem(Lb,j,bj);
If(ai<
=bj){Listinsert(Lc,++kai);
++i;
}
Else{Listinsert(Lc,++kbj);
++j;
While(i<
=La_len){
Getelem(La,i++,ai);
Listinsert(Lc,++k,ai);
While(j<
=Lb_len){
Getelem(Lb,j++,bj);
Listinsert(Lc,++k,bj);
}}//Mergelist
(3)把元素插入到链表当中
在链表的合并中常用的操作是插入,要在线性表的两个元素之间出入一个新的元素x。
为了插入元素x,首先要生成一个数据域为x的结点,然后插入数据元素x。
根据插入操作的逻辑定义,还要修改结点a中的指针域,令其指向结点x,而结点x中的指针域应指向结点b,从而实现3个元素a,b和x之间的逻辑变化。
上述指针修改语句描述为,
s—>
next=p—>
next;
p—>
next=s;
单链表中插入结点时的指针变化情况如图所示:
p
图1单链表中插入结点时的指针变化情
插入元素的代码如下:
statusListInsert_L(LinkList&
L,inti,ElemTypee){
//在带头结点的单链线性表L中第i个位置之前插入元素e
p=l;
j=0;
while(p&
j<
i-1){p=p->
}//寻找第i-1个结点
if(!
P||j>
i-1)returnERROR;
//i小于1或者大于表长+1
s=(LinkList)malloc(sizeof(LNode));
//生成新结点
s->
date=e;
s->
next=p->
//插入L中
p->
returnOK;
}//ListInsert_L
(4)在链表中删除元素
在线性表中删除元素b时,为了在单链表中实现元素a、b和c之间逻辑关系的变化,仅需改动节点a中的指针域即可。
假设p为指向节点a的指针,则修改指针的语句为
next->
删除节点时指针变化情况如图2所示
图2单链表删除节点时指针变化情况
在已知单链表中元素插入或插入或删除的确切位置的情况下,在单链表中插入
删除一个结点时,仅需修改指针而不需要移动元素。
删除元素代码如下:
StatusListInsert_L(LinkList&
L,intI,ElemTypee){
//在带头结点的单链表线性表L中,删除第i个元素,并由e返回其值
p=L;
while(p&
i-1){//寻找第i-1个结点,并令p指向其前驱
p=p—>
+j:
If(!
(p—>
next)||j>
//删除位置不合理
q=p—>
next=q—>
//删除并释放结点
e=q—>
data;
free(q);
//释放函数
retrunOK;
}//ListDelete_L
2.1.2链表的合并
链表的合并是将两个链表合并成一个链表。
假设两个链表LA和LB头指针为La,Lb,要归并La和Lb得到链表Lc,pa和pb分别指向La和Lb表中当前待比较插入的结点,
而pc指向Lc当前最后一个结点,若pa—>
data<
pb—>
data,则将pa所指结点链接到pc所指结点之后,,否则将pb所指结点链接到pc所指结点之后。
当LA和LB为非空表时,pa和pb分别指向La和Lb表中第一个结点,否则为空;
pc指向空表Lc中的头结点。
由于链表的长度为隐含的,则第一个循环执行的条件pa和pb皆非空,当其中一个为空时,说明有一个表的元素已归并完,则是要将另一个表的剩余段链接在pc所指结点之在内部排序中,如果按照排序过程中依据的不同原则进行分类,则大致可以分为插入排序、交换排序、选择排序、归并排序、和计数排序5类。
通常在排序过程中需进行一下两种基本操作:
(1)比较两个关键字的大小;
(2)将记录从一个位置转移到另一个位置。
前一个基本操作是对于任何排序方法来说都是必要的,而后者可以通过改变记录的储存方式来来予以避免。
且为了研究方便起见,设关键字均为整数。
待排序、记录的数
typedefstruct{
KeyTypekey;
//关键字项
InfoTypeotherinfo;
//其他数据项
Typedefstruct{
RedTyper[MSXSIZE+1];
//r[0]闲置或用作哨兵单元
Intlength;
//顺序表长度
}SqList//顺序表类型
本课程设计主要是应用直接插入排序将合并的链表进行排序。
直接插入排序是一种最简单的排序方法,他的基本操作是将一个记录插入已排好序的有序表中,从而得到一个新的、数据记录增一得有序表。
一般情况下,第i趟直接插入排序的操作为:
在含有i-1个记录的有序子序列r[1.i-1]中插入一个记录r[i]后,变成含有i个记录的有序子序列r1.i[];
并且和顺序表查找类似,在r[0]处设置监视哨。
在自i-1起往前收索的过程中,可以同时后已记录。
整个排序过程为进行n-1趟插入,即:
先将序列中的第一个记录看做一个有序的子序列,然后从第二个记录起逐个插入,直至整个序列变成按关键字有序序列为止。
链表直接插入排序的算法如下图3所示
voidInsertSort(SqList&
L){//对顺序表L作直接插入排序。
For(i=2;
i<
=L.length;
++i)
If(LT(L.r[i].Key,L.r[i-1].Key)){//“(”,需要将L.r[i]插入有序子表
L.r[0]=L.r[i]
L.r[i]=L.r[i-1];
For(j=i-2;
LT(L.r[0].Key,L.r[j].Key);
--j)
L.r[j+1]=L.r[j];
//记录后移
L.r[j+1]=L.r[0];
//插入到正确位置
}//InsertSort
2.1.3链表的排序
排序是计算机程序设计中的一个重要操作,他的功能是将一个数据元素(或记录)的任意序列,重新排列成一个按关键字有序的序列。
由于待排序的记录数量不同,使得排序过程中的存储器不同,可将排序方法分为两大类;
一类是内部排序,指的是待排序记录存放在计算机随机存储器中进行的排序过程。
另一类是外部排序,指的是待排序记录的数量很大,,以至内存一次不能容纳全部记录,在排序过程中尚需对外存进行访问的排序过程。
在链表的操作中常用到两个标准函数malloc和free。
通常,在设有“指针”数据类型的高级语言中均存在与其相应的过程与函数。
假设p和q是LinkList型的结点,则执行p=(LinkList)malloc(sizeof(LNode))的作用是由系统生成一个Lnode型的结点,同时将该结点的起始位置赋给指针变量p;
反之执行free的作用是由系统回收一个LNode型的结点,,回收后的空间可以备做再次生成结点时用。
因此,单链表和顺序存储不同,它是一种动态结构。
整个可用存储空间可为多个链表共同享用,每个链表占用的空间不需要预先分配划定,而是可以由系统即使生成。
因此建立线性表的链式存储结构的过程就是动态生成链表的过程。
即从“空表”的初始状态起,一次建立个元素的结点,并逐个插入链表。
单链表的建立算法如下,其时间复杂度为O(n×
n)。
ViodCreateList_L(LinkList&
L,intn){
//逆位序输入n个元素的值,建立带表头结点的单链线性表L。
L=(LinkList)malloc(sizef(LNode));
L—>
next=NULL;
//先建立一个带头结点的单链表
For(i=n;
i>
n;
--i){
p=(LinkList)malloc(sizeof(LNode)),//生成新结点
scanf(&
data);
next=L—>
next=p;
}//CrateList_L
2.1.4算法设计
程序的基本功能,首先建立建立单链表,向单链表中输入元素,然后输出单链表,将两个单链表进行合并。
先建立两个链表,假设分别为La=(x1,x2,…xn),Lb=(y1,y2,…yn),它们的长度分别为a,b。
若a>
b,则把这两个链表合并后,要求新链表LcLc=x1,y1,x2,y2,…xn,yn…,。
若a<
b,则新表Lc=y1,x1,y2,x2,…yn,xn并输出Lc。
本程序经过调试后运行以后有中文提示输入链表a的长度,然后手动输入链表中的元素,回车键后提示输入链表b的长度,再输入链表b的元素,回车键后本程序将按照设计需求自动进行两个链表的合并,最后进行新链表c的插入排序。
输出排好序的新链表d的相关信息。
程序的流程图如下所示:
建立链表a
建立链表b
合并ab链表
得到c链表
判断mn的大小
对c链表进行插入排序
图3程序流程图
(1)创建链表函数的设计
创建链表,首先由主函数输入要创建的链表长度n,在由主函数将参数传递到创建链表函数creat,由For循环控制表节点的创建,由malloc函数开辟新的结点空间,创建链表结束后,由print函数将链表元素输出。
创建链表函数的实现代码如下:
#include<
stdlib.h>
stdio.h>
conio.h>
malloc.h>
#defineLsizeof(structNode)
structNode//结构体
{
longintnumber;
structNode*next;
};
structNode*create(inta)//链表创建函数
intn;
structNode*p1,*p2,*head;
head=NULL;
n=0;
p2=p1=(structNode*)malloc(L);
//分配内存
scanf("
%ld"
&
p1->
number);
while(a)//录入链表信息
{
n=n+1;
if(n==1)
head=p1;
else
p2->
next=p1;
p2=p1;
p1=(structNode*)malloc(L);
if(a!
=1)//分配内存
scanf("
a--;
//控制输入的个数
}
next=NULL;
return(head);
}//链表创建函数结束
(2)输出链表的函数的实现
待链表输入完成后,定义单链表的头结点*p,通过运用一个循环语句,将链表内的元素一一输出在执行程序界面上。
voidprint(structNode*head)//输出函数
structNode*p;
p=head;
printf("
数字:
\n"
);
if(head!
=NULL)
do//循环实现输出
{
p->
"
p=p->
}while(p!
=NULL);
(3)链表的交叉合并
structNode*inter_link(structNode*chain1,inta,structNode*chain2,intb){
inttemp;
structNode*head,*p1,*p2,*pos;
/*判断a,b大小并合并*/
if(a>
=b){
head=p1=chain1;
p2=chain2;
}else/*b>
a*/{
head=p1=chain2;
p2=chain1;
temp=a,a=b,b=temp;
/*交换a和b*/
/*下面把p1的每个元素插在p2相应元素之前,p1长a,p2长b*/
pos=head;
/*此时pos指向p1中的第一个元素*/
while(p2!
=NULL){//漂亮,蛇形插入
p1=p1->
pos->
next=p2;
pos=p2;
p2=p2->
pos=p1;
returnhead;
(4)对合并好的链表进行插入排序
voidInsertSort(structNode*p,intm)//排序函数
inti,j,t;
structNode*k;
k=p;
for(i=0;
i<
m-1;
i++){
for(j=0;
j<
m-i-1;
j++){
if(p->
number>
(p->
next)->
number){
t=p->
number;
p->
number=(p->
number=t;
p=p->
p=k;
(5)主函数的定义
intmain()//main函数
structNode*p1,*p2;
inta;
intb;
inth;
printf("
请输入第一个链表:
\n输入链表的长度a:
%d"
a);
请输入链表数据:
"
p1=create(a);
\n你刚才输入的第一个链表信息:
\n"
print(p1);
\n请输入第二个链表:
\n输入链表的长度b:
b);
p2=create(b);
\n你刚才输入的第二个链表的信息:
print(p2);
p1=inter_link(p1,a,p2,b);
h=a+b;
\n合并后的链表\n:
InsertSort(p1,h);
\n排序后的链表:
return0;
3运行结果与分析
(1)打开软件,输入代码,运行程序,然后中文提示输入链表a的长度,回车之后提示输入链表中的数据元素。
录入第一组测试数据完成以后显示链表a的信息,这里m<
n。
如下图所示:
图4建立链表
(2)如果输入的元素个数超过链表定义的长度,则只录入前面的链表定义长度的那些元素。
演示如下图所示:
图5错误操作结果
继续按照提示输入链表b的长度和数据元素。
如下所示:
图6第一组数据运行结果
(3)录入第二组测试数据运行结果如下图所示:
图7第二组数据运行结果
4课程设计体会
这几天的课程设计,让我对以往课堂上学习到的理论知识得到了更深刻的理解,通过自己设计算法,调试程序一系列操作,最后才能使程序正确无误的运行,这一系列操作虽然对于我来说很复杂困难,但是通过查阅资料,以及同学的帮忙最终还是完成了本次课程设计。
以往对于链表的问题有些一知半解,有些东西也不是特别的明白清楚,有了这次课设感觉自己把以往认为很抽象的问题变得更具体,自己亲手来做这次课程设计,感觉有些明白了《数据结构》这门课程其中的奥妙。
我做两个链表的合并,想象起来并不是特别的困难,用语言很容易的就可以表达出来,对于这次课设就是编写代码来完成这一系列的操作,编写代码需要相当的加小心,一个字母的错误就能导致整个程序的错误,所以编写代码需要心细不能马虎任何一个小的字母。
我经过查阅资料,询问同学,多次的修改程序才使得程序最后的成功运行。
有了这次课设,不仅让我对这门课程有了新的认识和对知识的更深刻的理解,同时也磨练了自己的耐心和毅力。
以后学习中还需要继续努力学好这门课程。
5参考文献
[1]赵国玲.C语言与数据结构[M].北京:
电子工业出版社,1999.11:
120-146
[2]严蔚敏,吴伟民.数据结构(C语言版)[M].北京:
清华大学出版社,2006.10:
44-52
[3]严蔚敏.数据结构C语言[M].北京:
清华大学出版社,2006.10:
110-135
[4]谭浩强.C程序设计指导[M].北京:
清华大学出版社,2005
[5]潘新民,王燕芳.微型计算机控制技术[M],第2版.北京:
电子工业出版社,2003.4:
305-350
附录:
源程序
longintnumber;
intn;
//链表的交叉合并算法
pos=head;
p1=p1->
//对合并好的链表进行排序
if
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 数据结构 课程设计 两个 合并