JavaScript常見排序演算法
準備工作
常見排序演算法有 :①選擇排序; ②氣泡排序; ③插入排序; ④快速排序;
⑤歸併排序; ⑥計數排序; ⑦希爾排序; ⑧堆排序;(粗體字為不穩定排序)
在開始排序演算法之前,我們先建立一個待排序和搜尋的陣列
let arr = [
10,
22,
10,
1,
2,
5,
3,
89,
3,
7777,
1111,
2222,
0,
88884,
222,
111,
55,
44,
33,
22,
11
];
何為氣泡排序(演算法複雜度O(n2),穩定)
氣泡排序(Bubble Sort),是一種電腦科學領域的較簡單的排序演算法。它重複
氣泡排序實現
let bubbleSort = function(arr) {
for (let i = 0; i < arr.length; i++) {//總的遍歷次數
for (let j = 0; j < arr. length - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]]; //es6解構賦值
}
}
}
console.log(arr);
return arr;
};
bubbleSort(arr);
何為選擇排序
選擇排序(Selection sort)是一種簡單直觀的排序演算法。它的工作原理是每一次從待排序的資料元素中選出****最小(或最大)的一個元素,存放在序列的起始位置,然後,再從剩餘未排序元素中繼續尋找最小
選擇排序實現(演算法複雜度O(n2),不穩定)
function selectionSort(arr) {
let length = arr.length;
for (let i = 0; i < length - 1; i++) {
let min_index = i; //假設該項為最小值
for (let j = i + 1; j < length; j++) {
if (arr[j] < arr[min_index]) {
//如果找到比i更小的就改變min_index
min_index = j;
}
}
[arr[i], arr[min_index]] = [arr[min_index], arr[i]];
}
console.log(arr);
return arr;
}
selectionSort(arr);
何為插入排序(演算法複雜度 最好:O(n)最壞:O(n2),穩定)
有一個已經有序的資料序列,要求在這個已經排好的資料序列中插入一個數,但要求插入後此資料序列仍然有序,這個時候就要用到一種新的排序方法——插入排序法,插入排序的基本操作就是將一個數據插入到已經排好序的有序資料中,從而得到一個新的、個數加一的有序資料,演算法適用於少量資料的排序,時間複雜度為O(n^2)。是穩定的排序方法。插入演算法把要排序的陣列分成兩部分:第一部分包含了這個陣列的所有元素,但將最後一個元素除外(讓陣列多一個空間才有插入的位置),而第二部分就只包含這一個元素(即待插入元素)。在第一部分排序完成後,再將這個最後元素插入到已排好序的第一部分中。
插入排序的基本思想是:每步將一個待排序的記錄,按其關鍵碼值的大小插入前面已經排序的檔案中適當位置上,直到全部插入完為止。
插入排序實現
function insertionSort(arr) {
let length = arr.length;
let j, temp;
for (let i = 0; i < length; i++) {
j = i;
temp = arr[j]; //待插入的項
while (j > 0 && arr[j - 1] > temp) {
//如果已排序的陣列中存在比待插項大的,則交換
arr[j] = arr[j - 1];
j--;
}
arr[j] = temp;
}
console.log(arr);
}
何為歸併演算法(演算法複雜度O(nlogn),穩定)
歸併排序(MERGE-SORT)是建立在歸併操作上的一種有效的排序演算法,該演算法是採用分治法(Divide and Conquer)的一個非常典型的應用。將已有序的子序列合併,得到完全有序的序列;即先使每個子序列有序,再使子序列段間有序。若將兩個有序表合併成一個有序表,稱為二路歸併。
歸併演算法實現
//治
function merge(left, right) {
//傳進來的left,right都已排好序
let result = []; //歸併後的結果
let j = 0,
i = 0; //left和right的指標
while (i < left.length && j < right.length) {
if (left[i] < right[j]) {
//如果當前倆指標left[i]較小則push到result
result.push(left[i]);
i++;
} else {
result.push(right[j]);
j++;
}
}
if (i < left.length) {
//如果j指標先到頭
result = result.concat(left.slice(i, left.length));
}
if (j < right.length) { //如果i指標先到頭
result = result.concat(right.slice(j, left.length));
}
console.log(result);
return result;
}
function mergeSort(arr) {
//分
let length = arr.length;
let middle = Math.floor(length / 2);
let left = arr.slice(0, middle);
let right = arr.slice(middle, length);
if (length === 1) {
//遞迴結束條件
return arr;
}
return merge(mergeSort(left), mergeSort(right));
}
mergeSort(arr);
何為快速排序(演算法複雜度O(nlogn),不穩定)
快速排序(Quicksort)是對氣泡排序的一種改進。
快速排序由C. A. R. Hoare在1962年提出。它的基本思想是:通過一趟排序將要排序的資料分割成獨立的兩部分,其中一部分的所有資料都比另外一部分的所有資料都要小,然後再按此方法對這兩部分資料分別進行快速排序,整個排序過程可以遞迴進行,以此達到整個資料變成有序序列。
快速排序實現
//分的同時治
function partition(arr, left, right) {
let pivot = arr[Math.floor((left + right) / 2)]; //選擇基準值
let i = left,
j = right; //左右指標
while (i <= j) {
//將i指標移動到arr[i]>=pivot的位置
while (arr[i] < pivot) {
i++;
}
//將j指標移動到arr[j]<=pivot的位置
while (arr[j] > pivot) {
j--;
}
if (i <= j) {
//交換arr[i],arr[j]
[arr[i], arr[j]] = [arr[j], arr[i]];
j--;
i++;
}
}
return i; //返回左指標
}
function quick(arr, left, right) {
let index;
if (arr.length > 1) {
index = partition(arr, left, right); //分且治
//如果index左邊的length>2,遞迴呼叫
if (left < index - 1) {
quick(arr, left, index - 1);
}
//如果index右邊的length>2,遞迴呼叫
if (right>index) {
quick(arr, index, right);
}
}
}
quick(arr, 0, arr.length - 1);
console.log(arr);