快速排序(模板題)

快速排序(模板題)

Acwing 785

給定你一個長度爲n的整數數列。

請你使用快速排序對這個數列按照從小到大進行排序。

並將排好序的數列按順序輸出。

輸入格式

輸入共兩行,第一行包含整數 n。

第二行包含 n 個整數(所有整數均在1~109

範圍內),表示整個數列。

輸出格式

輸出共一行,包含 n 個整數,表示排好序的數列。

數據範圍

1≤n≤100000

輸入樣例:

5
3 1 2 4 5

輸出樣例:

1 2 3 4 5

快排模板

void quick_sort(int q[], int l, int r)
{
    if (l >= r) return;

    int i = l - 1, j = r + 1, x = q[(l + r)/2];
    while (i < j)
    {
        do i ++ ; while (q[i] < x);
        do j -- ; while (q[j] > x);
        if (i < j) swap(q[i], q[j]);
    }
    quick_sort(q, l, j), quick_sort(q, j + 1, r);
}

這種方式會將數組劃分爲小於等於和大於等於pivot 的左右兩部分,並且每一部分都不會爲空,因爲每次遞歸的時候數組的長度都會變小從而確保不會死循環。如果每次都選取數組最左邊的元素來作爲pivot,當數組已經是有序的時候每次遞歸數組的長度只會減少一,導致時間複雜度變爲 O(n2)

,這可以通過選中間元素作爲pivot或者每次隨機選取數組中一個元素與最左邊的元素交換來解決。注意這裏不能用最右邊的元素作爲pivot,這樣如果數組最右邊是最大元素的話會導致劃分完[l, j]不變導致死循環。

由於劃分完成後pivot不一定在這兩部分的分界線上,所以在做比如得到第k大的數這種題目時不能用j - l + 1 == k來判斷q[j]爲第k大的數,因爲左半區間只保證了所有數小於等於 pivot,而不一定都小於等於q[j]。

題解

#include<iostream>
using namespace std;
const int N = 100010;
int a[N];
void quick_sort(int q[],int l,int r)
{
    if(l>=r) return;
    int i=l-1,j=r+1,x=q[(l + r)/2];
    while(i<j){
        do i++ ; while(q[i]<x);
        do j-- ; while(q[j]>x);
        if(i<j) swap(q[i],q[j]);
    }
    quick_sort(q,l,j),quick_sort(q,j+1,r);
}
int main()
{
    int n;
    cin >> n;
    for (int i = 0; i < n; ++ i) cin >> a[i];
    quick_sort(a,0,n-1);
    for (int i = 0; i < n; ++ i) cout << a[i] << ' ';
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章