您的位置:首页 > 其它

测试排序算法耗时

2015-07-06 01:08 288 查看

0. 问题:

在待排序基数庞大的情况下,究竟哪种算法更利于排序?

1.定义:待排序文件

typedef int keytype;
typedef struct
{   keytype key;
keytype other;
}recordtype;
typedef struct
{   recordtype r[max-1];
int length;
}table;


*现保存为table.h*


2. 编写:排序算法

//* 按从小到大排序算法 *

//希尔插入排序
void shellinsertsort(table *tab)
{
int i,j,d;
d=tab->length/2;//设置增量
while(d>=1)
{   for(i=d+1;i<=tab->length;i++)
{   tab->r[0]=tab->r[i];//先保存第i个元素作为副本
j=i-d;//向前查找待插入位置
while(tab->r[0].key<tab->r[j].key&&j>0)
{   tab->r[j+d]=tab->r[j];//记录后移
j=j-d;//以增量为单位继续向前查找待插入位置
}
tab->r[j+d]=tab->r[0];//在当前位置插入第i个元素副本
}
d=d/2;//重新设置增量
}
}


//直接插入排序
void insertsort(table *tab)
{
int i,j;
for(i=2;i<=tab->length;i++)
{   j=i-1;
tab->r[0]=tab->r[i];//保存第i个元素作为副本,往前查找待插入位置
while(tab->r[0].key<tab->r[j].key)
{   tab->r[j+1]=tab->r[j];//记录后移
j=j-1;//继续以一个单位往前查找待插入位置
}
tab->r[j+1]=tab->r[0];//在当前位置插入第i个元素副本
}
}


//冒泡排序(改良后)
void bubblesort(table *tab)
{
int i,j,done;
i=1;done=1;
while(i<=tab->length&&done)  //最多进行tab->length次冒泡,如没有发生交换则结束
{
done=0;
for(j=1;j<=tab->length-i;j++)
if(tab->r[j+1].key<tab->r[j].key)//相邻两记录的排序码不符合排序要求,则进行交换
{
tab->r[0]=tab->r[j];   //以第0个元素作为中间单元进行交换
tab->r[j]=tab->r[j+1];
tab->r[j+1]=tab->r[0];
done=1;
}
i++;
}
}


//堆排序
void heapsort(table *tab)
{
int i;
for(i=tab->length/2;i>=1;i--) sift(tab,i,tab->length); //对所有元素建堆
for(i=tab->length;i>=2;i--) // i表示当前堆的大小,即等待排序的元素的个数
{
tab->r[0]=tab->r[i];
tab->r[i]=tab->r[1];
tab->r[1]=tab->r[0];  //上述3条语句为将堆中最小元素和最后一个元素交换
sift(tab,1,i-1);
}
}


//直接选择排序
void simpleselectsort(table *tab)
{
int i,j,k;
for(i=1;i<=tab->length-1;i++)  //每次选择一个最小的元素(的位置),和第i个元素交换
{
k=i;                    //记下当前最小元素的位置
for(j=i+1;j<=tab->length;j++)   //向右查找更小的元素
if(tab->r[j].key<tab->r[k].key) k=j;  //修改当前最小元素的位置
if(k!=i)  //如果第i次选到的最小元素位置k不等于i,则将第k、i个元素交换
{
tab->r[0]=tab->r[k];   //以没有用到的第0个元素作为中间单元进行交换
tab->r[k]=tab->r[i];
tab->r[i]=tab->r[0];
}
}
}


//快速排序
void quicksort(table *tab,int left,int right)
{
int i,j;
if(left<right)
{   i=left;j=right;
tab->r[0]=tab->r[i];//保存最左边元素作为副本,并将其标准值进行划分
do
{
while(tab->r[j].key>tab->r[0].key&&i<j) j--;//从右向左查找第1个小于标准值的位置
if(i<j)
{   tab->r[i].key=tab->r[j].ke
4000
y;//记录前移至标准值左端
i++;//重置位置i
}
while(tab->r[i].key<tab->r[0].key&&i<j) i++;//从左往右查找第1个大于标准值的位置
if(i<j)
{   tab->r[j].key=tab->r[i].key;//记录后移至标准值右端
j--;//重置位置j
}
}while(i!=j);
tab->r[i]=tab->r[0];//(当i=j,意味调整过程结束)在当前位置插入副本,将元素归位
quicksort(tab,left,i-1);//递归调用本函数,调整标准值左半部分
quicksort(tab,i+1,right);//递归调用本函数,调整标准值右半部分
}
else printf("ERROR!\n");
}


//二路归并排序
/*一次归并*/
void merge(table *tabs,table *tabg,int u,int m,int v)
{
int i,j,k,t;
i=u;      /*i从第1段的起始位置开始,一直到最终位置m*/
j=m+1;    /*j从第2段的起始位置开始,一直到最终位置v*/
k=u;      /*k表示的是目标tabg的起始位置*/
while(i<=m&&j<=v)
{       /*将两段有序元素中元素值较小的元素依次放入目标tabg中*/
if(tabs->r[i].key<=tabs->r[j].key)
{
tabg->r[k]=tabs->r[i]; i++;
}
else
{
tabg->r[k]=tabs->r[j]; j++;
}
k++;
}
if(i<=m)      /*将第1段剩余元素放入目标tabg中*/
for(t=i;t<=m;t++) tabg->r[k+t-i]=tabs->r[t];
else          /*将第2段剩余元素放入目标tabg中*/
for(t=j;t<=v;t++) tabg->r[k+t-j]=tabs->r[t];
}
/*一趟归并*/
void mergepass(table *tabs,table *tabg,int len)
{
int i,j,n;
n=tabg->length=tabs->length;
i=1;
while(i<=n-2*len+1)/*将以i为起点,长度为len的相邻两个有序段依次进行归并*/
{
merge(tabs,tabg,i,i+len-1,i+2*len-1);/*一次归并*/
i=i+2*len;                           /*置下一个一次归并的起始位置*/
}
if(i+len-1<n)
/*对剩下的1个长为len,另1个长度不足len,终点为n的两个有序段归并*/
merge(tabs,tabg,i,i+len-1,n);
else          /*对剩下的1个长不超过len,终点为n的有序段进行处理*/
for(j=i;j<=n;j++) tabg->r[j]=tabs->r[j];
} /*  本算法结束后tabg中的有序段的长度为2*len  */

void mergesort(table *tab)
{
int len;
table temp;            //中间变量
len=1;                 //初始时有序段的长度为1
while(len<tab->length) //有序段的长度小于待排序元素的个数,继续归并
{
mergepass(tab,&temp,len); //一趟归并,结果在temp中
len=2*len;                            //有序段的长度翻倍
mergepass(&temp,tab,len); //一趟归并,结果在tab中
len=2*len;                            //有序段的长度翻倍
}
}


3. 实现:

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<malloc.h>
#include"table.h"
#define max 50000

int main()
{
int i;
clock_t time[7],result[6];
table tab;
tab.length=max;
for(i=1;i<tab.length;i++)
tab.r[i].key=rand();
time[0]=clock();
shellinsertsort(&tab);
time[1]=clock();
insertsort(&tab);
time[2]=clock();
bubblesort(&tab)
time[3]=clock();
heapsort(&tab)
time[4]=clock();
simpleselectsort(&tab)
time[5]=clock();
quicksort(&tab,1,tab.length);
time[6]=clock();
mergesort(&tab)
time[7]=clock();
for(i=0;i<6;i++)
result[i]=(double)(time[i+1]-time[i]/1000);
printf("The time of sorting performances:\n");
printf("Shell: %.4d\nInsert: %.4d\nBubble: %.4d\n",result[0],result[1],result[2]);
printf("Heap: %.4d\nSimple Select: %.4d\nQuick: %.4d\nMerge: %.4d\n",result[3],result[4],result[5],result[6]);
return 0;
}


4. 结论:

Quick: 0.0050s

Shell: 0.0260s

Insert: 0.8780s

Bubble: 3.4510s

Heap: 0.0080s

Simple Select: 1.5280s

Merge: 0.0060s

quick < merge < heap <shell < insert < simple select < bubble


在排序基数变得很大的情况下,采用快速排序算法所花时间最少,整体效率也较高。

* 本实验可能缺乏一定的严谨性,还需根据后续出现的问题和现象加以完善。另外,实验过程中各算法执行的顺序有异,因此测量时间有可能存在差异。*

* 欢迎友好指出此实验中存在的不足!*
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  排序算法