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);
}
//堆排序
voidHeapAdjust(LinkList*L,ints,intm,int*CmpNum,int*ChgNum){
RedTypeTemp;
intj=0;
s++;
memcpy(&Temp,&L->r[s-1],sizeof(RedType));
for(j=2*s;j<=m;j*=2){
if(jr[j-1].key,L->r[j].key,CmpNum))
++j;
if(!
LT(Temp.key,L->r[j-1].key,CmpNum))
break;
(*ChgNum)++;
memcpy(&L->r[s-1],&L->r[j-1],sizeof(RedType));
s=j;
}
memcpy(&L->r[s-1],&Temp,sizeof(RedType));
}
voidHeapSort(LinkList*L,int*CmpNum,int*ChgNum){
inti=0;
RedTypeTemp;
for(i=L->Length/2-1;i>=0;i--)
HeapAdjust(L,i,L->Length,CmpNum,ChgNum);
for(i=L->Length;i>1;i--){
memcpy(&Temp,&L->r[0],sizeof(RedType));
(*ChgNum)++;
memcpy(&L->r[0],&L->r[i-1],sizeof(RedType));
memcpy(&L->r[i-1],&Temp,sizeof(RedType));
HeapAdjust(L,0,i-1,CmpNum,ChgNum);
}
}
//冒泡排序
voidBubbleSort(LinkList*L,int*CmpNum,int*ChgNum){
inti,j;
RedTypetemp;
for(i=1;i<=MAXSIZE;i++){
for(j=1;j<=MAXSIZE-i;j++){
if(!
LT(L->r[j].key,L->r[j+1].key,CmpNum)){
(*ChgNum)++;
memcpy(&temp,&L->r[j],sizeof(RedType));
memcpy(&L->r[j],&L->r[j+1],sizeof(RedType));
memcpy(&L->r[j+1],&temp,sizeof(RedType));
}
}
}
}
//选择排序
intSelectMinKey(LinkList*L,intk,int*CmpNum){
intMin=k;
for(;kLength;k++){
if(!
LT(L->r[Min].key,L->r[k].key,CmpNum))
Min=k;
}
returnMin;
}
voidSelSort(LinkList*L,int*CmpNum,int*ChgNum){
inti,j;
RedTypetemp;
for(i=0;iLength;i++){
j=SelectMinKey(L,i,CmpNum);
if(i!
=j){
(*ChgNum)++;
memcpy(&temp,&L->r[i],sizeof(RedType));
memcpy(&L->r[i],&L->r[j],sizeof(RedType));
memcpy(&L->r[j],&temp,sizeof(RedType));
}
}
}
3.函数的调用关系图反映了演示程序的层次结构:
main
srand
BubbleSortInsertSortSelectSortQuickSortShellSortHeapSort
InitLinkListRandomNumLTDisplay
四、调试分析
1.对正序、逆序和若干不同程度随机打乱的可排序表,进行各种排序方法的比较测试,得到的测试数据具有较好的典型性和可比较性。
通过设计和实现指定程序的随机乱序算法,对伪随机数序列的产生有了具体的认识和实践。
2.将排序算法中的关键字比较和交换分别由Less和Swap两个内部操作实现,较好的解决了排序算法的关键字比较次数和移动次数的统计问题。
而赋值是直接统计的。
3.本实习作业采用循序渐进的策略,首先设计和实现可排序表的建立和随机操作,然后用插入排序验证各种内部辅助操作的正确性,进而逐个加入其他排序算法,最后完成对测试结果的显示。
调试能力有了提高。
五、用户手册
1.本程序的运行环境为DOS操作系统,执行文件为:
内部排序算法比较.exe。
2.进入程序后即显示文本方式的用户界面:
3.输入1回车,即得直接插入排序的排序结果及其关键字比较次数和移动次数及时间
输入2回车,即得希尔排序的排序结果及其关键字比较次数和移动次数及时间
输入3回车,即得快速排序的排序结果及其关键字比较次数和移动次数及时间
输入4回车,即得堆排序的排序结果及其关键字比较次数和移动次数及时间
输入5回车,即得冒泡排序的排序结果及其关键字比较次数和移动次数及时间
输入6回车,即得选择排序的排序结果及其关键字比较次数和移动次数及时间
输入7回车,即得以上所有排序的排序结果及其关键字比较次数和移动次数及时间
输入8回车,即退出该程序
六、测试结果
对结果的截屏如下:
对各种表长和测试组数进行了测试,程序运行正常。
分析实测得到的数值,6种排序算法(快速排序采用“比中法”)的特点小结如下:
测试
插入排序
希尔排序
快速排序
堆排序
冒泡排序
选择排序
比较次数
第三多
越乱(逆)越多
少
乱否差异小
少
乱否差异小
稍多
乱否差异很小
最多
越乱(逆)越多
越乱(逆)越多
第二多
与乱否无关
移动次数
第二多
越乱(逆)越多
约为快速排序的两倍
第二少
乱否差异较小
稍多
乱否差异很小
最多
越乱(逆)越多
最少
正和逆序少
七、附录
源程序文件名清单:
052376_李明_内部排序算法比较.cpp//主程序
#include
#include
#include
#include
#include
#include
#defineMAXSIZE5000
#defineTRUE1
#defineFALSE0
typedefintBOOL;
typedefstruct{
intkey;
}RedType;
typedefstructLinkList{
RedTyper[MAXSIZE+1];
intLength;
}LinkList;
intRandArray[MAXSIZE+1];
voidRandomNum(){
inti;
srand(2000);
for(i=1;i<=MAXSIZE;i++)
RandArray[i]=(int)rand();
}
voidInitLinkList(LinkList*L){
inti;
memset(L,0,sizeof(LinkList));
RandomNum();
for(i=1;i<=MAXSIZE;i++)
L->r[i].key=RandArray[i];
L->Length=i;
}
boolLT(inti,intj,int*CmpNum){
(*CmpNum)++;
if(ireturnTRUE;
else
returnFALSE;
}
voidDisplay(LinkList*L){
FILE*f;
inti;
if((f=fopen("SortRes.txt","w"))==NULL){
printf("can'topenfile\n");
exit(0);
}
for(i=0;iLength;i++)
fprintf(f,"%d\n",L->r[i].key);
fclose(f);
}
//希尔排序
voidShellInsert(LinkList*L,intdk,int*CmpNum,int*ChgNum){
inti,j;
RedTypeTemp;
for(i=dk;iLength;i++){
if(LT(L->r[i].key,L->r[i-dk].key,CmpNum)){
memcpy(&Temp,&L->r[i],sizeof(RedType));
for(j=i-dk;j>=0&<(Temp.key,L->r[j].key,CmpNum);j-=dk){
(*ChgNum)++;
memcpy(&L->r[j+dk],&L->r[j],sizeof(RedType));
}
memcpy(&L->r[j+dk],&Temp,sizeof(RedType));
}
}
}
voidShellSort(LinkList*L,intdlta[],intt,int*CmpNum,int*ChgNum){
intk;
for(k=0;kShellInsert(L,dlta[k],CmpNum,ChgNum);
}
//快速排序
intPartition(LinkList*L,intlow,inthigh,int*CmpNum,int*ChgNum){
RedTypeTemp;
intPivotKey;
memcpy(&Temp,&L->r[low],sizeof(RedType));
PivotKey=L->r[low].key;
while(lowwhile(lowr[high].key>=PivotKey){
high--;
(*CmpNum)++;
}
(*ChgNum)++;
memcpy(&L->r[low],&L->r[high],sizeof(RedType));
while(lowr[low].key<=PivotKey){
low++;
(*CmpNum)++;
}
(*ChgNum)++;
memcpy(&L->r[high],&L->r[low],sizeof(RedType));
}
memcpy(&L->r[low],&Temp,sizeof(RedType));
returnlow;
}
voidQSort(LinkList*L,intlow,inthigh,int*CmpNum,int*ChgNum){
intPivotLoc=0;
if(lowPivotLoc=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);
}
//堆排序
voidHeapAdjust(LinkList*L,ints,intm,int*CmpNum,int*ChgNum){
RedTypeTemp;
intj=0;
s++;
memcpy(&Temp,&L->r[s-1],sizeof(RedType));
for(j=2*s;j<=m;j*=2){
if(jr[j-1].key,L->r[j].key,CmpNum))
++j;
if(!
LT(Temp.key,L->r[j-1].key,CmpNum))
break;
(*ChgNum)++;
memcpy(&L->r[s-1],&L->r[j-1],sizeof(RedType));
s=j;
}
memcpy(&L->r[s-1],&Temp,sizeof(RedType));
}
voidHeapSort(LinkList*L,int*CmpNum,int*ChgNum){
inti=0;
RedTypeTemp;
for(i=L->Length/2-1;i>=0;i--)
HeapAdjust(L,i,L->Length,CmpNum,ChgNum);
for(i=L->Length;i>1;i--){
memcpy(&Temp,&L->r[0],sizeof(RedType));
(*ChgNum)++;
memcpy(&L->r[0],&L->r[i-1],sizeof(RedType));
memcpy(&L->r[i-1