数据结构课程设计排序算法演示系统.docx
《数据结构课程设计排序算法演示系统.docx》由会员分享,可在线阅读,更多相关《数据结构课程设计排序算法演示系统.docx(48页珍藏版)》请在冰点文库上搜索。
数据结构课程设计排序算法演示系统
各专业全套优秀毕业设计图纸
计算机学院
数据结构课程设计
题目:
数据结构排序算法演示系统
班级:
姓名:
学号:
同组人姓名:
起迄日期:
课程设计地点:
指导教师:
评阅意见:
成绩评定:
评阅人:
日期:
完成日期:
2014年12月
一.设计目的
随着计算机技术的发展,各种排序算法不断的被提出。
排序算法在计算机科学中有非常重要的意义,且应用很广泛。
在以后的发展中排序对我们的学习和生活的影响会逐渐增大,很有必要学习排序知识。
此次课程设计一方面使自己掌握排序的知识,另一方面锻炼一下团队合作开发系统的能力。
二.设计内容和要求
功能要求:
(1)界面友好,易与操作。
可采用菜单或其它人机对话方式进行选择。
(2)实现各种内部排序。
包括直接插入排序,冒泡排序,直接选择排序,希尔排序,快速排序,堆排序,归并排序。
(3)待排序的元素的关键字为整数或(字符)。
可用随机数据和用户输入数据作测试比较。
比较的指标为有关键字参加的比较次数和关键字的移动次数(关键字交换以3次计)。
(1)演示程序以人机对话的形式进行。
每次测试完毕显示各种比较指标值的列表,以便比较各种排序的优劣。
三.本设计所采用的数据结构
typedefstruct
{
intkey;
}RecType;
4.
功能模块详细设计
4.1详细设计思想
主函数:
#include
#include
#include
#defineL8//排序元素个数
#defineFALSE0
#defineTRUE1
typedefstruct
{
intkey;
}RecType;
RecTypeR[L];
intnum;
intsum;
intsun;//定义排序趟数的全局变量
//系统主界面
//主函数
intmain()
{
RecTypeS[100];
inti,k;
charch1,ch2,q;
printf("\n\t\t***********排序算法演示系统************\n\n\t\t请输入%d个待排序的数据:
\n",L);
for(i=1;i<=L;i++)
{
printf("\t\t请输入第%dth数据:
",i);
scanf("%d",&S[i].key);
getchar();
}
ch1='y';
while(ch1=='y')
{
printf("\n\t\t菜单\n");
printf("\n\t\t***********************************************\n");
printf("\n\t\t*1--------更新排序数据*2--------直接插入排序\n");
printf("\n\t\t*3--------希尔排序*4--------冒泡排序\n");
printf("\n\t\t*5--------快速排序*6--------直接选择排序\n");
printf("\n\t\t*7--------堆排序*8--------归并排序\n");
printf("\n\t\t**********0--------退出************\n");
printf("\n\t\t********************************************\n");
printf("\n\t\t请选择:
");
scanf("%c",&ch2);
getchar();
for(i=1;i<=L;i++)
{
R[i].key=S[i].key;
}
switch(ch2)
{
case'1':
printf("\n\t\t请输入%d个待排序数据\n\t\t",L);
for(i=1;i<=L;i++)
{
scanf("%d",&S[i].key);
getchar();
printf("\t\t");
}
printf("\n\t\t数据输入完毕!
");
break;
case'2':
Insertsort();
break;
case'3':
Shellsort();
break;
case'4':
Bubblesort();
break;
case'5':
printf("\n\t\t原始数据为(按回车键开始排序):
\n\t\t");
for(k=1;k<=L;k++)
{
printf("%5d",R[k].key);
}
getchar();
printf("\n");
num=0;sun=0;sum=0;
Quicksort(1,L);
printf("\n\t\t排序最终结果是:
\n\t\t");
for(k=1;k<=L;k++)
{
printf("%5d",R[k].key);
}
printf("\n\t\t比较次数是:
%d\n\t\t",sum);
printf("\n\t\t交换次数是:
%d\n\t\t",sun);
break;
case'6':
Selectsort();
break;
case'7':
Heap();
break;
case'8':
Mergesort();
break;
case'0':
ch1='n';
break;
default:
system("cls");//清屏
printf("\n\t\t对不起,您输入有误,请重新输入!
\n");
break;
}
if(ch2!
='0')
{
if(ch2=='2'||ch2=='3'||ch2=='4'||ch2=='5'||ch2=='6'||ch2=='7'||ch2=='8')
{
printf("\n\n\t\t排序完毕!
");
printf("\n\t\t按回车键继续!
");
q=getchar();
if(q!
='\n')
{
getchar();
ch1='n';
}
}
}
}
return1;
}
图一主界面
4.1.1冒泡排序
核心思想
依次比较相邻的两个数,将小数放在前面,大数放在后面,第一轮比较后,最大的数便被放到了最后;第二轮操作前n-1个数据(假设有n个数据),依然是依次比较相邻的两个数,将小数放在前面,大数放在后面,倒数第二个数便是第二大的数;同理第i轮操作前n-i+1的数据(假设i取值是从1开始的),则n-i+i位置上的数据为第i大的数据。
一共有n-1轮,第i轮比较中共比较n-i次比较。
核心代码
voidBubblesort()
{
inti,j,k,x=0,y=0,m=0;
intexchange=TRUE;//标志位exchange初始化为TRUE1
printf("\n\t\t原始数据为(按回车键开始排序):
\n\t\t");
for(k=1;k<=L;k++)
{
printf("%5d",R[k].key);
}
getchar();
printf("\n");
for(i=1;i{
exchange=FALSE;
for(j=1;j<=L+1-i;j++)//内层相邻记录的交换与比较
{m++;//比较次数++
if(R[j].key{
R[0].key=R[j].key;
R[j].key=R[j-1].key;
R[j-1].key=R[0].key;
exchange=TRUE;
y++;//移动次数++
}
}
m--;//比较次数
if(exchange)//输出语句
{
printf("\t\t第%d趟冒泡排序的结果为:
\n\t\t",i);
for(k=1;k<=L;k++)
{printf("%5d",R[k].key);
}
getchar();
printf("\n");
}
}
printf("\n\t\t比较次数是:
\t\t");
printf("%d",m);
printf("\n\t\t移动次数是:
\t\t");
printf("%d",y);
printf("\n\t\t排序最终结果是:
\n\t\t");
for(i=1;i<=L;i++)
{printf("%5d",R[i].key);
}
}
图二直接插入排序
4.1.2快速排序
核心思想
首先检查数据列表中的数据数,如果小于两个,则直接退出程序。
如果有超过两个以上的数据,就选择一个分割点将数据分成两个部分,小于分割点的数据放在一组,其余的放在另一组,然后分别对两组数据排序。
通常分割点的数据是随机选取的。
这样无论你的数据是否已被排列过,你所分割成的两个字列表的大小是差不多的。
而只要两个子列表的大小差不多
核心代码
//递归算法实现
voidQuicksort(intlow,inthigh)
{
inti=low,j=high,k;
R[0].key=R[low].key;
while(i{
while(i{j--;
sum++;
}
if(i{R[i].key=R[j].key;//交换
i++;
sun++;
}
while(i{i++;
sum++;
}
if(i{
R[j].key=R[i].key;//交换
j--;
sun++;
}
}
R[i].key=R[0].key;
num++;
//输出语句包括排序的结果及次数
printf("\t\t第%d趟快速排序的结果为:
\n\t\t",num);
for(k=1;k<=L;k++)
{printf("%5d",R[k].key);
}
getchar();
printf("\n");
if(lowif(j+1}
图三快速排序
4.1.3直接插入排序
核心思想
经过i-1遍处理后,L[1..i-1]己排好序。
第i遍处理仅将L[i]插入L[1..i-1]的适当位置,使得L[1..i]又是排好序的序列。
要达到这个目的,我们可以用顺序比较的方法。
首先比较L[i]和L[i-1],如果L[i-1]≤L[i],则L[1..i]已排好序,第i遍处理就结束了;否则交换L[i]与L[i-1]的位置,继续比较L[i-1]和L[i-2],直到找到某一个位置j(1≤j≤i-1),使得L[j]≤L[j+1]时为止
核心代码
voidInsertsort()
{
inti,j,k,m=0,x=0;//初始化比较次数变量m,移动次数变量x
printf("\n\t\t原始数据为:
(按回车键开始排序)\n\t\t");
for(k=1;k<=L;k++)
{
printf("%5d",R[k].key);
}
getchar();
printf("\n");
//主要运行部分
for(i=2;i<=L;i++)
{
if(R[i].key{
R[0]=R[i];
j=i-1;
while(R[0].key{
R[j+1]=R[j];
j--;
}
R[j+1]=R[0];
x++;
}
m++;
//输出语句包括排序的结果及次数
printf("\t\t第%d趟直接插入排序的结果为:
\n\t\t",m);
for(k=1;k<=L;k++)
{printf("%5d",R[k].key);
}
getchar();
printf("\n");
}
printf("\n");
printf("\n\t\t比较次数是:
\t\t");
printf("%d",m);
printf("\n\t\t移动次数是:
\t\t");
printf("%d",x);
printf("\n\t\t排序最终结果是:
\n\t\t");
for(i=1;i<=L;i++)
{printf("%5d",R[i].key);
}
}
图四直接插入排序
4.1.4希尔排序
核心思想
先取一个小于n的整数d1作为第一个增量,把文件的全部记录分成d1个组。
所有距离为dl的倍数的记录放在同一个组中。
先在各组内进行直接插入排序;然后,取第二个增量d2核心代码
voidShellsort()
{
inti,j,gap,x,k,y=0,m=0;//初始化比较次数变量m,移动次数变量y
printf("\n\t\t原始数据为:
(按回车键开始排序)\n\t\t");
for(k=1;k<=L;k++)
{
printf("%5d",R[k].key);
}
getchar();
printf("\n");
//函数主要部分
gap=L/2;
while(gap>0)
{
for(i=gap+1;i<=L;i++)
{
j=i-gap;
while(j>0)
{
if(R[j].key>R[j+gap].key)
{
x=R[j].key;//交换语句
R[j].key=R[j+gap].key;
R[j+gap].key=x;
j=j-gap;
y++;//移动次数++
}
else
{
j=0;
}
}
}
gap=gap/2;
m++;//比较次数++
//输出语句包括排序的结果及次数
printf("\t\t第%d趟希尔排序的结果为:
\n\t\t",m);
for(k=1;k<=L;k++)
{
printf("%5d",R[k].key);
}
getchar();
printf("\n");
}
printf("\n\t\t比较次数是:
\t\t");
printf("%d",m);
printf("\n\t\t移动次数是:
\t\t");
printf("%d",y);
printf("\n\t\t排序最终结果是:
\n\t\t");
for(i=1;i<=L;i++)
{
printf("%5d",R[i].key);
}
printf("\n");
}
图五希尔排序
4.1.5直接选择排序
核心思想
第一次从R[0]~R[n-1]中选取最小值,与R[0]交换,第二次从R{1}~R[n-1]中选取最小值,与R[2]交换,....,第i次从R[i-1]~R[n-1]中选取最小值,与R[i-1]交换,.....,第n-1次从R[n-2]~R[n-1]中选取最小值,与R[n-2]交换,总共通过n-1次,得到一个按排序码从小到大排列的有序序列.
核心代码
voidSelectsort()
{
inti,j,k,h,x=0,y=0;
printf("\n\t\t原始数据为(按回车键开始排序):
\n\t\t");
for(k=1;k<=L;k++)
{
printf("%5d",R[k].key);
}
getchar();
printf("\n");
for(i=1;i{
h=i;
for(j=i+1;j<=L;j++)
{x++;//比较次数
if(R[j].key{
h=j;//确定最小值
}
}
if(h!
=i)
{
R[0].key=R[i].key;
R[i].key=R[h].key;
R[h].key=R[0].key;
y++;//移动次数
}
printf("\t\t第%d趟选择排序的结果为:
\n\t\t",i);
for(k=1;k<=L;k++)
printf("%5d",R[k].key);
getchar();
printf("\n");
}
//输出语句包括排序的结果及次数
printf("\n\t\t比较次数:
%d",x);
printf("\n\t\t移动次数:
%d",y);
printf("\n\t\t排序最终结果是:
\n\t\t");
for(i=1;i<=L;i++)
printf("%5d",R[i].key);
printf("\n");
}
图六选择排序
4.1.6堆排序
核心思想
堆排序是一树形选择排序,在排序过程中,将R[1..N]看成是一颗完全二叉树的顺序存储结构,利用完全二叉树中双亲结点和孩子结点之间的内在关系来选择最小的元素。
将原始记录序列建成一个堆,成为初始堆,并输出堆顶元素;调整剩余的记录序列,使之成为一个新堆,再输出堆顶元素;如此反复进行,当堆中只有一个元素时,整个序列的排序结束,输出的序列便是原始序列的非递减有序序列。
在堆排序的过程中,主要负责两方面的工作:
一是如何将原始记录序列构造成一个堆,即建立初始堆;二是输出堆顶元素后,如何将剩余记录整理成一个新堆。
核心代码
voidCreateHeap(introot,intindex,int*x,int*y)
{
intj,temp,finish;
j=2*root;//j指向左孩子
temp=R[root].key;
finish=0;
while(j<=index&&finish==0)
{
if(j{
if(R[j].key{
j++;
}
}//指向较大的孩子
if(temp>=R[j].key)
{
finish=1;
}
else
{
R[j/2].key=R[j].key;
(*y)++;
j=j*2;
}
*x=*x+2;
}
R[j/2].key=temp;
(*y)++;
}
//堆排序
voidHeapsort()
{
inti,j,temp,k,x=0,y=0;
for(i=(L/2);i>=1;i--)//建立初始堆
{
CreateHeap(i,L,&x,&y);
}
x=0;
y=0;
for(i=L-1,k=1;i>=1;i--,k++)//将堆中根节点和最后一个节点交换
{
temp=R[i+1].key;
R[i+1].key=R[1].key;
R[1].key=temp;
CreateHeap(1,i,&x,&y);
printf("\t\t第%d趟堆排序的结果为:
\n\t\t",k);
for(j=1;j<=L;j++)
{
printf("%5d",R[j].key);
}
getchar();
printf("\n");
}
printf("\n\t\t比较次数是:
%d\t\t",x);
printf("\n\t\t移动次数是:
%d\t\t",y);
}
voidHeap()
{
inti;
printf("\n\t\t原始数据为(按回车键开始排序):
\n\t\t");
for(i=1;i<=L;i++)
{
printf("%5d",R[i].key);
}
getchar();
printf("\n");
Heapsort();
printf("\n\t\t排序最终结果是:
\n\t\t");
for(i=1;i<=L;i++)
{
printf("%5d",R[i].key);
}
printf("\n");
}
voidMerge(intlow,intmm,inthigh,int*x,int*y)//两个有序序列的合并
{
inti=low,j=mm+1,p=0;
RecType*R1;//i对第一个开始到结尾,j从第二个开始到结尾
R1=newRecType[high-low+1];
if(!
R1)
{
printf("内存不足!
");
}
while(i<=mm&&j<=high)//两序列从起始位置开始将小的元素放入到R1中
{
R1[p++]=(R[i].key<=R[j].key)?
R[i++]:
R[j++];
(*x)++;
(*y)++;
}
while(i<=mm)//第二段结束,剩余放入R1中
{
R1[p++]=R[i++];
(*y)++;
}
while(j<=high)//第二段剩余,剩余放入R1中
{
R1[p++]=R[j++];
(*y)++;
}
for(p=0,i=low;i<=high;p++,i++)//剩余元素放入R1中,赋予R
{
R[i]=R1[p];
(*y)++;
}
}
图七堆排序
4.1.7归并排序
核心思想
将有n个记录的原始序列看作n个有序子序列,每个子序列的长度为1,然后从第一个子序列开始,把相邻的子