桶排序
- 效能:浪費空間,且只能比較自然數,時間複雜度是 O(m+n)
- 需要對資料範圍在
0~n
之間的整數進行排序
var testArr = [3, 5, 3, 5, 9, 7, 6]
console.log('原陣列:', arr)
function skipSort (n, skipArr) {
let arr = []
let sortArr = []
arr.length = n
for (let i = 0; i <= n; i++) {
arr[i] = 0
}
for (let j = 0; j < skipArr.length; j++) {
arr[skipArr[j]]++
}
for (let t = 0; t <= n; t++) {
if (arr[t]) {
for (let k = 1; k <= arr[t]; k++) {
sortArr.push(t)
}
}
}
return sortArr
}
console.log('桶排序--從小到大:', skipSort(10, testArr))
複製程式碼
氣泡排序
- 效能:時間複雜度是O(N的2次方),執行效率低
- 元素項向上移動至正確的順序,就好像氣泡往上冒一樣
從小到大
排序,比較兩個相鄰的項,如果第一個大於第二個則交換他們的位置
var arr = [3, 5, 3, 5, 9, 7, 6]
console.log('原陣列:', arr)
function bubbleSort (arr) {
let len = arr.length
for (let i = 0; i < len; i++) {
for (let j = 0; j < len - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
let temp = arr[j]
arr[j] = arr[j + 1]
arr[j + 1] = temp
}
}
}
return arr
}
console.log('氣泡排序--從小到大:',bubbleSort(arr))
複製程式碼
快速排序
- 效能:時間複雜度最差是O(N的2次方),平均時間複雜度為O(NlogN)
- 首先,在陣列中選擇一箇中間項作為主元
- 建立兩個指標,左邊的指向陣列第一個項,右邊的指向最後一個項。移動右指標,直到找到一個比主元小的項,接著,移動左邊的指標,直到找到一個比主元大的項,然後交換它們。重複這個過程,直到左側的指標超過了右側的指標。這個使比主元小的都在左側,比主元大的都在右側。這一步叫
劃分操作
。
- 接著,演算法對劃分後的小陣列(較主元小的值組成的的小陣列, 以及較主元大的值組成的小陣列)重複之前的兩個步驟,直到排序完成
切記
:一定要先從右往左找,再從左往右找,否則會出錯
var arr = [3, 5, 3, 5, 9, 7, 6]
console.log('原陣列:', arr)
function quickSort (arr, left, right) {
let len = arr.length
left = typeof left === 'undefined' ? 0 : left
right = typeof right === 'undefined' ? len - 1 : right
if (left > right) {
return
}
let temp = arr[left]
let i = left
let j = right
let t
while (i !== j) {
while (arr[j] >= temp && i < j) {
j--
}
while (arr[i] <= temp && i < j) {
i++
}
if (i < j) {
t = arr[i]
arr[i] = arr[j]
arr[j] = t
}
}
arr[left] = arr[i]
arr[i] = temp
quickSort(arr, left, i - 1)
quickSort(arr, i + 1, right)
return arr
}
console.log('快速排序--從小到大:',quickSort(arr))
複製程式碼
選擇排序
- 大概思路是找到最小的放在第一位,找到第二小的放在第二位,以此類推 演算法複雜度O(n^2)
var arr = [3, 5, 3, 5, 9, 7, 6]
console.log('原陣列:', arr)
function selectSort (arr) {
let len = arr.length
let minIndex
let temp
for (let i = 0; i < len; i++) {
minIndex = i
temp = arr[i]
for (let j = i + 1; j < len; j++) {
if (arr[j] < arr[minIndex]) {
minIndex = j
}
}
arr[i] = arr[minIndex]
arr[minIndex] = temp
}
return arr
}
console.log('選擇排序--從小到大:',selectSort(arr))
複製程式碼
插入排序
- 每次排一個陣列項,假設陣列的第一項已經排序
- 接著,把第二項與第一項進行對比,第二項是該插入到第一項之前還是之後
- 第三項是該插入到第一項之前還是第一項之後還是第三項
var arr = [3, 5, 3, 5, 9, 7, 6]
console.log('原陣列:', arr)
function insertSort (arr) {
let len = arr.length
let preIndex
for (let i = 1; i < len; i++) {
preIndex = i - 1
current = arr[i]
while (preIndex >= 0 && arr[preIndex] > current) {
arr[preIndex + 1] = arr[preIndex]
preIndex--
}
arr[preIndex + 1] = current
}
return arr
}
console.log('插入排序--從小到大:', insertSort(arr))
複製程式碼
歸併排序
Mozilla Firefox
使用歸併排序作為Array.prototype.sort的實現
chrome
使用快速排序的一個變體實現Array.prototype.sort
歸併排序
是一種分治演算法。本質上就是把一個原始陣列切分成較小的陣列,直到每個小陣列只有一個位置,接著把小陣列歸併成較大的陣列,在歸併過程中也會完成排序,直到最後只有一個排序完畢的大陣列
分治算
法的基本思想是將一個規模為N的問題分解為K個規模較小的子問題,這些子問題相互獨立且與原問題性質相同。求出子問題的解,就可得到原問題的解。
var arr = [3, 5, 3, 5, 9, 7, 6]
console.log('原陣列:', arr)
function mergeSort (arr) {
let len = arr.length
if (len < 2) {
return arr
}
let middle = Math.floor(len / 2)
let left = arr.slice(0, middle)
let right = arr.slice(middle)
return merge(mergeSort(left), mergeSort(right))
}
function merge (left, right) {
let result = []
while (left.length && right.length) {
if (left[0] < right[0]) {
result.push(left.shift())
} else {
result.push(right.shift())
}
}
result.push(...left)
result.push(...right)
return result
}
console.log('歸併排序--從小到大:', mergeSort(arr))
複製程式碼
各個排序演算法的效能比較