2、 快速排序
小結歸併排序(merge sort)所遵循的有序定理是命題1(任何乙個元素不小於其存在的左邊元素。)。核心思想是將陣列分為兩大部分a&b,a中的所有元素總小於b中的元素,ab兩部分滿足命題1,再將ab兩部分分別再以同樣的方式分a』&b』,重複該操作直至a&b兩部分中都僅存乙個元素 。這樣每乙個元素都滿足命題1,整個陣列有序。
merge操作是歸併的核心操作,目的在於將陣列分為兩大部分a&b,a中的所有元素總小於b中的元素。下面是merge的**實現:
private static void merge(comparable> a, int lo, int mid ,int hi)
package sort;
public class mergesort extends abstractsort
private static comparable> aux;
//最小遞迴構成(核心)
private static void merge(comparable> a, int lo, int mid ,int hi)
//自頂向下遞迴,遞迴從頂部向下解開去分治
public static void sort(comparable> a, int lo, int hi)
//自低向上非遞迴,從1開始,倍數合併,最後湊出完整陣列
public static void sort(comparable> a)
exch(a, lo, j);
return j;
}
下面以圖示方式講解partition的流程。以如下陣列為例,選取第乙個元素a(紅色),從左至右找違背小於a的元素然後停止並標記,從右至左尋找違背大於a的元素然後標記並停止,我把它稱作「衝突」。
交換兩個違背的綠色元素,繼續尋找直至下一次「衝突」,然後交換「衝突」的兩個元素。
繼續尋找衝突,發現兩個箭頭相遇了,這個時候停止尋找,把藍色箭頭的和元素a交換。
這個時候以紅色元素a所在的位置將陣列切分為兩部分,前一部分a的任意元素小於a並且後一部分b的元素大於a,對a來說滿足有序的命題3。
理解partition操作後再來看快速排序,快速排序類似於歸併都運用了分治的思想,不停的拆分整體讓小部分滿足有序,最後拆分到小部分是單個元素時就意味著每個元素都滿足有序。那麼接著上面的陣列繼續以圖示說明,對a與b部分再次partiton:
這裡額外說一點,可以看到a部分中的第乙個元素是插入到了最後,這種情況是不是越來越像冒泡了?對!這個隱患會導致快排退化成冒泡。 後面在效能上繼續介紹。接著繼續遞迴深入partition。中間過程不再展示了(懶),最後就排序完成了。
//尋找和第乙個元素互換的位置
public static int partition(comparable> a, int lo, int hi)
exch(a, lo, j);
return j;
} public static void sort(comparable> a)
public static void sort(comparable> a, int lo, int hi)
public static void main(string args) ;
quicksort.sort(a);
show(a);
system.out.println(issort(a));
}}對於長度為n的任意陣列,快速排序平均需要2nlgn次比較,漸近時間複雜度為o(nlgn),空間複雜度lgn,屬於原地排序。之前的隱患也看到了,快排在極端情況下有可能退化成氣泡排序,也就是說快排最多需要n*n/2次比較,所以快排前隨機打亂陣列是最廉價的預防手段。
歸併&快排都是效果不錯的排序方法,其中快排是各大api中常用sort方法,確實快排有很多的優勢,不僅實現簡單思路也清晰。理解這兩個演算法思路是關鍵,更重要的理解由數學命題作為切入點而設計演算法的思想。這兩個演算法的思想抽象出來就是:讓子陣列滿足有序,然後分解到更小的子陣列,遞迴下去直至子陣列的長度為1,即每個元素都滿足了有序。 歸併排序選擇的命題切入點是命題1——任何乙個元素不小於其存在的左邊元素。(效果上和命題2——有序陣列其任何乙個元素不大於其右邊的元素,一致),快速排序選擇的命題切入點是命題3——有序陣列其任何乙個元素不小於其左邊元素且不大於右邊元素。相比較之前的冒泡&選擇&插入排序三兄弟,歸併和冒泡&選擇排序選擇了一樣的切入點(命題1和命題2),快速排序和插入排序一樣選擇了命題3作為切入點。歸併和快排在分治思想的加持下效能有了顯著提公升。所以思想是乙個演算法的靈魂!也決定了演算法的高度!
快速排序 歸併排序
感覺好久之前不寫這些基礎的東西忽然覺著,想複習一下,就簡單溫習一下排序的例子 package com.ruishenh.algoritmic public class sort static void printmsg int arrs system.out.println static int g...
快速排序,歸併排序
快速排序 quicksort 是對 氣泡排序的一種改進。設要排序的 陣列是a 0 a n 1 首先任意選取乙個資料 通常選用陣列的第乙個數 作為關鍵資料,然後將所有比它小的數都放到它前面,所有比它大的數都放到它後面,這個過程稱為一趟快速排序。需要注意的是,多個相同的值的相對位置也許會在演算法結束時產...
歸併排序,快速排序
快速排序實現 filename fastsort description author hcq createtime 2019 04 12 10 01 public class fastsort arrays.stream arr foreach v system.out.println 排序後 s...