快排演算法及常見兩種常見優化方法
阿新 • • 發佈:2019-02-17
正常快排
最近在找實習,然而我覺得部落格還是要堅持日更,我相信時間總是擠出來的,不扯淡了,快排這是個面試常考題,今天主要著重於講他的優化方法,那我就直接先貼快排程式碼,再來細細道來我所知道的優化方法,正常的快排,先上圖片後上程式碼,比較容易理解
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:如果你覺得我文章哪裡寫錯了或者哪裡太糟糕了,歡迎指出