合并排序
合并排序的思路是:把数组分成两部分,分别进行排序,再把排好序的两部分合并成排序数组。合并排序对一个n个元素的数组排序所需时间是O(nlogn)。用合并排序排序{9, 4, 5, 2, 1, 7, 4, 6}过程如下:
算法C++实现:
1 //对n个数进行合并排序 2 void Merge(int A[], int low, int mid, int high) 3 { 4 int B[];//辅助数组 5 int s = low , t = mid + 1 , k = low; 6 7 //将小元素添加到辅助数组 8 while( s<=mid && t<=high ) 9 { 10 if(A[s]<=A[t]) 11 { 12 B[k] = A[s]; 13 s = s + 1; 14 } 15 else 16 { 17 B[k] = A[t]; 18 t = t + 1; 19 } 20 k = k + 1; 21 } 22 23 if(s == mid + 1) 24 { 25 //把A[t...high]中剩余的元素复制到B数组 26 for(int i = k ; i <= high ; i++) 27 B[i] = A[t++]; 28 } 29 else 30 { 31 //把A[s...mid]中剩余的元素复制到B数组 32 for(int i = k ; i <= high ; i++) 33 B[i] = A[s++]; 34 } 35 36 //把B数组复制到A数组 37 for(int j = low ; j <= high ; j++) 38 A[j] = B[j]; 39 } 40 41 void mergesort(int A[] , int low ,int high) 42 { 43 if(low < high) 44 { 45 //把数组分成两部分分别排序在合并 46 int mid = (low+high)/2; 47 mergesort(A , low , mid); 48 mergesort(A , mid+1 , high); 49 Merge(A , low , mid , high); 50 } 51 }
快速排序
快速排序的思路是:通过Split算法划分数组A[low…high],求得A[low]的位置w,使得小于或等于A[w]的元素所处位置为A[low…w-1],大于或等于A[w]的元素的位置为A[w+1…high],再对两个划分后的子数组递归排序。快速排序最好情形的时间复杂度为O(nlogn),最坏的情形为O(n*n),平均时间复杂度O(nlogn)。对数组{4, 6, 3, 1, 8, 7, 2, 5}排序过程如下:
算法C++实现如下:
1 QuickSortint Split(int A[], int low, int high) 2 { 3 int i = low; 4 int x = A[low]; 5 6 //从左往右扫描,围绕x划分数组 7 for(int j = low+1 ; j <= high ; j++) 8 { 9 if(A[j] <= x) 10 { 11 i++; 12 if(i != j) 13 { 14 A[0] = A[i]; 15 A[i] = A[j]; 16 A[j] = A[0]; 17 } 18 } 19 } 20 21 //A[low]填入i位置 22 A[0] = A[low]; 23 A[low] = A[i]; 24 A[i] = A[0]; 25 26 return i; 27 } 28 29 void quicksort(int A[], int low, int high) 30 { 31 int w; 32 if(low < high) 33 { 34 w = Split(A, low, high);//把数组划分成两部分 35 quicksort(A, low, w-1);//对左半部分递归处理 36 quicksort(A, w+1, high);//对有半部分递归处理 37 } 38 }
合并排序和快速排序执行时间比较
随机产生20组数据,第一组500000个,第二组1000000个,以此类推,到第20组10000000个,数据范围为(0,100000),对同一组数据进行合并排序和快速排序,记录运行时间,程序如下:
1 #include <iostream> 2 #include <stdlib.h> 3 #include <time.h> 4 #include <string> 5 6 using namespace std; 7 8 int A[10000001];//数据数组 9 int C[10000001];//复制数组 10 int B[10000001];//辅助数组 11 12 //初始化,随机产生n个数据保存在C数组中 13 void Initialize(int n) 14 { 15 srand((unsigned)time(0)); 16 for(int i = 1 ; i <= n ; i++) 17 C[i] = rand()%100000; 18 } 19 20 //复制C数组元素到A数组 21 void CopyCtoA(int n) 22 { 23 for(int i = 1 ; i <= n ; i++) 24 A[i] = C[i]; 25 } 26 27 28 //Merge 29 void Merge(int A[], int low, int mid, int high) 30 { 31 //int B[100001];//辅助数组 32 int s = low , t = mid + 1 , k = low; 33 34 //将小元素添加到辅助数组 35 while( s<=mid && t<=high ) 36 { 37 if(A[s]<=A[t]) 38 { 39 B[k] = A[s]; 40 s = s + 1; 41 } 42 else 43 { 44 B[k] = A[t]; 45 t = t + 1; 46 } 47 k = k + 1; 48 } 49 50 if(s == mid + 1) 51 { 52 //把A[t...high]中剩余的元素复制到B数组 53 for(int i = k ; i <= high ; i++) 54 B[i] = A[t++]; 55 } 56 else 57 { 58 //把A[s...mid]中剩余的元素复制到B数组 59 for(int i = k ; i <= high ; i++) 60 B[i] = A[s++]; 61 } 62 63 //把B数组复制到A数组 64 for(int j = low ; j <= high ; j++) 65 A[j] = B[j]; 66 } 67 68 //MergeSort 69 void MergeSort(int A[], int low, int high) 70 { 71 if(low < high) 72 { 73 //把数组分成两部分分别排序在合并 74 int mid = (low+high)/2; 75 MergeSort(A , low , mid); 76 MergeSort(A , mid+1 , high); 77 Merge(A , low , mid , high); 78 } 79 } 80 81 //Split 82 int Split(int A[],int low,int high) 83 { 84 A[0]=A[low]; //把基准记录暂存在A[0]中 85 int key=A[low]; 86 while(low<high) 87 { 88 while((low<high)&&(A[high]>=key)) //从右到左扫描 89 high--; 90 if(low<high) //low>=high而退出的循环,不需要移动数据 91 A[low++]=A[high]; //记录,并将low往右移动一个单位 92 while((low<high)&&(A[low]<=key)) //从左到右扫描 93 low++; 94 if(low<high) 95 A[high--]=A[low]; //记录,并将up往左移动一个单位 96 } 97 A[low]=A[0]; //正确的位置填入基准位置 98 return low; //返回当前填入基准记录的所在位置 99 } 100 101 //QuickSort 102 void QuickSort(int A[], int low, int high) 103 { 104 int mid; 105 if(low < high) 106 { 107 mid = Split(A, low, high);//把数组划分成两部分 108 QuickSort(A, low, mid-1);//对左半部分递归处理 109 QuickSort(A, mid+1, high);//对有半部分递归处理 110 } 111 } 112 113 114 115 //对n个数执行合并排序或快速排序,计算输出执行时间 116 void Sort_ExcutionTime(int n , string sort_type) 117 { 118 CopyCtoA(n); 119 clock_t start, end; 120 double totaltime; 121 122 if(sort_type == "MergeSort") 123 { 124 start = clock(); 125 MergeSort(A, 1, n); 126 end = clock(); 127 } 128 else if(sort_type == "QuickSort") 129 { 130 start = clock(); 131 QuickSort(A, 1, n); 132 end = clock(); 133 } 134 135 totaltime = (double)(end-start)/CLOCKS_PER_SEC*1000; 136 //totaltime = end-start; 137 cout<<sort_type<<" running time is: "<<totaltime<<" ms"<<'\n'; 138 } 139 140 //执行程序 141 void Excute() 142 { 143 for(int i = 1 ; i <= 20 ; i++) 144 { 145 Initialize(500000*i); 146 cout<<"n="<<500000*i<<'\n'; 147 Sort_ExcutionTime(500000*i, "MergeSort"); 148 Sort_ExcutionTime(500000*i, "QuickSort"); 149 cout<<'\n'; 150 } 151 } 152 153 int main() 154 { 155 Excute(); 156 return 0; 157 }
执行结果:
排序同一组数据,当数据量较少时,QuickSort的运行时间比MergeSort的运行时间少,随着数据增加,MergeSort的运行时间比QuickSort的运行时间少。