10种排序算法分析
10种排序算法,分别是直接插入排序,折半插入排序,希尔排序,冒泡排序,快速排序,直接选择排序,树形排序,堆排序,归并排序,基数排序。各有千秋,但依旧有优劣之分,熟悉每一个算法,对于我们的代码优化,也将事半功倍。
1,直接插入排序:
基本思想:
假设待排的n个记录存放在变量R中,首先将R[1]看做是有序区,将后n - 1个数组元素看作是无序区;然后将无序区的第一个元素R[2]插入到前面有序区的适当位置,从而得到新的有序区R[1..2];依次类推,经过n - 1趟直接插入排序后,得到有序区R[1..n] 。
如果想要让数组以0开始,可以加一个temp 存储需要比较的值
1 //1直接插入法 2 template<class T> 3 int InsertSort(T* pa,int n) 4 { 5 T temp; 6 int count=0; 7 for(int i = 1;i < n;i++) 8 { 9 temp = pa[i]; 10 int j = i; 11 while(j >= 1 && temp<pa[j-1]) 12 { 13 pa[j]=pa[j-1]; 14 j--; 15 count++; //移动次数 16 } 17 pa[j]=temp; 18 } 19 return count; 20 }
2,折半插入排序:
基本思想:
与直接插入排序类似,对于每一个待排的数据元素,在有序子集中实施折半查找,分左右两个分区,以减少比较次数。
1 template<class T> 2 int BinaryInsertSort(T* pa,int n) 3 { 4 T temp; 5 int count=0; 6 for(int i=1;i<n;i++) 7 { 8 temp=pa[i]; 9 int left=0,right=i-1; 10 while(left<=right) 11 { 12 int middle = (left+right)/2; 13 if(temp < pa[middle]) 14 right = middle-1; 15 else 16 left = middle+1; 17 } 18 for(int k=i-1;k>=left;k--) 19 { 20 pa[k+1]=pa[k]; 21 count++; //移动次数 22 } 23 pa[left]=temp; 24 } 25 return count; 26 }
3,希尔排序
基本算法思想:
1)选定一个记录下标的增量gap,将整个记录序列按增量gap从第一个记录开始划分为若干组,对每组使用直接插入排序的方法;
2)减小增量gap,不断重复上述过程,如此下去,直到gap=1(此时整个序列是一组)。
1 //3.希尔排序 2 template<class T> 3 int ShellSort(T *pa,int n) 4 { 5 T temp; 6 int count=0; 7 int gap=n/2; 8 while(gap) 9 { 10 for(int start=gap; start<2*gap && start<n; start++) 11 { 12 for(int i=start;i<n;i+=gap) 13 { 14 temp=pa[i]; 15 int j=i; 16 while(j>=gap && temp<pa[j-gap]) 17 { 18 pa[j]=pa[j-gap]; 19 j-=gap; 20 count++; 21 } 22 pa[j]=temp; 23 } 24 gap=gap/2; //每组元素个数 25 } 26 } 27 return count; 28 }
4,冒泡排序
基本做法:
1)(上冒)把各记录看作按纵向排列,然后自下而上地比较相邻记录的关键字kj和kj-1,若kj-1 > kj称为逆序,则两者交换位置;再将kj-1和kj-2进行比较,如有逆序则交换,直到全部关键字均比较一遍。这样一趟加工就使一个关键字上升到依其大小应该到达的位置。设有n个关键字,则经过n-1趟加工后,就使关键字从小到大、自上而下排列好了。
2)(下沉)把各记录看作按纵向排列,然后自上而下地比较相邻记录的关键字kj和kj+1,若kj > kj+1称为逆序,则两者交换位置;再将kj+1和kj+2进行比较,如有逆序则交换,直到全部关键字均比较一遍。这样一趟加工就使一个关键字下沉到依其大小应该到达的位置。设有n个关键字,则经过n-1趟加工后,就使关键字从小到大、自上而下排列好了。
1 //4.冒泡排序法 2 template<class T> 3 int BubbleSort(T *pa,int n) 4 { 5 T temp; 6 int i=0,count=0; 7 while(i<n-1) 8 { 9 int last=n-1; 10 for(int j=n-1;j>i;j--) 11 { 12 if(pa[j]<pa[j-1]) 13 { 14 temp=pa[j-1]; 15 pa[j-1]=pa[j]; 16 pa[j]=temp; 17 last=j; 18 count++; 19 } 20 } 21 i=last; 22 } 23 return count; 24 }
5,快速排序
基本思想:
在待排序文件中任取其中一个记录,通常选取第一个记录;以该记录的关键字为分界点,经过一趟排序后,将全部记录分成两个部分,所有关键字比分界点小的记录都放在它之前,所有关键字比分界点大的记录都放在它之后;然后再分别对这两个部分重复上述过程,直到每一部分只剩有一个记录为止。
1 //5.快速排序 2 template<class T> 3 int Partition(T *pa,int low,int high) 4 { 5 int i=low,j=high; 6 T temp=pa[i]; 7 while(i!=j) 8 { 9 while(pa[j]>=temp && j>i) 10 j--; 11 if(j>i) 12 { 13 pa[i++]=pa[j]; 14 n1++; 15 } 16 while(pa[i]<=temp && i<j) 17 i++; 18 if(i<j) 19 { 20 pa[j--]=pa[i]; 21 n1++; 22 } 23 } 24 pa[i]=temp; 25 return i; 26 } 27 28 template<class T> 29 void QuickSort(T* pa,int low,int high) 30 { 31 if(low >= high) 32 return; 33 int m = Partition(pa,low,high); 34 QuickSort(pa,low,m-1); 35 QuickSort(pa,m+1,high); 36 } 37 38 template<class T> 39 void QuickSort(T* pa,int n) 40 { 41 QuickSort(pa,0,n-1); 42 }
6,直接选择排序
基本做法思想:
直接通过比较关键字,首先在所有记录中选出关键字最小的记录,将它与第一个位置上的记录交换;然后在其余记录中选出关键字次小的记录,将它与第二个位置上的记录交换;依此类推,直至所有记录排成递增序列为止。
1 //6.选择排序法 2 template<class T> 3 int SelectSort(T* pa,int n) 4 { 5 T temp; 6 int count=0; 7 for(int i=0;i<n-1;i++) 8 { 9 int min=i; 10 for(int j=i+1;j<n;j++) 11 { 12 if(pa[j]<pa[min]) 13 min=j; 14 } 15 if(min != i) 16 { 17 temp=pa[i]; 18 pa[i]=pa[min]; 19 pa[min]=temp; 20 count++; 21 } 22 } 23 return count; 24 }
7,二叉排序树排序:
基本做法思想:
首先对n个关键字(n个叶子结点)进行两两比较,然后将其中 个较小者之间再进行两两比较,如此重复,直至选出最小关键字为止;欲选出次小关键字,需将叶子结点中的最小关键字改为无穷大,并修改从该叶子结点到根的路径上各结点的值,则根结点的值即为次小关键字;重复以上操作,可依次选出从小到大的所有关键字。
1 //8. 二叉排序树 2 int PowerOfTwo(int n) 3 { 4 int k=2; 5 while(k<n) 6 { 7 k=2*k; 8 } 9 return k; 10 } 11 template<class T> 12 struct DataNode 13 { 14 T data; 15 int index; 16 int flag; 17 }; 18 template<class T> 19 bool operator<(const DataNode<T>&x,const DataNode<T>&y) 20 { 21 return(x.data<y.data); 22 } 23 template<class T> 24 int Tournament(T* pa,int n) 25 { 26 DataNode<T> item; 27 int count=0,s; 28 int bottomsize=PowerOfTwo(n); 29 int treesize=2*bottomsize-1; 30 DataNode<T>* tree=new DataNode<T>[treesize]; 31 for(int j=bottomsize-1,i=0;j<treesize;j++,i++) 32 { 33 item.index=j; 34 if(i<n) 35 { 36 item.data=pa[i]; 37 item.flag=1; 38 } 39 else 40 { 41 item.data=T(); 42 item.flag=0; 43 } 44 tree[j]=item; 45 } 46 i=bottomsize-1; 47 while(i>0) 48 { 49 j=1; 50 while(j<2*i) 51 { 52 if(tree[j+1].flag==0 || tree[j].data<tree[j+1].data) 53 { 54 tree[(j-1)/2]=tree[j]; 55 count++; 56 } 57 else 58 { 59 tree[(j-1)/2]=tree[j+1]; 60 count++; 61 } 62 j=j+2; 63 } 64 i=(i-1)/2; 65 } 66 for(i=0;i<n-1;i++) 67 { 68 pa[i]=tree[0].data; 69 tree[tree[0].index].flag=0; 70 s=UpdateTree(tree,tree[0].index); 71 count=count+s; 72 } 73 pa[n-1]=tree[0].data; 74 delete []tree; 75 return count; 76 } 77 template<class T> 78 int UpdateTree(DataNode<T>* tree,int i) 79 { 80 int count=0; 81 tree[(i-1)/2]=( i%2 ==0 ? tree[i-1]:tree[i+1]); 82 i=(i-1)/2; 83 while(i>0) 84 { 85 int j=(i%2==0?i-1:i+1); 86 if(tree[i].flag==0) 87 { 88 tree[(i-1)/2]=tree[j]; 89 count++; 90 } 91 else if(tree[j].flag==0) 92 { 93 tree[(i-1)/2]=tree[j]; 94 count++; 95 } 96 else if(tree[i]<tree[j]) 97 { 98 tree[(i-1)/2]=tree[i]; 99 count++; 100 } 101 else 102 { 103 tree[(i-1)/2]=tree[j]; 104 count++; 105 } 106 i=(i-1)/2; 107 } 108 return count; 109 }
8,堆排序
基本做法思想:
对一组待排序记录的关键字,首先将它们按堆的定义排成一个序列,常称为建堆,从而输出堆顶的最大(或最小)关键字。然后对剩余的关键字再建堆,常称为重新调整成堆,即可得到次大(或次小)关键字,如此反复进行,直到全部关键字排成有序序列为止。
1 //7.堆排序 2 template<class T> 3 void BuildHeap(T* pa,int size) 4 { 5 for(int i=size/2-1;i>=0;i--) 6 { 7 PercolateDown(pa,i,size); 8 } 9 } 10 11 template<class T> 12 void PercolateDown(T* pa,int pos,int size) 13 { 14 int p=pos,c=2*p+1; 15 T temp=pa[p]; 16 while(c<size) 17 { 18 if(c+1<size && pa[c+1]>pa[c]) 19 { 20 ++c; 21 } 22 if(temp >= pa[c]) 23 break; 24 else 25 { 26 pa[p]=pa[c]; 27 p=c; 28 c=2*p+1; 29 } 30 } 31 pa[p]=temp; 32 } 33 34 template<class T> 35 int HeapSort(T* pa,int n) 36 { 37 T temp; 38 int count=0; 39 BuildHeap(pa,n); 40 for(int i=n-1;i>0;i--) 41 { 42 temp=pa[0]; 43 pa[0]=pa[i]; 44 pa[i]=temp; 45 count++; 46 PercolateDown(pa,0,i); 47 } 48 return count; 49 }
9,归并排序
基本做法思想:
对于一个长度为n的无序文件来说,归并排序把它看成是由n个只包括1个记录的有序文件组成的文件,然后进行两两归并,最后形成包含n个记录的有序文件。
1 //9.归并排序 2 template<class T> 3 int Merge(T* ini,T* merge,int s,int m,int e) 4 { 5 int i=s,j=m+1,k=s; 6 int count=0; 7 while(i<=m &&j<=e) 8 { 9 if(ini[i]<ini[j]) 10 { 11 merge[k++]=ini[i++]; 12 count++; 13 } 14 else 15 { 16 merge[k++]=ini[j++]; 17 count++; 18 } 19 } 20 if(i<=m) 21 { 22 while(i<=m) 23 { 24 merge[k++]=ini[i++]; 25 count++; 26 } 27 } 28 else 29 { 30 while(j<=e) 31 { 32 merge[k++]=ini[j++]; 33 count++; 34 } 35 } 36 return count; 37 }
10,基数排序:
基本做法思想:
设立r个队列,队列编号分别为0 ~ r-1,(r为基数)
(1)先按最低有效位的值,把n个关键字分配到这r个队列中,然后从小到大将各队列中的关键字再依次收集起来。
(2)再按次低有效位的值把刚收集起来的关键字分配到r个队列中,重复收集工作。
(3)重复地进行上述分配和收集,直到最高有效位。也就是说,如果数位为d,则需要重复进行d次。d由所有元素中最长的一个元素的位数计量。
1 //10.基数排序 2 int RadixSort(int* pa,int n) 3 { 4 Queue<int> Q[10]; 5 int base=1,flag=1,k,i; 6 int count=0; 7 while(flag) 8 { 9 for(i=0;i<n;i++) 10 { 11 k=(pa[i]/base)%10; 12 Q[k].Push(pa[i]); 13 count++; 14 } 15 base*=10; 16 flag=0; 17 i=0; 18 for(k=0;k<10;k++) 19 { 20 while(!Q[k].Empty()) 21 { 22 pa[i++]=Q[k].Pop(); 23 if(pa[i-1]/base!=0 && flag==0) 24 { 25 flag=1; 26 } 27 count++; 28 } 29 } 30 } 31 return count; 32 }
之前对这十种算法进行过具体分析,当时还计算了它的时间,引入#include<ctime>,加入clock()函数。
这里是我的对于10种排序算法的比较代码,并且还运行成功,在这个代码里面,由于需要比较时间,所以数量必须要多。一个程序运行成功,几乎是纳秒级别的,所以,要扩大时间,并且使结果具有代表性,就要多加数据。
1 #include<iostream> 2 #include<ctime> 3 #include"stdlib.h" 4 #include"windows.h" 5 #include"queue.h" 6 #include"list.h" 7 #define P 1234 8 #define M 10 9 using namespace std; 10 static int n1=0; 11 //1直接插入法 12 template<class T> 13 int InsertSort(T* pa,int n) 14 { 15 T temp; 16 int count=0; 17 for(int i = 1;i < n;i++) 18 { 19 temp = pa[i]; 20 int j = i; 21 while(j >= 1 && temp<pa[j-1]) 22 { 23 pa[j]=pa[j-1]; 24 j--; 25 count++; //移动次数 26 } 27 pa[j]=temp; 28 } 29 return count; 30 } 31 //2.折半插入法 32 template<class T> 33 int BinaryInsertSort(T* pa,int n) 34 { 35 T temp; 36 int count=0; 37 for(int i=1;i<n;i++) 38 { 39 temp=pa[i]; 40 int left=0,right=i-1; 41 while(left<=right) 42 { 43 int middle = (left+right)/2; 44 if(temp < pa[middle]) 45 right = middle-1; 46 else 47 left = middle+1; 48 } 49 for(int k=i-1;k>=left;k--) 50 { 51 pa[k+1]=pa[k]; 52 count++; //移动次数 53 } 54 pa[left]=temp; 55 } 56 return count; 57 } 58 //3.希尔排序 59 template<class T> 60 int ShellSort(T *pa,int n) 61 { 62 T temp; 63 int count=0; 64 int gap=n/2; 65 while(gap) 66 { 67 for(int start=gap; start<2*gap && start<n; start++) 68 { 69 for(int i=start;i<n;i+=gap) 70 { 71 temp=pa[i]; 72 int j=i; 73 while(j>=gap && temp<pa[j-gap]) 74 { 75 pa[j]=pa[j-gap]; 76 j-=gap; 77 count++; 78 } 79 pa[j]=temp; 80 } 81 gap=gap/2; //每组元素个数 82 } 83 } 84 return count; 85 } 86 87 //4.冒泡排序法 88 template<class T> 89 int BubbleSort(T *pa,int n) 90 { 91 T temp; 92 int i=0,count=0; 93 while(i<n-1) 94 { 95 int last=n-1; 96 for(int j=n-1;j>i;j--) 97 { 98 if(pa[j]<pa[j-1]) 99 { 100 temp=pa[j-1]; 101 pa[j-1]=pa[j]; 102 pa[j]=temp; 103 last=j; 104 count++; 105 } 106 } 107 i=last; 108 } 109 return count; 110 } 111 112 //5.快速排序 113 template<class T> 114 int Partition(T *pa,int low,int high) 115 { 116 int i=low,j=high; 117 T temp=pa[i]; 118 while(i!=j) 119 { 120 while(pa[j]>=temp && j>i) 121 j--; 122 if(j>i) 123 { 124 pa[i++]=pa[j]; 125 n1++; 126 } 127 while(pa[i]<=temp && i<j) 128 i++; 129 if(i<j) 130 { 131 pa[j--]=pa[i]; 132 n1++; 133 } 134 } 135 pa[i]=temp; 136 return i; 137 } 138 139 template<class T> 140 void QuickSort(T* pa,int low,int high) 141 { 142 if(low >= high) 143 return; 144 int m = Partition(pa,low,high); 145 QuickSort(pa,low,m-1); 146 QuickSort(pa,m+1,high); 147 } 148 149 template<class T> 150 void QuickSort(T* pa,int n) 151 { 152 QuickSort(pa,0,n-1); 153 } 154 155 //6.选择排序法 156 template<class T> 157 int SelectSort(T* pa,int n) 158 { 159 T temp; 160 int count=0; 161 for(int i=0;i<n-1;i++) 162 { 163 int min=i; 164 for(int j=i+1;j<n;j++) 165 { 166 if(pa[j]<pa[min]) 167 min=j; 168 } 169 if(min != i) 170 { 171 temp=pa[i]; 172 pa[i]=pa[min]; 173 pa[min]=temp; 174 count++; 175 } 176 } 177 return count; 178 } 179 180 //7.堆排序 181 template<class T> 182 void BuildHeap(T* pa,int size) 183 { 184 for(int i=size/2-1;i>=0;i--) 185 { 186 PercolateDown(pa,i,size); 187 } 188 } 189 190 template<class T> 191 void PercolateDown(T* pa,int pos,int size) 192 { 193 int p=pos,c=2*p+1; 194 T temp=pa[p]; 195 while(c<size) 196 { 197 if(c+1<size && pa[c+1]>pa[c]) 198 { 199 ++c; 200 } 201 if(temp >= pa[c]) 202 break; 203 else 204 { 205 pa[p]=pa[c]; 206 p=c; 207 c=2*p+1; 208 } 209 } 210 pa[p]=temp; 211 } 212 213 template<class T> 214 int HeapSort(T* pa,int n) 215 { 216 T temp; 217 int count=0; 218 BuildHeap(pa,n); 219 for(int i=n-1;i>0;i--) 220 { 221 temp=pa[0]; 222 pa[0]=pa[i]; 223 pa[i]=temp; 224 count++; 225 PercolateDown(pa,0,i); 226 } 227 return count; 228 } 229 //8. 二叉排序树 230 int PowerOfTwo(int n) 231 { 232 int k=2; 233 while(k<n) 234 { 235 k=2*k; 236 } 237 return k; 238 } 239 template<class T> 240 struct DataNode 241 { 242 T data; 243 int index; 244 int flag; 245 }; 246 template<class T> 247 bool operator<(const DataNode<T>&x,const DataNode<T>&y) 248 { 249 return(x.data<y.data); 250 } 251 template<class T> 252 int Tournament(T* pa,int n) 253 { 254 DataNode<T> item; 255 int count=0,s; 256 int bottomsize=PowerOfTwo(n); 257 int treesize=2*bottomsize-1; 258 DataNode<T>* tree=new DataNode<T>[treesize]; 259 for(int j=bottomsize-1,i=0;j<treesize;j++,i++) 260 { 261 item.index=j; 262 if(i<n) 263 { 264 item.data=pa[i]; 265 item.flag=1; 266 } 267 else 268 { 269 item.data=T(); 270 item.flag=0; 271 } 272 tree[j]=item; 273 } 274 i=bottomsize-1; 275 while(i>0) 276 { 277 j=1; 278 while(j<2*i) 279 { 280 if(tree[j+1].flag==0 || tree[j].data<tree[j+1].data) 281 { 282 tree[(j-1)/2]=tree[j]; 283 count++; 284 } 285 else 286 { 287 tree[(j-1)/2]=tree[j+1]; 288 count++; 289 } 290 j=j+2; 291 } 292 i=(i-1)/2; 293 } 294 for(i=0;i<n-1;i++) 295 { 296 pa[i]=tree[0].data; 297 tree[tree[0].index].flag=0; 298 s=UpdateTree(tree,tree[0].index); 299 count=count+s; 300 } 301 pa[n-1]=tree[0].data; 302 delete []tree; 303 return count; 304 } 305 template<class T> 306 int UpdateTree(DataNode<T>* tree,int i) 307 { 308 int count=0; 309 tree[(i-1)/2]=( i%2 ==0 ? tree[i-1]:tree[i+1]); 310 i=(i-1)/2; 311 while(i>0) 312 { 313 int j=(i%2==0?i-1:i+1); 314 if(tree[i].flag==0) 315 { 316 tree[(i-1)/2]=tree[j]; 317 count++; 318 } 319 else if(tree[j].flag==0) 320 { 321 tree[(i-1)/2]=tree[j]; 322 count++; 323 } 324 else if(tree[i]<tree[j]) 325 { 326 tree[(i-1)/2]=tree[i]; 327 count++; 328 } 329 else 330 { 331 tree[(i-1)/2]=tree[j]; 332 count++; 333 } 334 i=(i-1)/2; 335 } 336 return count; 337 } 338 //9.归并排序 339 template<class T> 340 int Merge(T* ini,T* merge,int s,int m,int e) 341 { 342 int i=s,j=m+1,k=s; 343 int count=0; 344 while(i<=m &&j<=e) 345 { 346 if(ini[i]<ini[j]) 347 { 348 merge[k++]=ini[i++]; 349 count++; 350 } 351 else 352 { 353 merge[k++]=ini[j++]; 354 count++; 355 } 356 } 357 if(i<=m) 358 { 359 while(i<=m) 360 { 361 merge[k++]=ini[i++]; 362 count++; 363 } 364 } 365 else 366 { 367 while(j<=e) 368 { 369 merge[k++]=ini[j++]; 370 count++; 371 } 372 } 373 return count; 374 } 375 //10.基数排序 376 int RadixSort(int* pa,int n) 377 { 378 Queue<int> Q[10]; 379 int base=1,flag=1,k,i; 380 int count=0; 381 while(flag) 382 { 383 for(i=0;i<n;i++) 384 { 385 k=(pa[i]/base)%10; 386 Q[k].Push(pa[i]); 387 count++; 388 } 389 base*=10; 390 flag=0; 391 i=0; 392 for(k=0;k<10;k++) 393 { 394 while(!Q[k].Empty()) 395 { 396 pa[i++]=Q[k].Pop(); 397 if(pa[i-1]/base!=0 && flag==0) 398 { 399 flag=1; 400 } 401 count++; 402 } 403 } 404 } 405 return count; 406 } 407 int main() 408 { 409 int a[M][P],b[M][P],i,j; 410 long count[10]={0},s=0; 411 double begin[10],end[10]; //时间的开始和结束 412 double t[10]; 413 srand(time(NULL)); 414 cout<<" "<<endl; 415 for(i = 0; i <M;i++ ) 416 { 417 for(j=0;j<P;j++) 418 { 419 a[i][j]=rand()%2000; //获得的数据的范围在0~2000 420 } 421 } 422 423 //------------------------------------------------直接插入法所得时间 424 for(i = 0;i < M ;i++) 425 { 426 for(j = 0; j < P ;j++) 427 { 428 b[i][j]=a[i][j]; 429 } 430 } 431 begin[0]=clock(); 432 for(i=0;i<M;i++) 433 { 434 s=InsertSort(b[i],P); 435 count[0]=count[0]+s; 436 } 437 end[0]=clock(); 438 t[0]=(double)(end[0]-begin[0])/CLOCKS_PER_SEC; 439 cout<<"直接插入排序法的时间"<<t[0]<<'s'<<endl; 440 cout<<" 直接插入的移动次数 "<<count[0]<<endl<<endl; 441 442 //----------------------------------------------------折半插入法所得时间 443 for(i = 0; i <M;i++ ) 444 { 445 for(j=0;j<P;j++) 446 b[i][j]=a[i][j]; 447 } 448 s=0; 449 begin[1]=clock(); 450 for(i=0;i<M;i++) 451 { 452 s=BinaryInsertSort(b[i],P); 453 count[1]=count[1]+s; 454 } 455 end[1]=clock(); 456 t[1]=(double)(end[1]-begin[1])/CLOCKS_PER_SEC; 457 cout<<"折半插入所用时间:"<<t[1]<<'s'<<endl; 458 cout<<" 折半 插入移动次数:"<<count[1]<<endl<<endl; 459 //---------------------------------------------------希尔排序法所得时间 460 for(i = 0; i <M;i++ ) 461 { 462 for(j=0;j<P;j++) 463 b[i][j] = a[i][j]; 464 } 465 begin[2]=clock(); 466 for(i=0;i<M;i++) 467 { 468 s=ShellSort(b[i],P); 469 count[2]=count[2]+s; 470 } 471 end[2]=clock(); 472 t[2]=(double)(end[2]-begin[2])/CLOCKS_PER_SEC; 473 cout<<" 希尔排序法所用时间: "<<t[2]<<'s'<<endl; 474 cout<<" 希尔排序的移动次数: "<<count[2]<<endl<<endl; 475 //-----------------------------------------------------冒泡排序法所得时间 476 for(i = 0; i <M;i++ ) 477 { 478 for(j=0;j<P ;j++) 479 b[i][j] = a[i][j]; 480 } 481 begin[3]=clock(); 482 for(i = 0;i < M;i++) 483 { 484 s=BubbleSort(b[i],P ); 485 count[3]=count[3]+s; 486 } 487 end[3]=clock(); 488 t[3]=(double)(end[3]-begin[3])/CLOCKS_PER_SEC; 489 cout<<"冒泡排序法所用时间: "<<t[3]<<'s'<<endl; 490 cout<<" 冒泡排序法移动次数:"<<count[3]<<endl<<endl; 491 //--------------------------------------------------快速排序法所得时间 492 for(i = 0; i <M;i++ ) 493 { 494 for(j=0;j<P;j++) 495 b[i][j]=a[i][j]; 496 } 497 s=0; 498 begin[4]=clock(); 499 for(i = 0;i < M; i++) 500 { 501 QuickSort(b[i],P); 502 } 503 count[4] = n1; 504 end [4] = clock(); 505 t[4] = (double)(end[4]-begin[4]) / CLOCKS_PER_SEC; 506 cout<<" 快速排序法所用时间: "<<t[4]<<'s'<<endl; 507 cout<<" 快速排序法移动次数: "<<count[4]<<endl<<endl; 508 //-------------------------------------------------选择排序法所得时间 for(i = 0; i < M;i++ ) 509 { 510 for(j = 0 ;j <P;j++) 511 b[i][j]=a[i][j]; 512 } 513 begin[5]=clock(); 514 for(i=0;i<M;i++) 515 { 516 s=SelectSort(b[i],P); 517 count[5]=count[5]+s; 518 } 519 end[5]=clock(); 520 t[5]=(double)(end[5]-begin[5])/CLOCKS_PER_SEC; 521 cout<<" 选择排序法所用时间:"<<t[5]<<'s'<<endl; 522 cout<<" 选择排序法移动次数:"<<count[5]<<endl<<endl; 523 //----------------------------------------------------堆排序所得时间 524 for(i = 0; i <M;i++ ) 525 { 526 for(j = 0 ;j < P;j++) 527 b[i][j] = a[i][j]; 528 } 529 530 begin[6]=clock(); 531 for(i=0;i<M;i++) 532 { 533 s=HeapSort(b[i],P); 534 count[6]=count[6]+s; 535 } 536 end[6]=clock(); 537 t[6]=(double)(end[6]-begin[6])/CLOCKS_PER_SEC; 538 539 cout<<"堆排序所用时间:"<<t[6]<<'s'<<endl; 540 cout<<" 堆排序移动次数:"<<count[6]<<endl<<endl; 541 542 //-----------------------------------------------------二叉排序法所得时间 543 for(i = 0; i <M;i++ ) 544 { 545 for(j=0;j<P;j++) 546 b[i][j]=a[i][j]; 547 } 548 begin[7]=clock(); 549 for(i=0;i<5;i++) 550 { 551 s=Tournament(b[i],10000); 552 count[7]=count[7]+s; 553 } 554 end[7]=clock(); 555 t[7]=(double)(end[7]-begin[7])/CLOCKS_PER_SEC; 556 cout<<"二叉排序法所用时间为:"<<t[7]<<'s'<<endl; 557 cout<<" 二叉排序法 的移动次数为:"<<count[7]<<endl<<endl; 558 //-----------------------------------------------------------归并排序法所得时间 559 for(i = 0; i <M;i++ ) 560 { 561 for(j=0;j<P;j++) 562 b[i][j]=a[i][j]; 563 } 564 int a1[M][P]; 565 for(i = 0; i <M;i++ ) 566 { 567 for(j=0;j<P;j++) 568 a1[i][j]=a[i][j]; 569 } 570 begin[8]=clock(); 571 for(i=0;i<5;i++) 572 { 573 s=Merge(a[i],a1[i],0,5000,P); 574 count[8]=count[8]+s; 575 } 576 Sleep(1000); 577 end[8]=clock(); 578 t[8]=(double)(end[8]-begin[8]-1000)/CLOCKS_PER_SEC; 579 cout<<"归并排序所用时间为:"<<t[8]<<'s'<<endl; 580 cout<<" 归并排序的移动次数: "<<count[8]<<endl<<endl; 581 //------------------------------------------------------基数排序法所得时间 582 for(i = 0; i <M;i++ ) 583 { 584 for(j=0;j<P;j++) 585 b[i][j]=a[i][j]; 586 } 587 begin[9]=clock(); 588 for(i=0;i<M;i++) 589 { 590 s=RadixSort(b[i],P); 591 count[9]=count[9]+s; 592 } 593 end[9]=clock(); 594 t[9]=(double)(end[9]-begin[9])/CLOCKS_PER_SEC; 595 cout<<"基数排序所用时间为:"<<t[9]<<'s'<<endl; 596 cout<<" 基数排序移动次数为: "<<count[9]<<endl<<endl; 597 //-------------------------------------------------------- 598 599 return 0; 600 }
为了方便大家参考分析,同时也给出代码中所提到的list.h文件和queue.h文件。
list.h文件:
1 #ifndef LIST_H 2 #define LIST_H 3 4 #include<stdlib.h> 5 6 template<class T> 7 class List 8 { 9 struct Node //双向结点声明 10 { 11 T data; 12 Node *prev,*next; 13 Node(const T &d=T(),Node *p=NULL,Node *n=NULL):data(d),prev(p),next(n){} 14 }; 15 int size; //数据结点个数 16 Node *head; //头结点指针 17 Node *tail; //尾结点指针 18 void init() //初始化函数 19 {size=0;head=new Node;tail=new Node;head->next=tail;tail->prev=head;} 20 21 public: 22 class const_iterator 23 { 24 protected: 25 Node *current; 26 T& retrieve()const{return current->data;} 27 const_iterator(Node *p):current(p){} 28 friend class List<T>; 29 public: 30 const_iterator():current(NULL){} 31 const T& operator*()const{return retrieve();}//current->data 32 const_iterator& operator++()//前++ 33 { 34 current=current->next; 35 return *this; 36 } 37 const_iterator operator++(int)//后++ 38 { 39 const_iterator old=*this; //old=current; 40 ++(*this); //current=current->next; 41 return old; 42 } 43 const_iterator& operator--()//前-- 44 { 45 current=current->prev; 46 return *this; 47 } 48 const_iterator operator--(int)//后-- 49 { 50 const_iterator old=*this; //old=current; 51 --(*this); //current=current->next; 52 return old; 53 } 54 bool operator==(const const_iterator & rhs)const 55 {return current==rhs.current;} 56 bool operator!=(const const_iterator & rhs)const 57 {return current!=rhs.current;} 58 59 }; 60 class iterator:public const_iterator 61 { 62 protected: 63 iterator(Node *p):const_iterator(p){} 64 friend class List<T>; 65 public: 66 iterator(){} 67 T& operator*(){return retrieve();} 68 const T& operator*()const{return const_iterator::operator*();} 69 iterator& operator++()//前++ 70 { 71 current=current->next; 72 return *this; 73 } 74 iterator operator++(int)//后++ 75 { 76 iterator old=*this; //old=current; 77 ++(*this); //current=current->next; 78 return old; 79 } 80 iterator& operator--()//前-- 81 { 82 current=current->prev; 83 return *this; 84 } 85 iterator operator--(int)//后-- 86 { 87 iterator old=*this; //old=current; 88 --(*this); //current=current->next; 89 return old; 90 } 91 }; 92 List(){init();} //默认构造函数 93 List(const List<T> &l){init();operator=(l);}//复制构造函数 94 ~List(){Clear();delete head;delete tail;} //析构函数 95 const List& operator=(const List& l); //复制赋值运算符函数 96 int Size()const{return size;} //求数据个数 97 bool Empty()const{return size==0;} //判空函数 98 void Clear(){while(!Empty())Pop_front();} //清表 99 100 iterator begin(){return iterator(head->next);} 101 const_iterator begin()const{return const_iterator(head->next);} 102 iterator end(){return iterator(tail);} 103 const_iterator end()const{return const_iterator(tail);} 104 105 T& Front(){return *begin();} //返回首元素的引用 106 const T& Front()const{return *begin();} //返回首元素的常量型引用 107 T& Back(){return *--end();} //返回尾元素的引用 108 const T& Back()const{return *--end();} //返回尾元素的常量型引用 109 void Push_front(const T& item){Insert(begin(),item);}//首插 110 void Push_back(const T& item){Insert(end(),item);}//尾插 111 void Pop_front(){Erase(begin());} //删除首结点 112 void Pop_back(){Erase(--end());} //删除尾结点 113 iterator Erase(iterator itr); //删除指示器位置上的结点 114 iterator Insert(iterator itr,const T& item);//在指示器的位置插入item 115 116 }; 117 template<class T>//复制赋值成员运算符函数的实现 118 const List<T>& List<T>::operator=(const List<T>& l) 119 { 120 Clear(); //清为空表 121 for(const_iterator itr=l.begin();itr!=l.end();++itr) //把表l的结点逐个复制 122 Push_back(*itr); 123 return *this; 124 } 125 126 template<class T> 127 List<T>::iterator List<T>::Erase(iterator itr) 128 { 129 Node *p=itr.current; 130 iterator re(p->next); 131 p->prev->next=p->next; 132 p->next->prev=p->prev; 133 delete p; 134 size--; 135 return re; 136 } 137 template<class T> 138 List<T>::iterator List<T>::Insert(iterator itr,const T& item) 139 { 140 Node *p=itr.current; 141 size++; 142 p->prev->next=new Node(item,p->prev,p); 143 p->prev=p->prev->next; 144 return iterator(p->prev); 145 } 146 147 #endif
queue.h文件:
1 #ifndef QUEUE_H 2 #define QUEUE_H 3 4 #include"list.h" 5 template<class T> 6 class Queue 7 { 8 List<T> queueL; 9 public: 10 Queue(){} 11 ~Queue(){} 12 int Size()const //求长 13 {return queueL.Size();} 14 bool Empty()const //判空 15 {return queueL.Empty();} 16 const T& Front()const //取队头项 17 {return queueL.Front();} 18 void Push(const T& item) //入队 19 {queueL.Push_back(item);} 20 T Pop() //出队 21 { T item=queueL.Front(); queueL.Pop_front(); return item;} 22 void Clear() //置空队 23 {queueL.Clear();} 24 }; 25 26 27 #endif
运行结果:
综上结果可见,快速排序,堆排序,归并排序的效率较高。
转载