快速排序
想明白快速排序,首先得解决这个问题:
一个无序数组,怎样调整数组各个单元的值,使得数组满足:a[0] 在数组中的某个位置,该位置的左边所有元素都不大于a[0],该位置右边的所有元素都不小于a[0] .
1 int Partition(int *a, int low, int high) { 2 if (a == null || low < 0 || high <= low) 3 return -1; 4 int temp = a[low];//先用临时变量保存啊a[0] 5 while (low < high) {//当两个扫描指针碰头时终止 6 while (low < high && a[high] >= temp) 7 --high;//从后往前找第一个小于a[0]的元素 8 swap(&a[high], &a[low]);//与空位交换 9 while (low < high && a[low] <= temp) 10 ++low;//从前往后找第一个大于a[0]的元素 11 swap(&a[high], &a[low]);//与空位交换 12 } 13 a[low] = temp;//把a[0]放到最终位置 14 return low;//返回a[0]所在位置的index 15 }
该程序执行步骤的简单说明:
(1)先用一个临时变量temp保存第一个元素
(2)两头扫描找出小于和大于temp的元素,交换位置
(3)扫描指针碰头时,循环结束。
(4)循环结束后,这时,前后两个扫描指针必定重合于一个单元,low == high; 然后啊a[low] = temp;把第一个元素放到最终位置,返回这个位置的index。
快速排序
1 void QuickSort(int *a, int low, int high) { 2 if (a == null || low < 0 || high <= low) 3 return; 4 int result = Partition(a, low, high); 5 QuickSort(a, low, result - 1); 6 QuickSort(a, result + 1, high); 7 }
快速排序是递归的。
快速排序通过不断往两边执行patition,缩小patition的范围,直到low >= high;再回溯。
最坏情况,每次选择的基准都是区间的最小的元素,每次分区结束后,基准的某一侧只有一个元素;对于不加优化的选择第一个元素作为基准的快速排序,当区间元素是有序时,退化成插入排序
时间复杂度是O(n^2);同时会有最糟糕的辅助空间:由树深logn退成线性n。
最佳情况:每次选择的基准都是区间的中位数,即排序后,基准两边的元素数目相等或差1个。这时递归的深度也最浅,是logn;
所以快速排序最适合越无序越好的大量数据。最坏是碰到有序序列,直接退化成冒泡排序。
优化策略一:生成一各[left,right]内的随机数,该随机数指向的元素与第一个元素交换值。
优化策略二:当递归到某个深度时,待分区的待排元素数目不大,终止递归;换用擅长小数据排序的排序算法,如直接插入排序,冒泡排序等。方法:递归结束条件改成right - left <= num
优化策略三:取最左,左右,中间三个元素的中间值放到第一个元素的位置;这然既减小了最坏情况的发生,又能哨兵扫描,使时间减少一半。
优化策略四:设置一个num。当待排元素数目超过num,把元素分成n份,并行处理在n个处理器上。
空间复杂度:O(logn)
稳定性:不稳定
一次性放到最终位置:是
快速排序的完整代码
1 #include"头文件.h" 2 /*快速排序*/ 3 void swap(int *a, int *b) { 4 int temp = *a; 5 *a = *b; 6 *b = temp; 7 } 8 int Partition(int *a, int low, int high) { 9 if (a == null || low < 0 || high <= low) 10 return -1; 11 int temp = a[low];//先用临时变量保存啊a[0] 12 while (low < high) {//当两个扫描指针碰头时终止 13 while (low < high && a[high] >= temp) 14 --high;//从后往前找第一个小于a[0]的元素 15 swap(&a[high], &a[low]);//与空位交换 16 while (low < high && a[low] <= temp) 17 ++low;//从前往后找第一个大于a[0]的元素 18 swap(&a[high], &a[low]);//与空位交换 19 } 20 a[low] = temp;//把a[0]放到最终位置 21 return low;//返回a[0]所在位置的index 22 } 23 24 void QuickSort(int *a, int low, int high) { 25 if (a == null || low < 0 || high <= low) 26 return; 27 int result = Partition(a, low, high); 28 QuickSort(a, low, result - 1); 29 QuickSort(a, result + 1, high); 30 } 31 32 33 int main() { 34 int a[100]; 35 for (int i = 0; i < 100; ++i) { 36 a[i] = 1 + rand() % 1000; 37 } 38 printf("排序前的数组:\n"); 39 for (int i = 0; i < 100; ++i) { 40 printf("%4d ", a[i]); 41 if ((i + 1) % 10 == 0) 42 printf("\n"); 43 } 44 printf("\n"); 45 printf("排序后的数组:\n"); 46 QuickSort(a, 0,99); 47 for (int i = 0; i < 100; ++i) { 48 printf("%4d ", a[i]); 49 if ((i+1) % 10 == 0) 50 printf("\n"); 51 } 52 printf("\n"); 53 system("pause"); 54 return 0; 55 }