十大排序演算法

paynmind發表於2020-10-06

排序演算法對比

十大排序演算法

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 從低位開始進行排序
LSD 基數排序 動圖

十大排序演算法

  • 最佳情況:T(n) = O(n * k)
  • 最差情況:T(n) = O(n * k)
  • 平均情況:T(n) = O(n * k)
說明: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]
複製程式碼


圖片和程式碼幾乎全部來自網路,自己總結一下方便今後複習。


相關文章