数据结构课程设计.docx
- 文档编号:29653626
- 上传时间:2023-07-25
- 格式:DOCX
- 页数:27
- 大小:114.18KB
数据结构课程设计.docx
《数据结构课程设计.docx》由会员分享,可在线阅读,更多相关《数据结构课程设计.docx(27页珍藏版)》请在冰豆网上搜索。
数据结构课程设计
数据结构
课程设计报告
课程设计题目:
各种内部排序性能比较
学生姓名:
专业:
班级:
学号:
指导教师:
年月日
目录
试验分析
需求分析说明3
总体设计3
详细设计4
试验内容4
代码6
程序测试22
总结24
1、需求分析说明:
排序是数据处理中经常遇到的一种重要操作。
然而排序的算法有很多,各有其优缺点和使用场合。
本程序的设计的主要目的是通过比较各种内部排序(包括:
选择法、冒泡法、直接插入法、快速法、两路合并法)的时间复杂度,即元素比较次数和移动次数,来分析各种算法优缺点和适合排列何种序列。
达到在实际应用中选择合适的方法消耗最短的时间完成排序。
2、总体设计:
本程序主要包括六个功能:
1、选择法排序2、冒泡法排序3、直接插入法排序
4、快速法排序5、二分法排序6、希尔排序
7、堆排序8、统计各种排序的时间复杂度
因此在类Sort定义中主要包括这七个函数。
以及需要用到的变量。
主函数中包括产生待排序序列、提示用户选择排序方法或比较各种排序的时
间复杂度。
并使用while循环使用户可以连续选择想要程序做的操作,直到选择退出程序为止。
选择法排序select
→
冒泡法排序bubble
→
Main()
插入法排序straight
→
Qsort()
快速法排序quick
→→
Merge()
二分法排序binary
→→
希尔排序Shell
→
堆排序Heap
SUB_MENUE():
输出各菜单→产生随机数序列→提示用户选择菜单
→若选择1,则重新输入数据进行排序,并再次选择排序方法。
→若选择2,则调用BIS_INT()函数进行二分法排序,并输出各趟排序结果
→若选择3,则调用STINSORT()函数进行直接排序,并输出各趟排序结果
→若选择4,则调用SHELL()函数进行希尔排序,并输出各趟排序结果
→若选择5,则调用QUICK()函数进行快速法排序,并输出各趟排序结果
→若选择6,则调用SELECT()函数进行选择排序,并输出各趟排序结果
→若选择7,则调用BUBBLE()函数进行冒泡法排序,并输出各趟排序结果
→若选择8,则调用HEAPSORT()函数进行堆排序,并输出各趟排序结果
→若选择9,则调用系统函数exit()退出循环,退出程序。
3、详细设计:
一、函数
voidSELECT()用选择法对序列排序并输出各趟排序结果;voidBUBBLE()用冒泡法对序列排序并输出各趟排序结果;voidSTINSORT()用直接插入法对序列排序并输出各趟排序结果;voidQUICK()用快速法对序列排序并输出各趟排序结果;voidHEAPSORT()用堆排序对序列排序并输出各趟排序结果;voidSHELL()用希尔法对序列排序并输出各趟排序结果;voidBIS_INT()用折半法对序列排序并输出各趟排序结果。
定义变量intCompar,intExch用于记录排序的元素比较、移动次数;
选择排序:
将初始序列(A[0]—A[n-1])作为待排序序列,第一趟在待排序序列中找出最小值元素,与该序列中第一个元素交换,下一趟排序在序列(A[1]—A[n-1])中进行,依次循环,完成排序。
该算法执行时间与元素的初始排列无关。
不论初始序列如何,该算法都必须执行n-1趟,每趟执行n-i-1次元素之间的比较。
总的比较次数为n(n-1)/2;因此,此种排序的最好、最坏和平均情况的时间复杂度都为O(n^2);需要移动元素次数为3(n-1);该排序算法经过一趟排序后,就能确定一个元素的最终位置,是不稳定的排序方法。
冒泡法排序:
此种排序是通过交换两个元素实现的。
第一趟在序列(A[0]—A[n-1])中从前往后进行两个相邻元素的比较,若后者小,则交换,比较n-1次;第一趟排序结束后,最大元素被置于最后(即沉底),下一趟排序只需在序列(A[0]—A[n-2])中进行;如果在某一趟排序中没有交换元素,说明子序列已经有序,无需再往下进行。
具体代码中通过定义变量last来确定排序的趟数。
一进入while循环,last的值就被置为0,并且只有在for循环中有元素的交换时才被修改为新值,如果某趟排序没有交换元素,则last保持为0,再由i=last决定循环结束,排序完成。
因此,冒泡排序最多执行n-1趟,第i趟比较n-1次,总共移动元素次数3n(n-1)/2,由此可看出,冒泡排序比较偏爱基本有序的序列。
直接插入法排序:
将序列中第一个元素作为一个有序序列,将剩下的n-1个元素插入该有序序列中,插入后保持该序列有序。
在将一个元素插入到有序表中时,首先将其存入临时变量temp中,然后从后往前查找插入位置,当temp小于表中元素时,就将该元素后移,继续比较移动,直到temp大于等于表中元素或者到了有序表中第一个元素时结束,这时就可将temp存入刚后移的元素的位置了。
次种排序法必须执行n-1趟,最好情况下,每趟排序只比较一次,移动两次。
最坏情况下,最多比较i次,移动i+2次。
快速排序:
此排序算法是一个递归算法。
定义函数Qsort(),实现具体排序过程。
每趟排序的结果是将当前序列分割为两个子序列:
左边的元素全部小于分割元素,右边的子序列全部大于分割元素。
再对两个子序列进行快速排序,依次循环,直到子序列为空或只有一个元素时结束。
定义变量left和right分别指向原始序列的第一个和最后一个元素,i和j为游动指针,初始化i=left;j=right+1;
设待排序序列的第一个元素为分割元素。
i从左向右扫描,找到第一个大于或等于分割元素的元素时结束,j从右往左扫描,找到第一个小于或等于分割元素的元素时结束,若i
再交换A[left]和A[j],完成一趟排序。
再调用本函数对低端序列和高端序列快速排序。
在函数quicksort()中,定义变量inth来保存原始序列的元素个数,以便后面输出每趟排序结果时使用。
再调用函数Qsort()。
二分法排序:
根据插入排序的基本思想,在找第i个记录的插入位置时,前i-1个记录已排序,将第i个记录的排序码key[i]和已排序的前i-1个的中间位置记录的排序码进行比较,如果key[i]小于中间位置记录排序码,则可以在前半部继续使用二分法查找,否则在后半部继续使用二分法查找,直到查找范围为空,即可确定key[i]的插入位置。
堆排序:
堆排序利用了大根堆(或小根堆)堆顶记录的关键字最大(或最小)这一特征,使得在当前无序区中选取最大(或最小)关键字的记录变得简单。
(1)用大根堆排序的基本思想
①先将初始文件R[1..n]建成一个大根堆,此堆为初始的无序区
②再将关键字最大的记录R[1](即堆顶)和无序区的最后一个记录R[n]交换,由此得到新的无序区R[1..n-1]和有序区R[n],且满足R[1..n-1].keys≤R[n].key
③由于交换后新的根R[1]可能违反堆性质,故应将当前无序区R[1..n-1]调整为堆。
然后再次将R[1..n-1]中关键字最大的记录R[1]和该区间的最后一个记录R[n-1]交换,由此得到新的无序区R[1..n-2]和有序区R[n-1..n],且仍满足关系R[1..n-2].keys≤R[n-1..n].keys,同样要将R[1..n-2]调整为堆。
……
直到无序区只有一个元素为止。
(2)大根堆排序算法的基本操作:
①初始化操作:
将R[1..n]构造为初始堆;
②每一趟排序的基本操作:
将当前无序区的堆顶记录R[1]和该区间的最后一个记录交换,然后将新的无序区调整为堆(亦称重建堆)。
注意:
2只需做n-1趟排序,选出较大的n-1个关键字即可以使得文件递增有序。
②用小根堆排序与利用大根堆类似,只不过其排序结果是递减有序的。
堆排序和直接选择排序刻堆排序中无序区总是在有序区之前,且有序区是在原向量的尾部由后往前逐步扩大至整个向量为止
4、代码:
#include
#include
#include
#include
#include
#include
#defineMAXSIZE100
typedefintRedType;
typedefstructSqList
{
RedTypeINT[MAXSIZE+1];
intlength;
}SqList;
SqListL;
voidTIME()//获得系统时间
{
staticchar*week[7]={"日","一","二","三","四","五","六"};
time_tt;
structtm*tp;
t=time(NULL);
tp=localtime(&t);
printf("\t ─────────────────────\n");
printf("\t\t现在是:
%d年%d月%d日",tp->tm_year+1900,tp->tm_mon+1,tp->tm_mday);
printf("%d:
%d:
%d",tp->tm_hour,tp->tm_min,tp->tm_sec,tp->tm_wday);
printf("星期%s\n",week[tp->tm_wday]);
}
voidPRINT(SqList*L)//打印排序结果
{
inti;
printf("\t\t");
for(i=1;i<=L->length;i++)
printf("%d",L->INT[i]);
printf("\n");
}
voidSTINSORT(SqList*L)//直接插入排序
{
inti,j;
for(i=2;i<=L->length;i++)
{
L->INT[0]=L->INT[i];
j=i-1;
while(L->INT[j]>L->INT[0])
{
L->INT[j+1]=L->INT[j];
j--;
}
L->INT[j+1]=L->INT[0];
}
}
//***********************************
//
//
//
voidBIS_INT(SqList*L)//折半插入排序
{
inti,j,low,high,mid;
intintCompar=0;//intCompar比较次数
intintExch=0;//intExch交换次数
for(i=2;i<=L->length;++i)
if(L->INT[i]
{
L->INT[0]=L->INT[i];//交换+1
intExch++;
high=i-1;
low=1;
while(low<=high)
{
mid=(low+high)/2;
if(L->INT[0]
high=mid-1;
else
low=mid+1;
intExch++;
}
for(j=i-1;j>=high+1;--j)
{
L->INT[j+1]=L->INT[j];//交换+1
intExch++;
}
L->INT[high+1]=L->INT[0];//交换+1
intExch++;
intCompar++;
}
printf("本次排序中一共比较了%d次,交换了%d次",intCompar,intExch);
}
voidSHELL(SqList*L)//希尔排序
{
inti,j,d;
d=L->length/2;
while(d>=1)
{
for(i=d+1;i<=L->length;i++)
{
L->INT[0]=L->INT[i];
j=i-d;
while(L->INT[j]>L->INT[0]&&j>0)
{
L->INT[j+d]=L->INT[j];
j=j-d;
}
L->INT[j+d]=L->INT[0];
}
d=d/2;
}
}
voidQUICK(SqList*L,intlow,inthigh)//快速排序
{
inti,j,temp;
i=low;
j=high;
temp=L->INT[low];
while(i { while(i j--; if(i { L->INT[i]=L->INT[j]; i++; } while(i i++; if(i { L->INT[j]=L->INT[i]; j--; } } L->INT[i]=temp; if(low QUICK(L,low,i-1); if(i QUICK(L,j+1,high); } voidSELECT(SqList*L)//选择排序 { inti,j,small; for(i=1;i<=L->length-1;i++) { small=i; for(j=i+1;j<=L->length;j++) { if(L->INT[j] small=j; } if(small! =i) {L->INT[0]=L->INT[i]; L->INT[i]=L->INT[small]; L->INT[small]=L->INT[0]; } } } voidBUBBLE(SqList*L)//冒泡优化排序 { inti,j,flag=1; for(i=0;i<=L->length-1&&flag==1;i++) { flag=0; for(j=0;j { if(L->INT[j]>L->INT[j+1]) { flag=1; L->INT[0]=L->INT[j]; L->INT[j]=L->INT[j+1]; L->INT[j+1]=L->INT[0]; } } } } voidBUILDHEAP(SqList*L,intk,intm)//建立堆 { inti,x; x=L->INT[k]; for(i=2*k;i<=m;i=i*2) { if(i i++; if(x>L->INT[i])break; L->INT[k]=L->INT[i]; k=i; } L->INT[k]=x; } voidHEAPSORT(SqList*L)//堆排序 { inti,n,temp; n=L->length; for(i=n/2;i>0;i--) BUILDHEAP(L,i,n); for(i=n;i>1;i--) { temp=L->INT[1]; L->INT[1]=L->INT[i]; L->INT[i]=temp; BUILDHEAP(L,1,i-1); } } voidRAND(SqList*L)//随机生成数字 { inti; srand((unsigned)time(NULL)); L->length=(rand()%(14))+2; for(i=0;i { L->INT[i]=(rand()%(100))+1; } } voidDisPlay(SqList*L)//数组回显 { inti; for(i=1;i<=L->length;i++) { printf("%d",L->INT[i]); } printf("\n"); } voidINIT(SqList*L)//初始化排序的数据 { inti; charc; loop: ; TIME(); printf("\t ─────────────────────\n"); printf("\n\t\t\t请输入待排序数据的数量【>=2】: "); while(scanf("%d",&L->length)! =1)//检测是否为正确输入数 { while((c=getchar())! ='\n'); printf("\n\t\t【×】Error: 错误的输入,请按任意键重新输入→\n\t\t\t\t"); getch(); system("cls"); gotoloop; } if(L->length<2||L->length>MAXSIZE) { printf("\n\t\t\t\t【×】Error: \n\t\t待排序数据数目小于2或超出最大输入量,请按任意键重新输入→\n\t\t\t\t"); getch(); system("cls"); gotoloop; } printf("\n"); for(i=1;i<=L->length;i++) { printf("\t\t\t请输入第%d个数据: ",i); lable: ; while(scanf("%d",&L->INT[i])! =1) { while((c=getchar())! ='\n'); printf("\n【×】Error: 数据输入出错,请重新输入→"); gotolable; } } printf("\n\n\n\n\t\t\t数据初始化成功,按任意键继续→\n"); getch(); system("cls"); } voidPRIN()//格式化输出─ { inti; printf("\t\t"); for(i=0;i printf("──"); printf("\n"); } intMENUE() { intinput_data; charc; TIME(); printf("\t ╭─────────────────────╮\n"); printf("\t|各种排序的基本操作实现|\n"); printf("\t |─────────────────────|\n"); printf("\t|1、手动(Hand)输入数据|\n"); printf("\t |─────────────────────|\n"); printf("\t|2、随机(Rand)生成数据|\n"); printf("\t |─────────────────────|\n"); printf("\t|3、退出...|\n"); printf("\t╰─────────────────────╯\n"); printf("\t请正确选择: "); while(scanf("%d",&input_data)! =1) { while((c=getchar())! ='\n'); returninput_data; } fflush(stdin); returninput_data; } voidSUB_MENUE() { charc; for(;;){ TIME(); printf("\t ╭─────────────────────╮\n"); printf("\t|各种排序的基本操作实现|\n"); printf("\t |─────────────────────|\n"); printf("\t|1、重新(Again)输入数据|\n"); printf("\t|2、折半(Binary)排序|\n"); printf("\t|3、直接(Straight)排序|\n"); printf("\t|4、希尔(Shell)排序|\n"); printf("\t|5、快速(Quick)排序|\n"); printf("\t|6、选择(Select)排序|\n"); printf("\t|7、冒泡(Bubble)排序|\n"); printf("\t|8、堆(Heap)排序|\n"); printf("\t|9、随机(Rand)生成|\n"); printf("\t|Q、退出...|\n"); printf("\t╰─────────────────────╯\n"); printf("\t【共%d个数据】如下: \n",L.length); PRIN(); PRINT(&L); PRIN(); printf("\t请选择: "); scanf("%s",&c); switch(c) { case'1': system("cls"); INIT(&L); system("cls"); break; case'2': BIS_INT(&L); printf("\n\t\t\t排序成功! ! ! \n\t\t\t"); DisPlay(&L); system("pause"); system("cls"); break; case'3': STINSORT(&L); printf("\n\t\t\t排序成功! ! ! \n\t\t\t"); system("pause"); system("cls"); break; case'4': SHELL(&L); printf("\n\t\t\t排序成功! \n\t\t\t"); system("pause"); system("cls"); break; case'5': QUICK(&L,1,L.length); printf("\n\t\t\t排序成功! \n\t\t\t"); system("pause"); system("cls"); break; case'6': SELECT(&L); printf("\n\t\t\t排序成功! \n\t\t\t"); system("pause"); system("cls"); break; case'7': BUBBLE(&L); p
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 数据结构 课程设计