快速排序的一種優化算法(三向切分)


快速排序:

時間復雜度O(N*logN),最壞情況為O(N^2)

空間復雜度O(1)

但是堆棧深度一般情況為O(logN),最壞情況為O(N)


 

快速排序實現:

partition划分算法:

int Partition(SeqList R,int i,int j)
{
    //調用Partition(R,low,high)時,對R[low..high]做划分,
    //並返回基准記錄的位置
    ReceType pivot=R[i]; //用區間的第1個記錄作為基准 '
    while(i<j){ //從區間兩端交替向中間掃描,直至i=j為止
        while(i<j&&R[j].key>=pivot.key) //pivot相當於在位置i上
            j--; //從右向左掃描,查找第1個關鍵字小於pivot.key的記錄R[j]
        if(i<j) //表示找到的R[j]的關鍵字<pivot.key
            R[i++]=R[j]; //相當於交換R[i]和R[j],交換后i指針加1
        while(i<j&&R[i].key<=pivot.key) //pivot相當於在位置j上
            i++; //從左向右掃描,查找第1個關鍵字大於pivot.key的記錄R[i]
        if(i<j) //表示找到了R[i],使R[i].key>pivot.key
            R[j--]=R[i]; //相當於交換R[i]和R[j],交換后j指針減1
    } //endwhile
    R[i]=pivot; //基准記錄已被最后定位
    return i;
} //partition 

然后,對整個數組進行遞歸排序:

QUICKSORT(A, p, r)
    if p < r
        then q ← PARTITION(A, p, r)   //關鍵
    QUICKSORT(A, p, q - 1)
    QUICKSORT(A, q + 1, r)

算法導論中提到的快速排序的優化版本:就地重排

PARTITION(A, p, r)
    x ← A[r]         //以最后一個元素,A[r]為主元
    i ← p - 1
    for j ← p to r - 1    //注,j從p指向的是r-1,不是r。
        do if A[j] ≤ x
            then i ← i + 1
            exchange A[i] <-> A[j]
    exchange A[i + 1] <-> A[r]
    return i + 1

本文重點:三向切分

快速排序什么時候不適用? 元素重復率特別高的時候。
如何優化?三向切分。前后各倆指針,總共四個指針。倆額外的指針指向跟待選元素相同的元素,最后全部置換到中間。
三向切分的好處?重復率高的時候,避免相同元素來回交換,節省交換次數。對於包含大量重復元素的數組,這個算法將排序時間從線性對數級降到了線性級別。
代碼:
#include <iostream>  
using namespace std;  
template <typename T>  
void sawp(T a[],int first,int second){  
    T temp;  
    temp = a[first];  
    a[first] = a[second];  
    a[second] = temp;  
}  
template <typename T>  
int sort(T a[],int low,int high){  
    if(low < high){  
        int lt = low,i=low+1,gt = high;  
        int temp = a[low];  
        while(i <= gt){  
            if(a[i] < temp){  
                sawp(a,lt++,i++);  
            }else if(a[i] > temp){  
                sawp(a,i,gt--);  
            }else{  
                i++;  
            }  
        }  
        sort(a,low,lt-1);  
        sort(a,gt+1,high);  
    }   
}  
int main() {  
    int a[] = {2,2,2,2,2,0,0,0,0,0,0,1,5};  
    //int a[] = {2,0,1,5};  
    int len = sizeof(a)/sizeof(int);  
    sort(a,0,len-1);  
    for (int i = 0; i < len; ++i)  
        cout << a[i] << " ";  
    cout << endl;  
}  

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM