测试排序算法耗时
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.0050sShell: 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
在排序基数变得很大的情况下,采用快速排序算法所花时间最少,整体效率也较高。
* 本实验可能缺乏一定的严谨性,还需根据后续出现的问题和现象加以完善。另外,实验过程中各算法执行的顺序有异,因此测量时间有可能存在差异。*
* 欢迎友好指出此实验中存在的不足!*
相关文章推荐
- JavaScript演示排序算法
- 算法之排序算法的算法思想和使用场景总结
- php 地区分类排序算法
- js三种排序算法分享
- Javascript中的常见排序算法
- java 合并排序算法、冒泡排序算法、选择排序算法、插入排序算法、快速排序算法的描述
- 排序算法的javascript实现与讲解(99js手记)
- C++中十种内部排序算法的比较分析
- Java实现几种常见排序算法代码
- 浅谈javascript实现八大排序
- JavaScript中九种常用排序算法
- STl中的排序算法详细解析
- PHP四种基本排序算法示例
- 排序算法之PHP版快速排序、冒泡排序
- JavaScript排序算法之希尔排序的2个实例
- Java常用排序算法及性能测试集合
- Java中常用的6种排序算法详细分解
- Javascript排序算法之合并排序(归并排序)的2个例子
- JAVA简单选择排序算法原理及实现
- 通用动态数组(三)——算法排序