数据结构课程设计 链表合并.docx

上传人:b****6 文档编号:2942061 上传时间:2022-11-16 格式:DOCX 页数:20 大小:98.01KB
下载 相关 举报
数据结构课程设计 链表合并.docx_第1页
第1页 / 共20页
数据结构课程设计 链表合并.docx_第2页
第2页 / 共20页
数据结构课程设计 链表合并.docx_第3页
第3页 / 共20页
数据结构课程设计 链表合并.docx_第4页
第4页 / 共20页
数据结构课程设计 链表合并.docx_第5页
第5页 / 共20页
点击查看更多>>
下载资源
资源描述

数据结构课程设计 链表合并.docx

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

数据结构课程设计 链表合并.docx

数据结构课程设计链表合并

两个链表的合并

1.课程设计目的

实现对两个的链表的交叉合并,输出线形表C用直接插入排序法对C进行升序排序,生成链表D,并输出链表D。

掌握对线性表的链式表示和实现,实现插入的操作。

了解链表交叉合并的方法和直接插入排序法的思想,并深刻掌握算法的格式和应用。

提高对数据结构的理解和应用,增强个人动手实践能力和逻辑分析能力。

2.设计方案论证

2.1设计思路

本课程设计完成将对链表的交叉合并和直接插入排序的实现。

首先将两个链表进行交叉合并,合并的要求如下:

建立两个链表A和B,链表元素个数分别为m和n个。

假设元素分别为(x1,x2,…xm),和(y1,y2,…yn)。

把它们合并成一个线形表C,使得:

当m>=n时,C=x1,y1,x2,y2,…xn,yn,…,xm

当n>m时,C=y1,x1,y2,x2,…ym,xm,…,yn

输出线形表C。

然后将已合并的链表进行直接插入排序,输出链表D。

2.1.1链表

线性表的链式存储结构简称为链表。

链表的特点是用一组任意的存储单元存储线性表的数据元素(这组存储单元是可以连续的,也可以使不连续的)。

因此,为了表示每个数据元素ai与其直接后继元素ai+1之间的逻辑关系,对数据ai除了储存其本身的信息之外,还要存储一个指示其直接后继的信息。

这两部分组成数据元素ai的存储影像,成为结点。

它包括两个域:

其储存元素信息的域称为数据域;存储直接后继位置的域成为指针域。

链表的每个结点只包含一个指针域。

用线性链表表示线性表的时,数据元素之间的逻辑关系是有结点中的指针指示的。

通常我们把链表话画成用箭头相连接的结点的序列,节点之间的箭头表示指针。

在c语言中,链表用结构指针来描述。

//————————线性表的单链表存储结构————————

typedefstructLnode{

ElemTypedata

StructLnode*next;

}Lnode,*LinkLIst;

后皆可。

这就是两个单链表的简单合并操作。

合并的算法如下,

VoidMergeList_L(LinkList&La,LinkList&b,LinkList&Lc){

//已知单链线性表La和Lb的元素按值非递减排列。

//归并}La和Lb得到新的单链表线性表Lc,Lc的元素也按值非递减排列。

pa=La—〉next;pa=Lb—〉next;

Lc=pc+La;

While(pa&&pb){

If(pc—>data<=pb—>data;)

pb—>next=pb;pc=pa;pa—>next;}

elsepc—>next=pb;pc=pb;pb—>next;}}

pc—>next=pa?

pa:

pb;

free(Lb)

在链表的合并中常用的操作是插入,假设要在线性表的两个元素之间出入一个新的元素x。

为了插入元素x,首先要生成一个数据域为x的结点,然后插入数据元素x。

根据插入操作的逻辑定义,还要修改结点a中的指针域,令其指向结点x,而结点x中的指针域应指向结点b,从而实现3个元素a,b和x之间的逻辑变化。

上述指针修改语句描述为,

s—>next=p—>next;p—>next=s;

单链表中插入结点时的指针变化情况如图1

p

 

s

图1单链表中插入结点时的指针变化情况

反之,在线性表中删除元素b时,为了在单链表中实现元素a、b和c之间逻辑关系的变化,仅需改动节点a中的指针域即可。

假设p为指向节点a的指针,则修改指针的语句为

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

删除节点时指针变化情况如图4所示

图2单链表删除节点时指针变化情况

在已知单链表中元素插入或插入或删除的确切位置的情况下,在单链表中插入或删除一个结点时,仅需修改指针而不需要移动元素。

删除元素代码如下:

StatusListInsert_L(LinkList&L,intI,ElemTypee){

//在带头结点的单链表线性表L中,删除第i个元素,并由e返回其值

p=L;j=0;

while(p&&j

p=p—>next;+j:

}

If(!

(p—>next)||j>i-1)returnERRoR;//删除位置不合理

q=p—>next;p—>next=q—>next;//删除并释放结点

e=q—>data;free(q);//释放函数

retrunOK;

}//ListDelete_L

2.1.3链表的排序

排序是计算机程序设计中的一个重要操作,他的功能是将一个数据元素(或记录)的任意序列,重新排列成一个按关键字有序的序列。

由于待排序的记录数量不同,使得排序过程中的存储器不同,可将排序方法分为两大类;一类是内部排序,指的是待排序记录存放在计算机随机存储器中进行的排序过程。

另一类是外部排序,指的是待排序记录的数量很大,,以至内存一次不能容纳全部记录,在排序过程中尚需对外存进行访问的排序过程。

在链表的操作中常用到两个标准函数malloc和free。

通常,在设有“指针”数据类型的高级语言中均存在与其相应的过程与函数。

假设p和q是LinkList型的结点,则执行p=(LinkList)malloc(sizeof(LNode))的作用是由系统生成一个Lnode型的结点,同时将该结点的起始位置赋给指针变量p;反之执行free(q)的作用是由系统回收一个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(&p—>data);

p—>next=L—>next;L—>next=p;

}

}//CrateList_L

2.1.2链表的合并

链表的合并是将两个链表合并成一个链表。

假设两个链表LA和LB头指针为La,Lb,要归并La和Lb得到链表Lc,pa和pb分别指向La和Lb表中当前待比较插入的结点,

而pc指向Lc当前最后一个结点,若pa—>datadata,则将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.2算法设计

程序的基本功能,首先建立建立单链表,向单链表中输入元素,然后输出单链表,将两个单链表进行合并。

先建立两个升序链表,假设分别为La=(x1,x2,…xn),Lb=(y1,y2,…yn),它们的长度分别为a,b。

若a>b,则把这两个链表合并后,要求新Lc=x1,y1,x2,y2,…xn,yn…,。

若a

本程序的主要特点是运用结构体和链表,其中在建立链表的时候通过手动输入链表节点元素,再由定义的函数完成链表的归并,最后输出两个链表的归并结果。

如果两个链表均为空表,则显示NULLLIST。

数据的主要流程,在主函数中创建链表A和链表B。

首先输入A链表的长度,然后主函数调用creat函数,creat函数中有malloc函数创建头结点,再由for循环控制所创建链表的长度,向已建好的链表中添加数据元素,当链表长度达到所规定的长度时则跳出函数,将链表输出,程序继续向下执行,提示输入链表B的长度,方法与创建练表A相同。

在创建链表结束后,由主函数调用hebing函数,对两个链表进行归并。

本程序是完成对连个链表的交叉合并的实现,首先判断链表A和链表B的长度的大小,设链表A的长度为a,链表B的长度为b,若a>b,则新表Lc=x1,y1,x2,y2,…xn,yn…;若a

设置两个指针分别指向A和B,并对A和B节点进行比较,若A结点的数据元素大于B结点的数据元素,则将A结点存入到C链表中,A链表指针后移,B链表指针不动,继续下一次比较,当A链表或B链表为空时,则将剩余的数据元素依次存入C链表后。

若输入的两个链表均为空链表,则显示链表为空。

程序流程图如图3所示:

图3设计程序流程图

 

图4调用函数hebing流程图

调用函数print的是用来输出链表的函数,用以循环实现对链表的输出,流程图如图5所示

 

图5调用函数print流程图

(1)创建链表函数的设计

创建链表,首先由主函数输入要创建的链表长度n,在由主函数将参数传递到创建链表函数creat,由For循环控制表节点的创建,由malloc函数开辟新的结点空间,创建链表结束后,由print函数将链表元素输出。

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

当前位置:首页 > 高中教育 > 小学教育

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

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