数据结构C语言版实验报告内部排序算法比较Word文档下载推荐.docx
《数据结构C语言版实验报告内部排序算法比较Word文档下载推荐.docx》由会员分享,可在线阅读,更多相关《数据结构C语言版实验报告内部排序算法比较Word文档下载推荐.docx(15页珍藏版)》请在冰豆网上搜索。
![数据结构C语言版实验报告内部排序算法比较Word文档下载推荐.docx](https://file1.bdocx.com/fileroot1/2023-1/10/b4773ff0-392b-4bc6-b1ff-f850c77d4073/b4773ff0-392b-4bc6-b1ff-f850c77d40731.gif)
voidSelSort(LinkList*L,int*CmpNum,int*ChgNum)//选择排序
voidCompare(LinkList*L,int*CmpNum,int*ChgNum)//比较所有排序
2.各程序模块之间的层次(调用)关系:
二、详细设计
//定义标识符关键字BOOL别名为
inttypedefstructStudentData//记录数据类型
{
intnum;
//定义关键字类型
}Data;
//排序的记录数据类型定义
typedefstructLinkList//记录线性表
{
intLength;
//定义表长
//表长记录最大值
}LinkList;
//排序的记录线性表类型定义
intRandArray[MAXSIZE];
//定义随机数组类型及最大值
/******************随机生成函数********************/
voidRandomNum()
inti;
srand((int)time(NULL));
//用伪随机数程序产生伪随机数
for(i=0;
i小于MAXSIZE;
i++)RandArray[i]<
=(int)rand();
返回;
/*****************初始化链表**********************/
voidInitLinkList(LinkList*L)//初始化链表
memset(L,0,sizeof(LinkList));
RandomNum();
i小于<
MAXSIZE;
i++)
L->
Record[i].num<
=RandArray[i];
L->
Length<
=i;
BOOLLT(inti,intj,int*CmpNum)
(*CmpNum)++;
若i<
j)则返回TRUE;
否则返回FALSE;
voidDisplay(LinkList*L)
FILE*f;
//定义一个文件指针finti;
若打开文件的指令不为空则//通过文件指针f打开文件为条件判断
{//是否应该打开文件输出“can'
topenfile”;
exit(0);
}
for(i=0;
i小于L->
Length;
fprintf(f,"
%d\n"
L->
Record[i].num);
通过文件指针f关闭文件;
三、调试分析
1.调试过程中遇到的问题及经验体会:
在本次程序的编写和调试过程中,我曾多次修改代码,并根据调试显示的界面一次次调整代码。
在调试成功之前,我的程序因为3个错误而无法运行,在经过完整并且仔细的检查后,发现3处错误分别是没有定义变量就直接套用、忘记加指针符号、忘记在嵌套语句后加大括号,这些看似不显眼的小问题却导致整个程序无法运行,所以我认为在编程过程中要及其严谨,尽量少犯或避免犯语法错误,保证代码的完整性。
2.算法的时空分析:
1.稳定性比较:
插入排序、冒泡排序、简单选择排序及其他线形排序是稳定的;
希尔排序、快速排序、堆排序是不稳定的。
2.时间复杂性比较:
插入排序、冒泡排序、选择排序的时间复杂性为O(n2);
其它非线形排序的时间复杂性为O(nlog2n);
线形排序的时间复杂性为O(n)。
3.辅助空间的比较:
线形排序的辅助空间为O(n),其它排序的辅助空间为O
(1)。
4.其它比较:
插入、冒泡排序的速度较慢,但参加排序的序列局部或整体有序时,这种排序能达到较快的速度。
反而在这种情况下,快速排序反而慢了:
当n较小时,对稳定性不作要求时宜用选择排序,对稳定性有要求时宜用插入或冒泡排序;
当n较大时,关键字元素比较随机,对稳定性没要求宜用快速排序。
当n较大时,关键字元素可能出现本身是有序的,对稳定性有要求时,空间允许的情况下,宜用归并排序。
当n较大时,关键字元素可能出现本身是有序的,对稳定性没有要求时宜用堆排序。
四、用户守则
1.可执行文件为:
a.exe
2.为了界面更加友好特将背景颜色设计为黑色,字体为白色。
3.进入演示程序后即显示文本形式的用户界面,再按提示一步步完成:
五、测试结果
测试结果及其分析:
通过本次程序的运行,得到数据:
插入排序:
比较的次数为25114496,交换的次数为25094525,花费的时间为1203ms;
希尔排序:
比较的次数为3834939,交换的次数为3782098,花费的时间为187ms;
快速排序:
比较的次数为153398,交换的次数为62804,花费的时间为0ms;
堆排序:
比较的次数为235273,交换的次数为124235,花费的时间为16ms;
冒泡排序:
比较的次数为49995000,交换的次数为27537172,花费的时间为2969ms;
选择排序:
比较的次数为50005000,交换的次数为9988,花费的时间为1656ms。
算法效率是依据算法执行的时间来看的,从上面的数据来看,虽然插入排序的算法简洁,容易实现,但是从它执行的时间1203ms来看它的效率并不是很高,而且比较次数和交换次数都比较多,在这六种排序中效率是很底的;
希尔排序的时间复杂度较直接排序低,在六种内部排序中效率居中;
分析冒泡排序的效率,容易看出,若初始序列为“正序”序列,则只进行一趟排序,在排序过程中进行n-1次关键字的比较,反之,则需进行n-1趟排序,总的时间复杂度为O(n2),在该程序中,冒泡排序所花费的时间为4360,是所有排序中花费最多的,可见效率是很底的。
快速排序是对冒泡排序的一种改进,它所用的时间几乎为0,交换的比较的次数都比较少;
堆排序仅次于快速排序,花费的时间只有16ms。
由以上讨论可知,从时间上看,快速排序的平均性能都优于其他5种排序。
算法时间复杂度分析如下:
1、直接插入排序:
当文件的初始状态不同时,直接插入排序所耗费的时间是有很大差异的。
最好情况是文件初态为正序,此时算法的时间复杂度为O(n),最坏情况是文件初态为反序,相应的时间复杂度为O(n2),算法的平均时间复杂度是O(n2);
2、选择排序是不稳定的,算法复杂度为O(n2);
3、快速排序是不稳定的主体算法时间运算量约
O(log2n)
,划分子区函数运算量约
O(n)
,所以总的时间复杂度为
O(nlog2n)
,它显然优于冒泡排序
O(n2);
4、希尔排序是不稳定的,算法复杂度是n1.25~1.6*n1.25;
5、冒泡排序是稳定的,时间复杂度为O(n2);
6、堆排序是不稳定的。
对各种表长和测试组数进行了测试,程序运行正常。
分析实测得到的数值,6种排序算法的特点小结如下:
(1)若n较小(如n≤50),可采用直接插入或直接选择排序。
当记录规模较小时,直接插入排序较好;
否则因为直接选择移动的记录数少于直接插人,应选直接选择排序为宜;
(2)若文件初始状态基本有序(指正序),则应选用直接插人、冒泡或随机的快速排序为宜;
(3)若n较大,则应采用时间复杂度为O(nlgn)的排序方法:
快速排序、堆排序或归并排序;
快速排序是目前基于比较的内部排序中被认为是最好的方法,当待排序的关键字是随机分布时,快速排序的平均时间最短;
堆排序所需的辅助空间少于快速排序,并且不会出现快速排序可能出现的最坏情况。
这两种排序都是不稳定的。
六、附录(源代码)
#include<
stdio.h>
#include<
stdlib.h>
string.h>
time.h>
windows.h>
winbase.h>
#defineMAXSIZE10000//线性表中最多元素个数
#defineTRUE1
#defineFALSE0
typedefintBOOL;
//定义标识符关键字BOOL别名为inttypedefstructStudentData//记录数据类型
//排序的记录数据类型定义typedefstructLinkList//记录线性表
//排序的记录线性表类型定义intRandArray[MAXSIZE];
//定义随机数组类型及最大值/******************随机生成函数********************/
voidRandomNum()//随机生成函数
srand((int)time(NULL));
//用伪随机数程序产生伪随机数for(i=0;
i<
RandArray[i]=(int)rand();
return;
//调用随机函数
Record[i].num=RandArray[i];
Length=i;
BOOLLT(inti,intj,int*CmpNum){
if(i<
j)returnTRUE;
returnFALSE;
voidDisplay(LinkList*L)
if((f=fopen("
SortRes.txt"
"
w"
))==NULL)//通过文件指针f打开文件为条件判断
{//是否应该打开文件printf("
can'
topenfile\n"
);
for(i=0;
fclose(f);
//通过文件指针f关闭文件
/***********冒泡排序*******************************/
voidBubbleSort(LinkList*L,int*CmpNum,int*ChgNum)
{inti,j;
Datatemp;
MAXSIZE-1;
i++)
for(j=0;
j<
MAXSIZE-i-1;
j++){
if(!
LT(L->
Record[j].num,L->
Record[j+1].num,CmpNum))
(*ChgNum)++;
memcpy(&
temp,&
Record[j],sizeof(Data));
memcpy(&
Record[j],&
Record[j+1],sizeof(Data));
Record[j+1],&
temp,sizeof(Data));
}
/*******选择排序*******************************/
intSelectMinKey(LinkList*L,intk,int*CmpNum)
intMin=k;
for(k<
k++){
if(!
Record[Min].num,L->
Record[k].num,CmpNum))
Min=k;
}
returnMin;
voidSelSort(LinkList*L,int*CmpNum,int*ChgNum)
inti,j;
Datatemp;
i++){
j=SelectMinKey(L,i,CmpNum);
if(i!
=j)
Record[i],sizeof(Data));
Record[i],&
}
/*************快速排序******************************/
intPartition(LinkList*L,intlow,inthigh,int*CmpNum,int*ChgNum){
DataTemp;
intPivotKey;
Temp,&
Record[low],sizeof(Data));
PivotKey=L->
Record[low].num;
while(low<
high)
while(low<
high&
&
Record[high].num>
=PivotKey)
high--;
Record[low],&
Record[high],sizeof(Data));
while(low<
Record[low].num<
low++;
Record[high],&
Temp,sizeof(Data));
returnlow;
voidQSort(LinkList*L,intlow,inthigh,int*CmpNum,int*ChgNum){
intPivotLoc=0;
if(low<
PivotLoc=Partition(L,low,high,CmpNum,ChgNum);
QSort(L,low,PivotLoc-1,CmpNum,ChgNum);
QSort(L,PivotLoc+1,high,CmpNum,ChgNum);
voidQuickSort(LinkList*L,int*CmpNum,int*ChgNum){
QSort(L,0,L->
Length-1,CmpNum,ChgNum);
/*********************希尔排序*************************/voidShellInsert(LinkList*L,intdk,int*CmpNum,int*ChgNum)
DataTemp;
for(i=dk;
i++){
if(LT(L->
Record[i].num,L->
Record[i-dk].num,CmpNum)){
for(j=i-dk;
j>
=0&
LT(Temp.num,L->
Record[j].num,CmpNum)j-=dk)
Record[j+dk],&
voidShellSort(LinkList*L,intdlta[],intt,int*CmpNum,int*ChgNum)
intk;
for(k=0;
k<
t;
k++)ShellInsert(L,dlta[k],CmpNum,ChgNum);
}/************堆排序******************************/
voidHeapAdjust(LinkList*L,ints,intm,int*CmpNum,int*ChgNum)
intj=0;
s++;
Record[s-1],sizeof(Data));
for(j=2*s;
j<
=mj*=2)
if(j<
m&
LT(L->
Record[j-1].num,L->
Record[j].num,CmpNum))
++j;
LT(Temp.num,L->
Record[j-1].num,CmpNum))
break;
Record[s-1],&
Record[j-1],sizeof(Data));
s=j;
voidHeapSort(LinkList*L,int*CmpNum,int*ChgNum)
inti=0;
for(i=L->
Length/2-1;
i>
=0;
i--)
HeapAdjust(L,i,L->
Length,CmpNum,ChgNum);
1;
Record[0],sizeof(Data));
Record[0],&
Record[i-1],sizeof(Data));
Record[i-1],&
HeapAdjust(L,0,i-1,CmpNum,ChgNum);
/****************比较所有排序******************************/
voidCompare(LinkList*L,int*CmpNum,int*ChgNum){
intTempTime,i;
intSpendTime;
intdlta[3]={7,3,1};
intIndata[1]={1};
TempTime=(int)GetTickCount();
ShellSort(L,Indata,1,&
CmpNum[0],&
ChgNum[0]);
SpendTime=(int)GetTickCount()-TempTime;
printf("
\n\t====================================================="
\n\n\t插入排序:
"
printf("
\n\t比较的次数=%d\t交换的次数=%d\t所用的时间=%dms"
CmpNum[0],ChgNum[0],SpendTime);
//随机数列复位TempTime=(int)GetTickCount();
ShellSort(L,dlta,3,&
CmpNum[1],&
ChgNum[1]);
SpendTime=(int)GetTickCount()-TempTime;
\n\n\t希尔排序:
CmpNum[1],ChgNum[1],SpendTime);
//随机数列复位
QuickSort(L,&
CmpNum[2],&
ChgNum[2]);
SpendTime=(int)GetTickCo