這裏有動態圖示,效果很好:https://www.toptal.com/developers/sorting-algorithms/算法
冒泡排序,感受是最簡單的排序:數組
基本思路:每次把數組中最小的一個元素像氣泡同樣浮動、固定到最頂端:dom
從前向後遍歷數組,每次拿到一個元素,就執行一遍冒泡:ide
從數組末尾開始,到當前元素截止,從後向前遍歷,每次比較數組中相鄰的兩個元素,若是後者比較小,就把二者互換。函數
這樣通過第一次冒泡,能夠把最小的元素『浮』到數組的首位。第二次冒泡會把第二小的元素『浮』到數組的第二位。直到全部的元素都被『浮動』到正確的位置。測試
代碼極其簡單:ui
var BubbleSort = function (array) { var len = array.length; for(var i=0; i<len; ++i){ for(var j=len-1; j>i; --j){ if(array[j] < array[j-1]){ var temp = array[j]; array[j] = array[j-1]; array[j-1] = temp; } } } };
冒泡算法通常是把小的元素上浮。也能夠略微改動一下,變成大的元素下沉,實現上很類似。spa
插入排序:code
基本思路:假定已有一個有序數組(從小到大),則每次插入只要把新元素放到合適的位置就能夠了,爲了減小額外的內存佔用,能夠在原數組上作調整:blog
對數組從前向後遍歷,保證遍歷過的元素,都是從小到大排列:因此遍歷到新元素時,就要把新元素和已遍歷過的元素逐個比較,經過 swap 最後把新元素放到合適位置。
代碼實現:
var InsertSort = function (array) { //從前到後,每次指定一個數字,逐個比較它以前的每一個數字,插入到合適的位置 var len = array.length; for(var i=0; i<len; ++i){ for(var j=i; j>0; --j){ if(array[j] < array[j-1]){ var tmp = array[j - 1]; array[j - 1] = array[j]; array[j] = tmp; } else { break; } } } };
感受直接插入排序,中間也有用到冒泡的思路:遍歷到新元素時,用冒泡的方式,把新元素逐步浮動到正確的位置。
堆排序:
基本思路:構建一個最小堆,每次從堆中取出堆頂,也就是最小元素。而後調整最小堆,再次取出堆頂的最小元素。直到堆爲空。(用數組的方式構建優先隊列的方式,我後續寫一下)
爲了不申請額外的數組,此處直接在原數組中作了調整:每次取出的最小元素沒有放到新的數組,而是放到數組尾部,而後把剩下的數組元素調整成最小堆。
這樣當全部元素都被移動到數組尾端以後,也就完成了排序。
代碼實現:
//從小到大 var HeapSort = function (array) { var len = array.length; for(var k=len-1; k>=0; --k) { //build heap for (var i = k; i > 0; --i) { var pIndex = Math.floor((i - 1) / 2); if (array[i] < array[pIndex]) { var temp = array[pIndex]; array[pIndex] = array[i]; array[i] = temp; } } //remove smallest to array end array.push(array.shift()); } };
這裏用到了 JS 中的數組內建函數 shift、push。若是要更通用的方式,有這樣一個思路:第一次構建成最小堆後,不取出堆頂,而是直接用除堆頂之外的元素再次構建最小堆。僞碼以下:
for(i from 0 to array.lengh){
build heap using array[i]-array[length-1]
}
快排:
據論證是最快的排序方式,等後續我實現希爾排序後比較一下速度。。。
基本思路:每次指定一個元素,將數組中全部小於它的元素,放到數組最側,大於它的元素放到右側。而後以該元素爲界分紅兩個數組區間,對它們執行一樣的操做。
代碼實現:
var QuickSort = function (array, pre, last) { var keyIndex = last; var key = array[keyIndex]; var oldPre = pre; var oldLast = last; last -= 1; if(pre > last){ return; } while(pre <= last){ if(array[pre] <= key){ ++pre; } else if(array[last] >= key){ --last; } else { var temp = array[last]; array[last] = array[pre]; array[pre] = temp; } } array[keyIndex] = array[pre]; array[pre] = key; QuickSort(array, oldPre, pre-1); QuickSort(array, pre+1, oldLast); };
JS 中數組的 sort 函數,也是用的快排,可是我對比後發現 sort 函數比上面實現的快排要慢,基本上 sort 耗時是 QuickSort 的2-3倍。這中間具體多了些什麼?
用來對比的 sort 函數:
arrayCopy.sort(function (first, second) { if(first < second){ return -1; } return 1; });
附上個人測試代碼:
var testArray = []; var totalNum = 20000; for(var i=0; i<totalNum; ++i){ testArray.push(Math.random() * totalNum); // testArray.push(Math.ceil(Math.random() * totalNum)); } var arrayCopy = testArray.slice(); var now = Date.now(); InsertSort(arrayCopy); console.log("插入排序:" + (Date.now() - now)); arrayCopy = testArray.slice(); now = Date.now(); HeapSort(arrayCopy); console.log("堆排序:" + (Date.now() - now)); arrayCopy = testArray.slice(); now = Date.now(); BubbleSort(arrayCopy); console.log("冒泡排序:" + (Date.now() - now)); arrayCopy = testArray.slice(); now = Date.now(); arrayCopy.sort(function (first, second) { if(first < second){ return -1; } return 1; }); console.log("Array.sort 排序:" + (Date.now() - now)); arrayCopy = testArray.slice(); now = Date.now(); QuickSort(arrayCopy, 0, arrayCopy.length-1); console.log("快排:" + (Date.now() - now));
幾回測試的結果:
插入排序:217 堆排序:770 冒泡排序:740 Array.sort 排序:11 快排:6 插入排序:217 堆排序:771 冒泡排序:753 Array.sort 排序:10 快排:5 插入排序:218 堆排序:763 冒泡排序:735 Array.sort 排序:9 快排:4 插入排序:217 堆排序:762 冒泡排序:747 Array.sort 排序:11 快排:7 插入排序:222 堆排序:764 冒泡排序:759 Array.sort 排序:17 快排:7