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

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

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

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

数据结构课程设计两个链表合并星.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。

对合并的链表C进行直接插入排序,输出链表D。

此次课程设计实验的数据位

①A表(30,41,15,12,56,80)

B表(23,56,78,23,12,33,79,90,55)

②A表(30,41,15,12,56,80,23,12,34)

B表(23,56,78,23,12)

2.1.1链表

链表是一种物理存储单元上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的。

链表由一系列结点(链表中每一个元素称为结点)组成,结点可以在运行时动态生成。

每个结点包括两个部分:

一个是存储数据元素的数据域,另一个是存储下一个结点地址的指针域。

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

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

相比于线性表顺序结构,链表比较方便插入和删除操作。

(1)线性表的单链表存储结构

ypedefstructNode{

ElemTypedata;

structNode*next;

}Node;

typedefstructNode*Linklist;

(2)实现两个链表的简单合并算法如下:

VoidMergelist_L(Linklist&La,Linklist&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&&jnext;++j;}//寻找第i-1个结点

if(!

P||j>i-1)returnERROR;//i小于1或者大于表长+1

s=(LinkList)malloc(sizeof(LNode));//生成新结点

s->date=e;s->next=p->next;//插入L中

p->next=s;

returnOK;

}//ListInsert_L

(4)在链表中删除元素

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

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

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

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

图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.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.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(&p—>data);

p—>next=L—>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

本程序经过调试后运行以后有中文提示输入链表a的长度,然后手动输入链表中的元素,回车键后提示输入链表b的长度,再输入链表b的元素,回车键后本程序将按照设计需求自动进行两个链表的合并,最后进行新链表c的插入排序。

输出排好序的新链表d的相关信息。

程序的流程图如下所示:

建立链表a

建立链表b

合并ab链表

得到c链表

 

判断mn的大小

 

对c链表进行插入排序

 

图3程序流程图

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

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

创建链表函数的实现代码如下:

#include

#include

#include

#include

#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("%ld",&p1->number);

a--;//控制输入的个数

}

p2->next=NULL;

return(head);

}//链表创建函数结束

(2)输出链表的函数的实现

待链表输入完成后,定义单链表的头结点*p,通过运用一个循环语句,将链表内的元素一一输出在执行程序界面上。

voidprint(structNode*head)//输出函数

{

structNode*p;

p=head;

printf("数字:

\n");

if(head!

=NULL)

do//循环实现输出

{

printf("%ld",p->number);

printf("");

p=p->next;

}while(p!

=NULL);

printf("\n");

}

(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->next;

pos->next=p2;

pos=p2;

p2=p2->next;

pos->next=p1;

pos=p1;

}

returnhead;

}

(4)对合并好的链表进行插入排序

voidInsertSort(structNode*p,intm)//排序函数

{

inti,j,t;

structNode*k;

k=p;

for(i=0;i

for(j=0;j

if(p->number>(p->next)->number){

t=p->number;

p->number=(p->next)->number;

(p->next)->number=t;

}

p=p->next;

}

p=k;

}

}

(5)主函数的定义

intmain()//main函数

{

structNode*p1,*p2;

inta;

intb;

inth;

printf("请输入第一个链表:

\n");

printf("\n输入链表的长度a:

\n");

scanf("%d",&a);

printf("请输入链表数据:

");

p1=create(a);

printf("\n你刚才输入的第一个链表信息:

\n");

print(p1);

printf("\n请输入第二个链表:

\n");

printf("\n输入链表的长度b:

\n");

scanf("%d",&b);

printf("请输入链表数据:

");

p2=create(b);

printf("\n你刚才输入的第二个链表的信息:

\n");

print(p2);

p1=inter_link(p1,a,p2,b);

h=a+b;

printf("\n合并后的链表\n:

");

print(p1);

InsertSort(p1,h);

printf("\n排序后的链表:

\n");

print(p1);

return0;

}

3运行结果与分析

(1)打开软件,输入代码,运行程序,然后中文提示输入链表a的长度,回车之后提示输入链表中的数据元素。

录入第一组测试数据完成以后显示链表a的信息,这里m

如下图所示:

图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

 

附录:

源程序

#include

#include

#include

#include

#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("%ld",&p1->number);

a--;//控制输入的个数

}

p2->next=NULL;

return(head);

}//链表创建函数结束

voidprint(structNode*head)//输出函数

{

structNode*p;

p=head;

printf("数字:

\n");

if(head!

=NULL)

do//循环实现输出

{

printf("%ld",p->number);

printf("");

p=p->next;

}while(p!

=NULL);

printf("\n");

}

//链表的交叉合并算法

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->next;

pos->next=p2;

pos=p2;

p2=p2->next;

pos->next=p1;

pos=p1;

}

returnhead;

}

//对合并好的链表进行排序

voidInsertSort(structNode*p,intm)//排序函数

{

inti,j,t;

structNode*k;

k=p;

for(i=0;i

for(j=0;j

if

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

当前位置:首页 > PPT模板 > 自然景观

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

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