快速排序

想明白快速排序,首先得解决这个问题:

一个无序数组,怎样调整数组各个单元的值,使得数组满足: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("排序前的数组:
");
39     for (int i = 0; i < 100; ++i) {
40         printf("%4d ", a[i]);
41         if ((i + 1) % 10 == 0)
42             printf("
");
43     }
44     printf("
");
45     printf("排序后的数组:
");
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("
");
51     }
52     printf("
");
53     system("pause");
54     return 0;
55 }
View Code

原文地址:https://www.cnblogs.com/joyeehe/p/7868023.html