C=23,30,56,41,78,15,23,12,12,56,33,80,79,90,55
排序结果:
D=12,12,15,23,23,30,33,41,55,56,56,78,79,80,90
(2)A表的数据元素个数m=9,B表的数据元素个数n=5,此时m>n
分析合并结果:
当m>=n时,应该先插入A表中的数据元素,在偶数位插入A表中的数据元素,在奇数位插入B表中的数据元素,最后插入A表中剩余的数据元素。
C=30,23,41,56,15,78,12,23,56,12,80,23,12,34
排序结果:
D=12,12,12,15,23,23,23,30,34,41,56,56,78,80
三、实验设计分析及实现步骤:
3.1分析问题,给出数学模型,设计相应的数据结构。
1)分析问题特点,用链表形式描述问题数学模型。
2)选择体现问题本身特点的链表形式逻辑结构。
3)依据逻辑结构和问题特点,按照要求处理要求的链表问题。
3.2算法设计
1)确定所需模块:
对于复杂的程序设计,要充分利用模块化程序设计方法和面向对象思想,自顶向下,逐步细化。
2)各子模块功能描述:
给出主要模块的算法描述,用流程图或伪代码表示。
3)模块之间的调用关系:
给出算法各模块之间的关系图示。
3.3上机实现程序
为提高工作效率,充分利用上机调试时间,在上机之前列出程序清单。
3.4算法分析及优化
经过上机调试,源程序运行正确,并且实现算法要求的功能,解决课程设计题目中给出的问题后,分析算法的时间复杂度和空间复杂度,如有可能对程序进行优化改进。
四、算法思想:
con(SLNode*Ahead,SLNode*Bhead)函数和InsertSort(SLNode*head)函数是实现问题两个要求的两个主要函数。
其中con()函数实现两个链表的合并,其算法思想是:
按照链表个数小的链表元素个数进行控制循环,使用while循环直到指向元素为空停止,在每一步循环中将元素插入元素个数多的链表中。
InsertSort()函数功能是实现链表的直接插入法排序,其算法思想是:
首先使用一个while循环控制排序次数,直到指向为空停止;然后,使用一个for循环实现每次排序过程中元素比较的次数,而且,在for循环中使用while循环判断各个元素之间的大小,进而实现各个数据之间大小的排序
五、模块划分:
(1)数据模块
参考使用课本上的具有头结点的链表抽象数据类型SLNode,该抽象数据类型中包含一个DataType类型的数据和一个指针,在开始用时,DataType定义为整型变量,指针用来指向下一个元素。
对应的使用链表抽象数据类型SLNode基本操作的函数有:
初始化操作函数ListInitiate()和插入一个结点操作函数ListInsert()。
(2)录入数据模块
voidinputdata(SLNode*head,intlength),其功能是为链表录入数据,其中length为链表的长度,head指向链表的头结点。
这样就实现了使用给定的数据对链表进行初始化。
可以实现各种链表的录入
(3)输出数据模块
voidoutputdata(SLNode*head),其功能为是输出head指向的链表中的各项元素,从而验证操作是否成功
(4)合并链表模块
SLNodecon(SLNode*Ahead,SLNode*Bhead),其功能是按照题目要求实现两个链表的合并,其中Ahead指向的链表的长度大于Bhead指向的链表
(5)排序模块
voidInsertSort(SLNode*head),此函数功能是对head指向的链表使用直接插入法对链表进行排序
(6)主函数模块
voidmain(),函数中调用了各个模块的函数,从而实现了题目合并排序的要求
(7)模块之间的关系图示:
图5-7模块关系图
六、程序流程图:
图6-1程序流程图
七、程序设计:
#include
#include
intm,n;
intcount=1;
structNode
{
intdata;
structNode*next;
}*A,*B,*C,*D;
//打印AList列表
voidprintList(structNode*AList)
{
structNode*post;
post=AList->next;
switch(count)
{
case1:
printf("\nListA:
");
break;
case2:
printf("\nListB:
");
break;
case3:
printf("\nListC:
");
break;
case4:
printf("\nListD:
");
break;
default:
printf("\nList:
");
break;
}
while(post)
{
printf("%d",post->data);
post=post->next;
}
count++;
}
//初始化表头,列表含有表头
voidinit()
{
A=(structNode*)malloc(sizeof(structNode));
A->data=0;
A->next=0;
B=(structNode*)malloc(sizeof(structNode));
B->data=0;
B->next=0;
C=(structNode*)malloc(sizeof(structNode));
C->data=0;
C->next=0;
D=(structNode*)malloc(sizeof(structNode));
D->data=0;
D->next=0;
}
//读取列表A和B
voidReadListAB()
{
inti;
structNode*post;
structNode*pre;
//输入列表长度
printf("m=");scanf("%d",&m);
printf("n=");scanf("%d",&n);
//读取列表A
pre=A;
for(i=1;i<=m;i++)
{
post=(structNode*)malloc(sizeof(structNode));
printf("A%d=",i);
scanf("%d",&post->data);
post->next=0;
pre->next=post;
pre=post;
}
//读取列表B
pre=B;
for(i=1;i<=n;i++)
{
post=(structNode*)malloc(sizeof(structNode));
printf("B%d=",i);
scanf("%d",&post->data);
post->next=0;
pre->next=post;
pre=post;
}
}
//合并列表A和B
voidMergeABToC()
{
inti;
structNode*pre,*postA,*postB,*postC;
pre=C;
postA=A->next;
postB=B->next;
if(m>=n)
{
for(i=1;i<=n;i++)
{
postC=(structNode*)malloc(sizeof(structNode));
postC->data=postA->data;
postC->next=0;
pre->next=postC;
pre=postC;
postC=(structNode*)malloc(sizeof(structNode));
postC->data=postB->data;
postC->next=0;
pre->next=postC;
pre=postC;
postA=postA->next;
postB=postB->next;
}
for(i=n+1;i<=m;i++)
{
postC=(structNode*)malloc(sizeof(structNode));
postC->data=postA->data;
postC->next=0;
pre->next=postC;
pre=postC;
postA=postA->next;
}
}
else
{
for(i=1;i<=m;i++)
{
postC=(structNode*)malloc(sizeof(structNode));
postC->data=postB->data;
postC->next=0;
pre->next=postC;
pre=postC;
postC=(structNode*)malloc(sizeof(structNode));
postC->data=postA->data;
postC->next=0;
pre->next=postC;
pre=postC;
postA=postA->next;
postB=postB->next;
}
for(i=m+1;i<=n;i++)
{
postC=(structNode*)malloc(sizeof(structNode));
postC->data=postB->data;
postC->next=0;
pre->next=postC;
pre=postC;
postB=postB->next;
}
}
}
//使用直接插入法,将C排序输出D
voidSortCToD()
{
structNode*pre,*postC,*postD,*lopD;
intlen;
//表示总的长度
len=m+n;
pre=D;//指向D有序数列的尾指针
postC=C->next;//指向C列表
//列表D第一个节点加入
postD=(structNode*)malloc(sizeof(structNode));
postD->data=postC->data;
postD->next=0;
pre->next=postD;
pre=postD;
postC=postC->next;
while(postC)
{
//pre为指向插入的前一个节点,lopD是指向插入的后一个节点
pre=D;
lopD=D->next;
while(lopD)
{
if(lopD->data>postC->data)
break;
else
{
pre=lopD;
lopD=lopD->next;
}
}
//将节点插入
postD=(structNode*)malloc(sizeof(structNode));
postD->data=postC->data;
postD->next=0;
pre->next=postD;
postD->next=lopD;
//循环条件
postC=postC->next;
}
}
voidmain(void)
{
init();
ReadListAB();
MergeABToC();
SortCToD();
printList(A);
printList(B);
printList(C);
printList(D);
}
八、测试结果:
1带入测试数据
(1)结果:
图8-1测试结果
测试结果:
单链表D=12,12,15,23,23,30,33,41,55,56,56,78,79,80,90
2带入测试数据
(2)结果:
图8-2测试结果
测试结果:
单链表D=12,12,12,15,23,23,23,30,34,41,56,56,78,80
3测试结论:
通过观察程序的连接、编译、运行得到的运行结果,可以得知程序运行结果和理论
分析吻合,说明通过单链表的操作可以完成两个单链表的合并,并能够对单链表合并后的数据元素进行排序。
九、实验总结:
1.程序改进:
单链表是数据结构里面典型的线性表,此程序只是运行了两个简单的链表操作,还不能运行比较复杂的链表操作,还需要改进.
2.心得体会:
在本次的课程设计中,我学到了很多知识,由于自身的能力有限,很多程序的编写都还不是很熟练,还需要通过参考书查资料及其他同学的帮助才能完成,通过程序的编写和运行,发现了自己很多的不足,在自己弱势方面有了更清醒的认识,虽然课程设计的程序还是有一点粗糙,课程设计的实验报告写的还不够细致,但是在此次课程设计中,我得到了锻炼,自己的能力也得到了提高,达到课程设计锻炼我们综合能力的目标。
参考文献资料
[1].朱战立.编著.数据结构——使用C语言.西安交通大学出版社,2004
[2].苏小红,孙志岗等编著.C语言大学实用教程(第2版).电子工业出版社,2008
[3].梁肇新编著.编程高手箴言.电子工业出版社,2003