数据结构课程设计.docx

上传人:b****8 文档编号:29653626 上传时间:2023-07-25 格式:DOCX 页数:27 大小:114.18KB
下载 相关 举报
数据结构课程设计.docx_第1页
第1页 / 共27页
数据结构课程设计.docx_第2页
第2页 / 共27页
数据结构课程设计.docx_第3页
第3页 / 共27页
数据结构课程设计.docx_第4页
第4页 / 共27页
数据结构课程设计.docx_第5页
第5页 / 共27页
点击查看更多>>
下载资源
资源描述

数据结构课程设计.docx

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

数据结构课程设计.docx

数据结构课程设计

数据结构

课程设计报告

课程设计题目:

各种内部排序性能比较

 

学生姓名:

专业:

班级:

学号:

指导教师:

 

年月日

目录

试验分析

需求分析说明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=j时结束。

再交换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]INT[i-1])//开始比较(前一项大于后一项时)

{

L->INT[0]=L->INT[i];//交换+1

intExch++;

high=i-1;

low=1;

while(low<=high)

{

mid=(low+high)/2;

if(L->INT[0]INT[mid])//比较+1

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(iINT[j])

j--;

if(i

{

L->INT[i]=L->INT[j];

i++;

}

while(iINT[i]<=temp)

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]INT[small])

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;jlength-i;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(iINT[i]INT[i+1])

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

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

当前位置:首页 > 总结汇报

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

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