洛谷 P1177 【模板】快速排序

题目所在网址:https://www.luogu.com.cn/problem/P1177

题面说是快排的板子题,可将纯纯快排的板子扔上去之后 T 的一塌糊涂...看来没这么简单。

对于快排,我的理解,一趟快排所做的事(从结果上来看)就是:把标准值扔到它最终该待的地方并且使它左边的值都小于它,右边的值都大于它。把这个过程扔到递归中去做足够多的的次数,就能够使一串数字排好顺序。

我们知道,快排的时间效率会随给定的数列特征不同而变化:

  • 假如,我们每次选定的标准值,它最终待的地方都是中间位置,这样我们的快排每次都能从中间位置分割进而递归,第一趟确定一个数的位置,第二趟确定两个数的位置,第三趟确定四个数的位置......这样的话,一共排序的趟数是 logn,每趟的时间是 O(n) ,就达到了快排的最好时间复杂度:O(nlogn)
  • 假如,这串数字本来就是有序的,我们每次选定的标准值,它最终待的地方都是最边上的位置,这就意味着我们做完一趟快排,把标准值放在该放的位置之后,第二趟快排要对剩下的 n - 1 个数做,第三趟快排要对剩下的 n - 2 个数做......这样的话,一共排序的趟数是 n ,它的时间复杂度是 n + n-1 + n-2 + ... + 2 + 1 = n(n + 1) / 2,显然,为 O(n2),这便是快排最不拿手的情况。

如何让我们的快排小兄弟不再怕这种情况?有两种思路:

  1、数据虽然很不友好,但我们设法在选取标准值的时候尽量随机。

参考如下代码:

int key = arr[(rand() % (high - low + 1)) + low];

对于本题,你甚至可以这么写:

int key = arr[(low + high) / 2];

  2,让数据变得友好

拿到数据之后,我们可以人为的将其打乱,这个过程花费 O(n),但由于 打乱数据 和 快排 是顺序的关系,不会影响到整体的时间效率。

参考如下代码:

void disrupt(int arr[], int n){//O(n)打乱数组,提升快排效率
    int temp, t_rand;
    for(int i = 0; i < n; i++){
        temp = arr[i];
        t_rand = rand() % n;
        arr[i] = arr[t_rand];
        arr[t_rand] = temp;
    }
}

这样的快排板子,便能够顺利的通过本题。

附上完整AC代码:

  1. #include<iostream>  
  2. #include<fstream>  
  3. #include<algorithm>  
  4. #include<cstdlib>  
  5. #include<ctime>  
  6. using namespace std;  
  7.   
  8. void disrupt(int arr[], int n){//O(n)打乱数组,提升快排效率  
  9.     int temp, t_rand;  
  10.     for(int i = 0; i < n; i++){  
  11.         temp = arr[i];  
  12.         t_rand = rand() % n;  
  13.         arr[i] = arr[t_rand];  
  14.         arr[t_rand] = temp;  
  15.     }  
  16. }  
  17.   
  18. void Quick_sort(int arr[], int low, int high){  
  19.     if(high <= low)return;  
  20.     int i = low - 1, j = high + 1;  
  21.     int key = arr[low];  
  22.     while(true){  
  23.         do{  
  24.             j--;          
  25.         }  
  26.         while(arr[j] > key);  
  27.         do{  
  28.             i++;  
  29.         }  
  30.         while(arr[i] < key);  
  31.         if(i < j)swap(arr[i], arr[j]);  
  32.         else break;  
  33.     }  
  34.     Quick_sort(arr, low, i - 1);  
  35.     Quick_sort(arr, j + 1, high);  
  36. }  
  37.   
  38. int num[100000 + 5];  
  39.   
  40. int main(){  
  41. //  ifstream cin("data.txt");  
  42.     srand((unsigned)time(NULL));  
  43.     int n;  
  44.     cin >> n;  
  45.     for(int i = 0; i < n; i++){  
  46.         cin >> num[i];  
  47.     }  
  48.     disrupt(num, n);  
  49.     Quick_sort(num, 0, n - 1);  
  50.     for(int i = 0; i < n; i++){  
  51.         cout << num[i] << " ";  
  52.     }   
  53.     return 0;  
  54. }  
posted @ 2020-03-07 20:14  sheeeeeeep  阅读(336)  评论(0编辑  收藏  举报