1. 程式人生 > >快排演算法及常見兩種常見優化方法

快排演算法及常見兩種常見優化方法

正常快排

最近在找實習,然而我覺得部落格還是要堅持日更,我相信時間總是擠出來的,不扯淡了,快排這是個面試常考題,今天主要著重於講他的優化方法,那我就直接先貼快排程式碼,再來細細道來我所知道的優化方法,正常的快排,先上圖片後上程式碼,比較容易理解


    public void sort(Comparable[] a,int lo,int hi){
        if(lo>= hi) return;
        int j=partition(a,lo, hi);
        sort(a,lo,j-1);
        sort(a,j+1, hi);
    }

    private
int partition(Comparable[] a, int lo, int hi) { int i=lo,j=hi+1; Comparable temp = a[lo]; while(true){ while(a[++i].compareTo(temp)<0) if(i==hi) break; while(a[--j].compareTo(temp)>0) if(i==lo) break; if(i>=j) break;//why?why? swap(a,i,j); } swap(a,lo,j); return
j; } private void swap(Comparable[] a, int i, int j) { Comparable t=a[i]; a[i]=a[j]; a[j]=t; }

切分軌跡圖片如下:

正常快排

時間複雜度

時間複雜度最快平均是O(nlogn),最慢的時候是O(n2);輔助空間也是O(logn);最開始學快排時最疑惑的就是這個東西不知道怎麼得來的,一種是通過數學運算可以的出來,還有一種是通過遞迴樹來理解就容易多了
這裡寫圖片描述
這張圖片別人部落格那裡弄過來的,所謂時間複雜度最理想的就是取到中位數情況,那麼遞迴樹就是一個完全二叉樹,那麼樹的深度也就是最低為Logn,這個時候每一次又需要n次比較,所以時間複雜度nlogn,當快排為順序或者逆序時,這個數為一個斜二叉樹,深度為n,同樣每次需要n次比較,那那麼最壞需要n2的時間

第一種優化方法

第一種優化方法,於插入排序相結合,在小陣列的情況下,快排比較慢,因為遞迴sort會出現呼叫自己情況,所以

//sort裡面這句
if(start>=end) return;
//換成下面這句
if(start>=end+M) 
    Insertion.sort(a,start,end);//直接將這部分排序用插入排序來完成
return;

第二種優化方法

第二種就是三向切分,主要用於具有大量重複資料的情況,可以大大提高效率,因為正常的快排會出現同樣會把這些數進行遞迴,

public void sort(Comparable[] a,int lo,int hi){
        if(lo>= hi) return;
        int j=partition(a,lo, hi);
        sort(a,lo,j-1);
        sort(a,j+1, hi);
    }

    private int partition(Comparable[] a, int lo, int hi) {

        int i=lo,j=hi+1;
        Comparable temp = a[lo];
        while(true){
            while(a[++i].compareTo(temp)<0) if(i==hi) break;
            while(a[--j].compareTo(temp)>0) if(i==lo) break;
            if(i>=j) break;
            swap(a,i,j);
        }
        swap(a,lo,j);
        return j;
    }

    private void swap(Comparable[] a, int i, int j) {
        Comparable t=a[i];
        a[i]=a[j];
        a[j]=t;
    }

三向切分示意圖和切分軌跡圖,程式碼對照著圖來看,相信聰明的你很快就可以理解
示意圖

切分軌跡圖

ps:如果你覺得我的文章對你有幫助,那麼就頂那裡點一下,也可以關注我的公眾號,csdn左上角有二維碼,有什麼問題都可以問我,文章會同步釋出哦
ps:如果你覺得我文章哪裡寫錯了或者哪裡太糟糕了,歡迎指出