快速、歸併、堆排、冒泡、選擇、插入詳解

快速排序

分區(partition)

給一個數組arr和一個num,要求大於num的在左邊,小於num的在右邊,要求時間複雜度是O(N),空間複雜度是O(1)。git

僞代碼:github

一、給一個指針i,初始位置是0,表示當前指向的位置
二、進行分區操做,初始化 <= 區的位置在 -1
三、當前數 <= num 時,把當前數和 <= 區的下一個數交換,<= 往前走一個位置,當前數往前跳一個。
四、當前數 > num 時,直接往前跳一個。
五、重複三、4步驟,直到整個數組遍歷完成。
複製代碼

code算法

荷蘭國旗問題

現有紅白藍三個不一樣顏色的小球,亂序排列在一塊兒,請從新排列這些小球,使得紅白藍三色的同顏色的球在一塊兒。這個問題之因此叫荷蘭國旗問題,是由於咱們能夠將紅白藍三色小球想象成條狀物,有序排列後正好組成荷蘭國旗。數組

<==>其實這個問題等價於bash

給你一個數組 arr和一個num。要求大於 num 在左邊,等於 num 在中間,小於 num 的在右邊。要求時間複雜度是 O(N)。空間複雜度是 O(1)less

僞代碼:優化

一、分區爲 <區、>區
二、用指針 i 表示當前值,指針 less 表示 < 區的值(初始是 -1),指針 more 表示 > 區的值(初始是arr.length)
三、當前值 < num。把 i和 < 區的後一個數交換,i往前走,<區往前走
四、當前值 > num。把 i和 > 區的前一個樹交換,< 區往前走,i 不動
五、當前值 = num。i++
六、重複三、四、5直到遍歷完成
複製代碼

codeui

leetcode題目地址spa

經典快排

主要應用了partiton的思想。指針

經典快排代碼 改進後的快排

時間複雜度

O(N^2)
由於會出現最壞狀況。好比 1,2,3,4,5,6,7,8,9
第一次parition。  1,2,3,4,5,6,7,8,9              其中partition中循環是9次
第二次parition 8做爲哨兵 1,2,3,4,5,6,7,8,9          8

這是個等差數列 N + N-1 + .... + 1
(N+1)*N/2 ~ O(N^2)
因此時間複雜度是 O(N^2)

最好的時候是經過partition分區的值是數值的中位數
這樣經過master公式得出時間複雜度是 O(NlogN)
T(N) = 2T(N/2) + O(N) ~ O(N)

改進方式:
在經過隨機性最後讓數組中別的值取代,這樣時間複雜度是 O(NlogN)

綜上:
經典快排的時間複雜度是 **O(N^2)**
改進的快排時間複雜度是 **O(NlogN)**

複製代碼

空間複雜度

O(logN)
由於在操做中要把左右位置記住,下次partition時才能從相應的位置開始,
而這些位置是的數量就是一個樹的高度,因此時間複雜度是 O(logN)。
複製代碼

穩定性

[ 2,4,2,1]  由算法思想得知,在排序過程當中兩個2是會互換位置的,這個算法是不穩定的。
複製代碼

優化

一、在哨兵處增長隨機性,可使得快排的時間複雜度降到O(NlogN)
二、partition 時使用荷蘭國旗方式分紅三段分區
三、快排數量較少時,使用其餘普通的排序方式(在快排的過程是使用其餘排序方式)。
複製代碼

改進後的快排

歸併排序

merge

給兩個數組各自都是有序的,如何使得所有有序?

僞代碼:

[2,3,6,7]   [5,7,9,10]

一、準備兩個指針i、j,分別指向兩個數組的頭部。再準備一個輔助數組help,臨時存儲排好序的部分數組。指針 n 指向輔助數組0位置。
二、把 i 指針指向的值和 j 指針指向的值進行比較,誰小複製誰到輔助數組help。同時 n 和 更小的指針往前走一步。直到指針i或者指針j到數組的末尾
三、指針i 或者 指針 j 退出循環。把還沒跑到指針尾部的數據複製到 help 數組中。
四、返回 help
複製代碼

merge

歸併排序邏輯

思想:

歸併排序是藉助上面 merge 的思想: 先把數組分紅左右兩部分,先讓左邊有序,
再讓右邊有序,最後總體有序。在 merge 中依次比較左右兩部分的值,
誰小 copy 誰到 help 數組。而後在把 help 數組複製到原數組相應的位置。

複製代碼

mergeSort

時間複雜度是 O(NlogN),由於這個排序能夠表示成 T(N) = T(N/2) + O(N)。

根據 master 公式這個時間複雜度是 O(NlogN)

空間複雜度是 O(N)。由於在 merge 中有個 help 數組申請。

下面問題是歸併排序思想的應用。

小和問題

在一個數組中, 每個數左邊比當前數小的數累加起來, 叫作這個數組的小和。 求一個數組的小和。

例子:

對於[1,3,4,2,5]
1左邊比1小的數, 沒有;
3左邊比3小的數, 1;
4左邊比4小的數, 一、 3;
2左邊比2小的數, 1;
5左邊比5小的數, 一、 三、 四、 2
因此小和爲1+1+3+1+1+3+4+2=16
複製代碼

xiaohe

逆序對問題

在數組中的兩個數字,若是前面一個數字大於後面的數字,則這兩個數字組成一個逆序對,輸入一個數組,求出這個數組中的逆序對的總數P。

好比在數組 [1,3,4,2,5] 中總共有這兩個逆序對[3,2]、[四、2] 
複製代碼

code

逆序對問題2

與上題同樣,也是在 merge 中過程當中操做

reverse-pairs

code

堆排序

堆排序

冒泡排序

冒泡排序思想代碼

比較前一個位置的數若是比後一個大,就交換,不然不交換。
複製代碼

code

冒泡排序複雜度分析

  1. 算法時間是時間複雜度爲O(n²)
  2. 空間複雜度爲O(1)
  3. 選擇排序是穩定的(若是有相等元素,不交換,就能夠作到穩定)

選擇排序

選擇排序思想代碼

一、從待排序序列中,找到關鍵字最小的元素;起始假定第一個元素爲最小
二、若是最小元素不是待排序序列的第一個元素,將其和第一個元素互換
三、從餘下的 N - 1 個元素中,找出關鍵字最小的元素,重複1,2步,直到排序結束。
複製代碼

code

選擇排序複雜度分析

  1. 算法時間是時間複雜度爲O(n²)
  2. 空間複雜度爲O(1)
  3. 選擇排序是不穩定的( 不穩定算法,好比數組 [5,5,1],依次排序事後,1,5交換位置。兩個5的相對次序發生了變化,所以是不穩定性的)

插入排序

插入排序思想代碼

一、從第一個元素開始,該元素能夠認爲已經被排序
二、取出下一個元素,在已經排序的元素序列中從後向前掃描
三、若是下一個元素比掃描的元素小,交換。不然,跳出循環,繼續下次循環的排序
複製代碼

code

插入排序複雜度分析

  1. 時間是時間複雜度爲O(n²)。
  2. 空間複雜度爲O(1)
  3. 插入排序是穩定的(對於數組[2,4,6,4],當4插入有序數組2,4,6時,當相等時,就中止,不作處理,能夠作到穩定性)

總結

排序方法 時間複雜度 空間複雜度 穩定性
快排 O(NlogN) O(logN) 不穩定
歸併 O(NlogN) O(N) 穩定
堆排 O(NlogN) O(1) 不穩定
冒泡 O(N^2) O(1) 穩定
選擇 O(N^2) O(1) 不穩定
插入 O(N^2) O(1) 穩定

備註:快排、歸併、堆排雖然時間複雜度都是O(logN),可是常數項極低,所以工程上有的相對比較多。

原文地址,歡迎 star。

相關文章
相關標籤/搜索