排序演算法對比
n: 資料規模
k:“桶”的個數
In-place: 佔用常數記憶體,不佔用額外記憶體
Out-place: 佔用額外記憶體
1.氣泡排序(Bubble Sort)
動圖演示
JavaScript 程式碼
function bubbleSort(arr){
var low = 0;
var high = arr.length - 1;
while(low < high){
for(j = low; j < high; ++j){
//正向冒泡,找到最大者
if(arr[j] > arr[j+1]){
[arr[j],arr[j+1]] = [arr[j+1],arr[j]];
}
}
--high;
for(j = high; j > low; --j){
//反向冒泡,找到最小者
if(arr[j] < arr[j - 1]){
[arr[j],arr[j-1]] = [arr[j-1],arr[j]];
}
}
++low;
}
return arr;
}
var arr = [3,44,38,5,47,15,36,26,27,2,46,4,19,50,48];
console.log(bubbleSort(arr));
// [2, 3, 4, 5, 15, 19, 26, 27, 36, 38, 44, 46, 47, 48, 50]
複製程式碼
2.選擇排序(Selection Sort)
動圖演示
JavaScript 程式碼
function selectionSort(arr){
var len = arr.length;
var midIndex;
for(var i = 0; i < len - 1; i++){
midIndex = i;
for(var j = i + 1;j < len; j++){
if(arr[j] < arr[midIndex]){
midIndex = j;
}
}
[arr[i],arr[midIndex]] = [arr[midIndex],arr[i]];
}
return arr;
}
var arr = [3,44,38,5,47,15,36,26,27,2,46,4,19,50,48];
console.log(selectionSort(arr));
// [2, 3, 4, 5, 15, 19, 26, 27, 36, 38, 44, 46, 47, 48, 50]
複製程式碼
3.插入排序(Insertion Sort)
動圖演示
JavaScript 程式碼
function binaryInsertSort(array){
for(var i = 1; i < array.length; i++){
var key = array[i],
left = 0,
right = i-1;
while(left <= right){
var middle = parseInt((left + right) / 2);
if(key < array[middle]){
right = middle - 1;
}else{
left = middle + 1;
}
}
for(var j = i-1; j >= left; j--){
array[j+1] = array[j];
}
array[left] = key;
}
return array;
}
var arr=[3,44,38,5,47,15,36,26,27,2,46,4,19,50,48];
console.log(binaryInsertSort(arr));
// [2, 3, 4, 5, 15, 19, 26, 27, 36, 38, 44, 46, 47, 48, 50]
複製程式碼
4.希爾排序(Shell Sort)
圖示
JavaScript 程式碼
function shellSort(arr){
var len = arr.length,
temp,
gap =1;
while(gap < len/5){
gap = gap*5 + 1;
}
for(gap; gap > 0; gap = Math.floor(gap/5)){
for(var i = gap;i < len;i++){
temp = arr[i];
for(var j = i-gap;j>=0 && arr[j] > temp;j-=gap){
arr[j+gap] = arr[j];
}
arr[j+gap] = temp;
}
}
return arr;
}
var arr = [9,1,2,5,7,4,8,6,3,5];
console.log(shellSort(arr));
// [1, 2, 3, 4, 5, 5, 6, 7, 8, 9]
複製程式碼
5.歸併排序(Merge Sort)
動圖演示
JavaScript 程式碼
function mergeSort(arr){
var len = arr.length;
if(len <= 1){
return arr;
}
var middle = Math.floor(len / 2),
left = arr.slice(0,middle),
right = arr.slice(middle);
return merge(mergeSort(left),mergeSort(right));
}
function merge(left,right){
var result = [];
while(left.length && right.length){
if(left[0] <= right[0]){
result.push(left.shift());
}else{
result.push(right.shift());
}
}
return result.concat(left).concat(right);
}
var arr = [3,44,38,5,47,15,36,26,27,2,46,4,19,50,48];
console.log(mergeSort(arr));
// [2, 3, 4, 5, 15, 19, 26, 27, 36, 38, 44, 46, 47, 48, 50]
複製程式碼
6.快速排序(Quick Sort)
動圖演示
JavaScript 程式碼
function quickSort(arr){
if(arr.length<=1){
return arr;
}
var pivotIndex = Math.floor(arr.length/2);
var pivot = arr.splice(pivotIndex,1)[0];
var left = [];
var right = [];
for(var i=0;i<arr.length;i++){
if(arr[i] < pivot){
left.push(arr[i]);
}else{
right.push(arr[i]);
}
}
return quickSort(left).concat([pivot],quickSort(right));
}
var arr = [3,44,38,5,47,15,36,26,27,2,46,4,19,50,48];
console.log(quickSort(arr));
// [2, 3, 4, 5, 15, 19, 26, 27, 36, 38, 44, 46, 47, 48, 50]複製程式碼
7.堆排序(Heap Sort)
動圖演示
JavaScript 程式碼
var len;
function buildMaxHeap(arr){
len = arr.length;
// 建立大頂堆
for(var i = Math.floor(len/2);i >= 0; i--){
heapify(arr,i);
}
}
function heapify(arr,i){
var left = 2 * i + 1,
right = 2 * i + 2,
largest = i; // i 為該子樹的根節點
if(left < len && arr[left] > arr[largest]){
largest = left;
}
if(right < len && arr[right] > arr[largest]){
largest = right;
}
if(largest != i){ // 即上面的 if 語句有一個執行了
[arr[i],arr[largest]] = [arr[largest],arr[i]]; // 交換最大的為父節點
heapify(arr,largest); // 作為根時,子節點可能比他大,因此要繼續調整
}
}
function heapSort(arr){
buildMaxHeap(arr);
for(var i = len - 1; i > 0 ; i--){
[arr[0],arr[i]] = [arr[i],arr[0]];
len--;
heapify(arr,0);
}
return arr;
}
var arr=[91,50,96,13,35,65,46,65,10,30,20,31,77,81,22];
console.log(heapSort(arr,4)); // [10, 13, 20, 22, 30, 31, 35, 46, 50, 65, 65, 77, 81, 91, 96]
複製程式碼
8.計數排序 (Counting Sort)
動圖演示
JavaScript 程式碼
function countingSort(array){
var index = 0, tempArr = [];
console.time('計數排序耗時:');
for(var i = 0; i < array.length; i++){
tempArr[array[i]] = tempArr[array[i]] ? tempArr[array[i]] + 1 : 1 ;
}
for(var j = 0;j <= tempArr.length;j++){
while(tempArr[j]>0){
array[index++] = j;
tempArr[j]--;
}
}
console.timeEnd('計數排序耗時:');
return array;
}
var arr=[7,12,12,12,56,23,19,33,35,42,2,8,22,39,26,17];
console.log(countingSort(arr,4));
// [2, 7, 8, 12, 12, 12, 17, 19, 22, 23, 26, 33, 35, 39, 42, 56]
複製程式碼
9.桶排序(Bucket Sort)
動圖演示
JavaScript 程式碼
/*
桶排序:
array : 待排序陣列
bucketSize : 桶的數目
*/
function bucketSort(array, bucketSize) {
if (array.length <= 1) {
return array;
}
var buckets = [], result = [], min = max = array[0], space, n = 0;
bucketSize = bucketSize || 5;
console.time('桶排序耗時');
for (var i = 1; i < arr.length; i++) {
min = min <= array[i] ? min : array[i];
max = max >= array[i] ? max : array[i];
}
space = (max - min + 1) / bucketSize;
for (var j = 0; j < array.length; j++) {
var index = Math.floor((array[j] - min) / space);
if (buckets[index]) {
// 非空桶,進行插入排序
var k = buckets[index].length - 1;
while (k >= 0 && buckets[index][k] > array[j]) {
buckets[index][k + 1] = buckets[index][k];
k--;
}
buckets[index][k + 1] = array[j];
} else {
// 空桶,初始化
buckets[index] = [];
buckets[index].push(array[j]);
}
}
while (n < bucketSize) {
result = result.concat(buckets[n]);
n++;
}
console.timeEnd('桶排序耗時');
return result;
}
var arr=[7,12,56,23,19,33,35,42,2,8,22,39,26,17];
console.log(bucketSort(arr,4)); // [2, 7, 8, 12, 17, 19, 22, 23, 26, 33, 35, 39, 42, 56]
複製程式碼
10.基數排序(Radix Sort)
- MSD 從高位開始進行排序
- LSD 從低位開始進行排序
- 最佳情況:T(n) = O(n * k)
- 最差情況:T(n) = O(n * k)
- 平均情況:T(n) = O(n * k)
JavaScript 程式碼
/*
基數排序:
arr : 待排序陣列
maxDigit : 陣列中的最大數的位數
*/
function radixSort(arr,maxDigit){
var mod = 10;
var dev = 1;
var counter = [];
console.time('基數排序耗時:');
for(var i = 0; i < maxDigit; i++ ,dev *= 10,mod *= 10){
for(var j = 0;j < arr.length; j++){
var bucket = parseInt((arr[j]%mod)/dev);
if(counter[bucket] == null){
counter[bucket] =[];
}
counter[bucket].push(arr[j]);
}
var pos = 0;
for(var j = 0;j < counter.length; j++){
var value = null;
if(counter[j]!=null){
while((value = counter[j].shift()) != null){
arr[pos++] = value;
}
}
}
}
console.timeEnd('基數排序耗時:');
return arr;
}
var arr = [3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48];
console.log(radixSort(arr,2));
// [2, 3, 4, 5, 15, 19, 26, 27, 36, 38, 44, 46, 47, 48, 50]
複製程式碼
圖片和程式碼幾乎全部來自網路,自己總結一下方便今後複習。