快速排序和随机化快排学习
0.基本思想
选定基准值(通常为当前数组的第一个元素),经过一系列比较和交换,将比基准值小的放在其左边,将比基准值大的放在其右边,这称为是一次循环。
1. 递归1
//百度百科上的C++实现:
#include <iostream> using namespace std; void Qsort(int arr[], int low, int high){ if (high <= low) return; int i = low; int j = high + 1; int key = arr[low]; while (true) { /*从左向右找比key大的值*/ while (arr[++i] < key) { if (i == high){ break; } } /*从右向左找比key小的值*/ while (arr[--j] > key) { if (j == low){ break; } } if (i >= j) break; /*交换i,j对应的值*/ int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } /*中枢值与j对应值交换*/ int temp = arr[low]; arr[low] = arr[j]; arr[j] = temp; Qsort(arr, low, j - 1); Qsort(arr, j + 1, high); } int main() { int a[] = {9,8,7,6,5}; Qsort(a, 0, sizeof(a) / sizeof(a[0]) - 1);/*这里原文第三个参数要减1否则内存越界*/ for(int i = 0; i < sizeof(a) / sizeof(a[0]); i++) { cout << a[i] << " "; } return 0; }
2.更简洁版本的代码
转自:https://blog.csdn.net/haelang/article/details/44496387,非常好的一篇博文!
//快速排序 public static void QuickSort(int[] a, int left, int right) { if (left < right) { int p = partition(a, left, right); QuickSort(a, left, p - 1); QuickSort(a, p + 1, right); } } //快速排序数组划分 private static int partition(int[] a, int left, int right) { int x = a[right]; int p = left - 1; for (int i = left; i < right; i++) { if (a[i] <= x) {//从小到大排序 p++; swap(a, p, i); } } swap(a, p+1, right); return p+1; }
精髓:p指向的是比基准元素(这里选取的是最右元素)小的最后一个的元素位置。最后p+1的位置就是right的最终的位置。
如果if判断语句改为了>,那么就是只有在a[i]比基准元素大的时候才会被调整到前面,就是大在前,从大到小排序了。
博文中给的例子也很好。
3.随机化快排
//快速排序的随机化版本,除了调用划分函数不同,和之前快排的代码结构一模一样 public static void RandomQuickSort(int[] a, int left, int right) { if (left < right) { int p = randomPartition(a, left, right); RandomQuickSort(a, left, p - 1); RandomQuickSort(a, p + 1, right); } } //随机化划分 public static int randomPartition(int[] a, int left, int right) { int r = random.nextInt(right - left) + left; //生成一个随机数,即是主元所在位置 swap(a, right, r); //将主元与序列最右边元素互换位置,这样就变成了之前快排的形式。 return partition(a, left, right); //直接调用之前的代码 }
因为在数组有序的时候,如果只选择最右作为基准,快排就退化为选择排序,复杂度O(n^2)。快排平均时间复杂度是O(nlogn),对于每一个元素都是排左和排右。所以这里的改进策略是随机选取基准元素,就可以得到平衡的划分。
4.性能比较
上面博文中给了测试结果,在随机化的序列中,普通快排相较于随机化更快一点,因为后者多了生成随机数与交换的过程。
但是在已经排好序的序列中,随机化是碾压级别的!