在數據排序的算法中,不一樣數據規模應當使用合適的排序算法才能達到最好的效果,如小規模的數據排序,可使用冒泡排序、插入排序,選擇排序,他們的時間複雜度都爲O(n2),大規模的數據排序就可使用歸併排序和快速排序,時間複雜度爲O(nlogn)。今天咱們就來看一下歸併排序和快速排序。html
排序數組,將數組從中間分紅先後兩部分,對先後兩部分分別排序,而後合在一塊兒,這個數組就是有序的。算法
1.歸併排序是一個穩定的排序算法:在合併的過程當中,若是A[p...q]和A[q+1...r]之間中有相同的元素,先把A[p...q]中的元素放入tmp數組。這樣就保證了值相同的元素,在合併先後的前後順序不變。
數組
2.歸併排序的時間複雜度是O(nlogn):在解決遞歸問題時,咱們得出一個結論:遞歸問題能夠寫成遞推公式,遞歸代碼的時間複雜度也能夠寫成遞推公式網絡
咱們假設對n個元素進行歸併排序須要的時間是T(n),那分解成兩個子數組排序的時間都是T(n/2),套用結論能夠獲得歸併排序的時間複雜度的計算公式就是:數據結構
T(1) = C; n=1 時,只須要常量級的執行時間,因此表示爲 C。 T(n) = 2*T(n/2) + n; n>1
再次將這個公式分解:post
T(n) = 2*T(n/2) + n = 2*(2*T(n/4) + n/2) + n = 4*T(n/4) + 2*n = 4*(2*T(n/8) + n/4) + 2*n = 8*T(n/8) + 3*n = 8*(2*T(n/16) + n/8) + 3*n = 16*T(n/16) + 4*n ...... = 2^k * T(n/2^k) + k * n ......
咱們能夠獲得T(n)=2^kT(n/2^k)+kn.當T(n/2^k)=T(1)時,也就是n/2^k=1,咱們將獲得k=log2n,問你將k帶入公式獲得性能
T(n)=Cn+nlog2n學習
用大O標記法來表示爲T(n) 就等於 O(nlogn)編碼
並且時間複雜度是很是穩定的:最好狀況,最壞狀況,仍是平均狀況,時間複雜度都是O(nlogn)url
三、歸併排序的空間複雜度爲O(n)
歸併排序的致命缺點:歸併排序不是原地排序算法(在合併兩個有序數組時,須要藉助額外的存儲空間)
遞歸代碼的空間複雜度並不能像時間複雜度那樣累加、儘管每次合併操做都須要申請額外的內存空間,但在合併完成以後、臨時開闢的內存空間就被釋放掉了、臨時內存空間最大也不會超過 n 個數據的大小
若是要排序數組中下標從p到r之間的一組數據,咱們選擇p到r之間的任意一個數據做爲pivot(分區點),遍歷數據,見小於pivot的放在右邊,大於pivot放在左邊。這樣數組就分紅了三部分,用遞歸排序下標從 p 到 q-1 之間的數據和下標從 q+1.到r之間的數據,直到區間縮小爲1,說明數據都有序
快速排序的時間複雜度爲O(1):在排序過程當中,假如遇到須要移動數據的,咱們能夠之間用交換的思想
(圖片來源於網絡,侵刪)
空間複雜度爲O(1)
看圖:
(圖片來源於網絡,侵刪)
處理過程的差別:
遞歸排序:先處理子問題再合併
快速排序:先分區,再處理子問題
歸併排序雖然穩定,是時間複雜度爲O(nlogn)的排序算法,可是它不是原地排序算法,合併過程當中須要額外的空間。
遞歸代碼的時間複雜度,若是每次分區操做,都能正好將數組分爲兩個大小相等的兩個小區間,那快速排序的遞推公式和遞推排序是相同的,因此,快排的時間複雜度爲O(nlogn)
可是,每次都分得那麼均勻是很是難實現的。
T(n)在大部分狀況下的時間複雜度均可以作到O(nlogn),只有在極端狀況下才會退化爲O(n2).
遞歸和快排都是分治的思想,代碼都經過遞歸來實現,過程很是類似。歸併排序時間複雜度都很是穩定爲O(nlogn),可是每次合併的時候都須要額外的空間,空間複雜度很是高爲是O(n),快速排序算法雖然最壞時間複雜度爲O(n2),可是平均時間複雜度爲O(nlogn),最壞的狀況咱們也能夠避免。
以上內容爲我的的學習筆記,僅做爲學習交流之用。
歡迎你們關注公衆號,不定時乾貨,只作有價值的輸出