排序演算法的總結
學習了選擇排序演算法、插入排序演算法、氣泡排序演算法等。
選擇排序演算法: 時間複雜度是O(n*n)
主要思想是: 每次迴圈是第i個與後面的元素逐個比較,一次迴圈後得出了最大值,放在了第i個位置上
插入排序演算法:
1. 從第i個元素開始,逐個比較i-1到0個元素,誰大誰小。在每次比較的過程中是交換比較的元素
由於每次比較採用的是交換每個元素,交換存在時間的消耗。
2. 每次比較記錄比較的最大值,採用的是向後移一位的方法來避免交換帶來的時間上不必要的消耗
氣泡排序演算法
1. 相鄰的兩個元素比較,符合條件的就交換每個元素的值,然後在i+1,再相鄰的每個元素比較
比較一趟下來,最後一個元素就是最大值了
由於每次比較採用的是交換的方法來處理符合條件的元素,存在著時間上的不必要的消耗
2. 把交換的操作改為移位的操作,這樣就減少了交換帶來的消耗
*X*:不難看出插入排序和氣泡排序都可能由於交換操作帶來時間上的消耗,仔細觀察可以發現排序演算法中存在著許多可以
優化程式碼的小細節
歸併排序演算法:(每次歸併的時候採用的是二分)
1. 自頂向下的過程 開始是全部,每次遞迴都是二分 。在最後一次的時候子塊變得有序,主塊也變的有序了
2.自底向上的過程 採用一個增量(增量的大小在沒次迴圈之後*2),增量把整體分成了幾個部分,分別把這些部分排好序
整體就有序了
// 自底向上 的 歸併排序算
function MergeSortBU(arr, n) {
for(var sz=1; sz<n; sz += sz)
for(var i=0; i + sz <n; i += sz +sz)
Merge(arr, i, i+sz-1, min(i + sz + sz-1, n-1))
}
快速排序演算法:時間複雜度(O(nlogn))
主要是Partition函式
1. 設定兩個k,j變數
k 是遍歷的元素 j是大於和小於指定元素的邊界
返回值p保證 arr[l...p-1] < arr[p]
arr[p+1...r] > arr[p]
問題來了:
當排序陣列近乎有序的時候 快排的節點組成的樹節點的高度為n(本來是log(n))
這時 快排退化成 o(n*n) 級別的排序演算法
解決: 在採取指定值的時候可以隨機一個值來作為這次Partition的指定值
問題又來了:
當陣列元素中有大量的重複元素 是一樣的情況下
會導致快排的時候一端 變得非常長 而另一端變得很短
這時如果重新改變 Partition函式 尤為重要
2. Partition函式採用兩頭的辦法來解決這個問題
使用兩個變數i和j
保證 [l+1...i) <= arr[l]
[j...r] >= arr[l]
返回的是 i
快速排序的最優演算法(三路排序演算法)
三路快速排序演算法 分成三部分 小於 等於 大於
小於arr[l] 範圍是 [l+1...lt]
等於arr[l] 範圍是 [lt+1...k)
大於arr[l] 範圍是 [gt...r]
堆排序演算法:
// 二叉堆
// 父親節點大於等於 子節點
// 是一顆完全二叉樹
// 堆排序演算法
// 將n個元素逐個插入到一個空堆中,演算法複雜度是O(nlongn)
穩定排序 對於相等的元素 在排序後,原來靠前的元素依然靠前
至此排序演算法就算告一個段落了,在排序演算法的過程中還是挺有意思的。就是發現問題,解決問題的過程。要想達到自己想要的
時間複雜度,就要想辦法優化演算法。