常用的有:氣泡排序、插入排序、選擇排序、歸併排序、快速排序、計數排序、基數排序、桶排序
時間複雜度:
插入,冒泡,選擇排序:o ( n^2)
快排,歸併排序:o ( nlogn )
桶,計數,基數排序:o ( n )
有些排序演算法,時間複雜度,和原始資料的有序度相關,並且有穩定排序和不穩定排序,即排序後,是否改變了原來相等元素間的順序性;
舉例,訂單按金額排序,但要求相同金額的訂單,按照建立時間排序
所以,可以先按照建立時間排序,然後選擇穩定的排序演算法,按照金額排序,這樣就可以滿足要求
氣泡排序,是原地排序演算法,空間複雜度 o ( 1 ),每次迴圈,兩兩元素進行比較,將最大的元素不斷下沉,直到成為陣列末尾元素;
冒泡是穩定排序演算法,相等的元素,並不會交換次序,並且設計演算法時,在一次遍歷中,沒有元素交換,就可以認為資料已經有序,無需下次遍歷;
最壞時間複雜度:初始狀態的有序度是 0,要進行 n*
(n-1)/
2 次交換
最好時間複雜度:初始狀態的有序度是 n*
(n-1)/
2,一次遍歷,沒有元素交換,就結束排序
平均時間複雜度:使用概率論計算比較複雜,但可以通過有序度來粗略計算
取中間值 n*
(n-1)/
4 次交換
所以簡單統計,平均時間複雜度是 o ( n^
2)
插入排序,將集合分為排序區間,和未排序區間,每次都在未排序區間,選擇元素,插入到排序區間中,直到未排序區間為空,保證後插入的相同元素,放在前面插入相同元素的後面,所以是穩定的排序演算法;
空間複雜度是 o(1
) 最好時間複雜度是 o
(n):當每次都是在排序區間最後插入元素,插入時間複雜度是 o(1
) 最壞時間和平均時間複雜度是 o
(n^2
):每次插入時間複雜度是 o
(n) 平均時間複雜度:是每次向有序集合,插入乙個元素的平均時間複雜度是 o
(n),所以平均時間複雜度,是 o
(n^2
)
選擇排序,同樣將集合,分排序區間,未排序區間,每次從未排序區間,選擇最小元素,放在排序區間隊尾;
空間複雜度 o(1
) 最好,最壞,平均時間複雜度,都是 o
(n^2
),每次選擇時間複雜度都是 o
(n),共進行 n 次選擇
不穩定的排序演算法,因為每次都需要交換元素,就可能破壞了未排序區間元素的順序性
插入排序,應用更廣;
相比於氣泡排序,交換元素操作更簡單,氣泡排序需要三行**執行交換,插入只需一行
相比於選擇排序,插入是穩定性排序,而選擇排序不是
都使用分治思想,將大問題劃分為小問題來解決,都用遞迴來實現;
歸併排序,是將集合等分為兩個子集合,分別進行排序後,合併兩個有序子集合,然後子集合,同樣進行等分,排序,合併,如此遞迴,直到集合剩餘乙個元素;
遞推公式是 f
(p..
.q)=
merge(f
(p..
.r),
f(r.
..q)
),merge,合併兩個有序的陣列
終止條件是 p == r 或者 q == r
是穩定排序演算法,要求合併有序集合中,相同的元素,將前面集合先放入
遞迴**的時間複雜度,也使用遞迴來分析;
歸併時間複雜度 t
(n)=2*
t(n/2)
+ n,其中最後乙個 n 是合併兩個有序集合 n/
2 的時間複雜度
截至條件 t(1
)= c,c 是常量
t(n)=2
*(2*
t(n/4)
+ n/2)
+ n =4*
t(n/4)
+2*n =2^
(k)*
t(n/2^
(k))
+ kn,因為k次等分後 2
^k = n
最終得到 t
(n)= nlog2n + cn
所以歸併排序的時間複雜度是 o
(nlogn),並且沒有最好和最壞的區分,都需要遞迴這麼多次
歸併排序,與要排序的原始陣列的有序程度無關,其最好情況、最壞情況,還是平均情況,時間複雜度都是 o( nlogn ),並且空間複雜度是 o ( n ),這是其乙個缺點;
快速排序,每次從集合中,選取乙個基準數,進行資料交換,保證小於基準數的值放在基準數左邊,大於基準數的值放在基準值右邊,如此對基準值左邊集合,對基準值右邊集合,進行遞迴,直到根據基準數劃分後的子集合元素個數都為1;
// 排序a陣列,從p到r的元素,等於根據基準數交換資料後,分為小於基準數的p到q的元素,和大於基準數的q到r的元素
// 然後分別進行遞迴快速排序
遞推公式:fastsort
(a,p,r)
=fastsort
(a,p,q-1)
+fastsort
(a,q+
1,r)
終止條件是:p == r
quick_sort_c
(a, p, r)
根據基準值交換元素,需要不額外使用空間,選擇基準數後,分為兩個指標,依次從左往右和從右往左,左往右選擇比基準數大的值,右往左選擇比基準數小的值,兩個指標都找到後,進行交換,最後左右指標相遇,將相遇元素和基準值交換;
注意,這裡基準數的選擇,覺得了快排效率,簡單選擇最左邊,或者最右邊,更優化是三點選取,隨機選擇等
基準數如果選最左邊,要先從右往左進行查詢,因為這樣,最終左右指標相遇的點,是從左往右得到的,比基準數大,
且交換後的元素,即比基準數小,那麼最後一次交換,就是正確的,反之會最後是從右往左,比基準數小,且交換後
的元素,即比基準數大,這樣,是無法與最左邊的基準數交換,交換後就是錯誤的
快速排序,左右指標交換元素,會破壞相等元素的順序關係,所以是乙個不穩定的排序演算法;
快速排序,每次分割槽時間複雜度是 o
(n) 最好時間複雜度:每次都是等分,進行 log2n 次分割槽,所以最好時間複雜度是 o (nlogn)
最差時間複雜度:進行了 n 次分割槽,每次分割槽都是乙個元素 + 剩餘元素,所以最壞時間複雜度是 o
(n^2
) 平均時間複雜度是 o (nlogn);
快速排序的空間複雜度是 o (1),而歸併排序,空間複雜度是 o ( n ),這是快排應用廣的乙個原因;
在 o(n) 時間複雜度內,求無序陣列中的第 k 大元素,跟快排思路類似,基準值左邊放比基準值大的元素,那麼交換元素後,如果基準值下標是 k-1,那麼那麼就有 k-1 個元素比其大,基準值就為第 k 大元素,所以和快排演算法一致,只是左邊集合放大的元素,並且終止條件是 基準下標 q = k -1;
第 k 大的元素,即集合中只有 k-
1 個元素,比其大
按照快排的思路,選擇基準值,進行分割槽後,分割槽點是 p,要求比 a[p] 大,放集合左部分,
所以集合中,有 p 個元素,比 a[p] 大,如果 p =k-
1,那麼就要 k-
1 個元素比 a[p] da, a[p] 即為所求
如果 p > k-
1,那麼在左邊集合查詢
如果 p < k-
1,那麼在右邊集合查詢
如此遞迴,最終遞迴終止條件,p +
1= k
時間複雜度:第一次分割槽,需掃瞄全部資料,第二次分割槽,n/
2 資料,如此遞迴計算 n + n/
2+ n/4+
...+
1,n(
1/2)
^k =
1,得到 2
^k = n,等比數列求和 a(1
-q^n)/1
-q =n(
1-(1
/2)^k)/(
1-1/
2)=2n
(1-1
/n)=
2n -
2 所以時間複雜度是 o
(n)
如果有 10 個日誌檔案,每個大小約 300 m,每個檔案裡是按照時間從小到大排序的,希望將 10 個日誌檔案,合併為 1 個檔案,合併後仍然按照時間戳從小到大排列,要求演算法,使用空間只有 1gb,如何快速合併
典型的歸併排序,只不過排序 1gb 資料後,需要寫入磁碟
四 排序演算法
1.快速排序 procedure qsort l,r integer var i,j,mid integer begin i l j r mid a l r div 2 repeat while a i mid do dec j if i j then begin swap a i a j inc ...
Acwing演算法基礎課筆記(1 1)排序和二分
主要思想 上課學習內容 背過模板 課下 寫出模板題 做題目 課下 寫同一道題3 5次 快排 分治 確定分解點 q l q l r 2,q 隨機 調整區間 左邊所有數小於等於x,所以右邊數都大於等於x 遞迴處理左右兩段 樸素方法 1 a b 2 q l r q i x 放a q i x 放b 3 把a...
四 排序演算法 快速排序
快速排序的思想 選擇陣列中的乙個數作為中軸線,然後以這個中軸線為中心,大於中軸線的資料放到右邊,小於中軸線的資料放到左邊,然後每次比較完後再變中軸線的位置,不斷比較下去 include using namespace std template void quick sort t arry,int l...