十大經典排序算法的JS版
阿新 • • 發佈:2019-04-16
shellSort strong 使用 number ont 數組長度 實現 可能 width
排序對比:
排序對比.jpg排序分類:
排序分類.jpg- 冒泡排序(Bubble Sort)
冒泡排序是一種簡單的排序算法,它重復的走訪要排序的數列,一次比較兩個元素,如果它們的順序錯誤就把它們交換過來,走訪數列的工作是重復的進行直到沒有再需要交換,也就是說數列已經排序完成,這個算法的名字的由來是因為越小的元素會精油交換慢慢浮到數列的頂端。
1.初級版
function bubbleSort(array) {
const length = array.length;
for (let i = 0; i < length; i++) {
for (let j = 0; j < length - 1 - i; j++) {
if (array[j] > array[j + 1]) {
let temp = array[j + 1];
array[j + 1] = array[j];
array[j] = temp;
}
}
}
return array;
}
2.改進版
設置一個標誌性變量pos,用於記錄每趟排序中最後一次進行交換的位置,由於pos位置之後的記錄均已交換到位,故在進行下一趟排序是只要掃描到pos位置即可
function bubbleSort(array) {
let i = array.length - 1;
while (i > 0) {
let pos = 0;
for (let j = 0; j < i; j++) {
if (array[j] > array[j + 1]) {
pos = j;
let temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
}
}
i = pos;
}
return array;
}
3.加強版
傳統冒泡排序中的每一趟排序操作只能找到一個最大值或者最小值,我們考慮利用在每趟排序中進行正向和反向兩遍冒泡的方法一可以得到裏那個個最終值(最大及最小),從而使排序趟數至少減少一半
function bubbleSort(array) {
let low = 0;
let high = array.length - 1;
while (low < high) {
for (let j = low; j < high; j++) {
if (array[j] > array[j + 1]) {
const temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
}
}
--high;
}
return array;
}
- 選擇排序(Selection Sort)
表現最穩定的排序算法之一,因為無論什麽數據進去都是O(n2)的時間復雜度......所以用它的時候數據規模越小越好,唯一的好處就是不占用額外的內存空間,理論上將,選擇排序可能也是平時排序一般人想到的最多的排序方法之一
function selectionSort(array) {
let length = array.length;
for (let i = 0; i < length - 1; i++) {
let minIndex = i;
for (let j = i + 1; j < length; j++) {
if (array[j] < array[minIndex]) {
minIndex = j;
}
}
let temp = array[i];
array[i] = array[minIndex];
array[minIndex] = temp;
}
return array;
}
- 插入排序(Insertion Sort)
插入排序的代碼實現雖然沒有冒泡排序和選擇排序那麽簡單粗暴,但是它的原理卻是最好理解的,它的工作原理是通過構建有序序列,對未排序的數據,在已排序的序列中從後向前掃描,找到相應的位置並插入
1.初級版—從後往前插
function insertionSort(array) {
for (let i = 1; i < array.length; i++) {
let key = array[i];
let j = i - 1;
while (j >= 0 && array[j] > key) {
array[j + 1] = array[j];
j--;
}
array[j + 1] = key;
}
return array;
}
2.升級版—基於二分法
function insertionSort(array) {
for (let i = 1; i < array.length; i++) {
let key = array[i], left = 0, right = i - 1;
while (left <= right) {
let middle = parseInt((left + right) / 2);
if (key < array[middle]) {
right = middle - 1;
} else {
left = middle + 1;
}
}
for (let j = i - 1; j >= left; j--) {
array[j + 1] = array[j];
}
array[left] = key;
}
return array;
}
- 希爾排序(Shell Sort)
希爾排序的核心在於間隔序列的設定。既可以提前設定好間隔序列,也可以動態定義間隔序列。
function shellSort(array) {
let gap = 1;
while (gap < array.length / 5) {
gap = gap * 5 + 1;
}
for (gap; gap > 0; parseInt(gap / 5)) {
for (let i = gap; i < array.length; i++) {
const temp = array[i];
for (let j = i - gap; j >= 0 && array[j] > temp; j -= gap) {
array[j + gap] = array[j];
}
array[j + gap] = temp;
}
}
return array;
}
- 歸並排序(Merge Sort)
歸並排序是建立在歸並操作的一種有效的排序算法,該算法是采用分治法的一個非常典型的應用。歸並排序是一種穩定的排序算法,將已有序的子序列合並,等到一個完全有序的序列,即先使每個子序列有序,再使子序列段有序,若將兩個有序表合並成一個有序表,稱作2路合並
function mergeSort(array) {
if (array.length < 2) {
return array;
}
const middle = parseInt(array.length / 2);
const left = array.slice(0, middle);
const right = array.slice(middle);
return merge(test_run(left), test_run(right));
}
function merge(left, right) {
const newArray = [];
while (left.length && right.length) {
if (left[0] <= right[0]) {
newArray.push(left.shift());
} else {
newArray.push(right.shift());
}
}
while (left.length) {
newArray.push(left.shift());
}
while (right.length) {
newArray.push(right.shift());
}
return newArray;
}
- 快速排序(Quick Sort)
快速排序的基本思想是:通過一趟排序將待排記錄分割成獨立的兩部分,其中一部分記錄關鍵字均比另一部分的關鍵字小,則可分別對這兩部分記錄繼續進行排序,以達到整個序列有序
方法一
const quickSort = function (array) {
if (array.length <= 1) {
return array;
}
const pivotIndex = parseInt(array.length / 2);
const pivot = Number(array.splice(pivotIndex, 1));
const left = []; const right = [];
for (let i = 0; i < array.length; i++) {
if (array[i] < pivot) {
left.push(array[i]);
} else {
right.push(array[i]);
}
}
return quickSort(left).concat([pivot], quickSort(right));
};
方法二
其中 left = 0; right = array.length-1
function quickSort(array, left, right) {
if (left < right) {
let x = array[right], i = left - 1;
for (let j = left; j <= right; j++) {
if (array[j] <= x) {
i++;
const temp = array[i];
array[i] = array[j];
array[j] = temp;
}
}
quickSort(array, left, i - 1);
quickSort(array, i + 1, right);
}
return array;
}
- 堆排序(Heap Sort)
是指利用堆這種數據結構所涉及的一種排序算法,堆積是一個近似完全二叉樹的結構,並滿足堆積的性質:即子節點的鍵值或索引總是小於(或大於)它的父節點
function heapSort(array) {
let length = array.length;
for (let i = parseInt(array.length / 2) - 1; i >= 0; i--) {
heap(array, i, length);
}
for (let j = length - 1; j >= 1; j--) {
const temp = array[0];
array[0] = array[j];
array[j] = temp;
heap(array, 0, --length);
}
return array;
}
function heap(array, x, length) {
let l = 2 * x + 1, r = 2 * x + 2, largest = x;
if (l < length && array[l] > array[largest]) {
largest = l;
}
if (r < length && array[r] > array[largest]) {
largest = r;
}
if (largest != x) {
const temp = array[x];
array[x] = array[largest];
array[largest] = temp;
heap(array, largest, length);
}
}
- 計數排序(Counting Sort)
計數排序的核心在於輸入的數據值轉換為鍵存儲在額外開辟的數組空間中,作為一種限行時間非要咋地的排序,計數排序要求輸入的數據必須是由確定範圍的整數。
計數排序是一種很穩定的排序算法,需要用到一個額外的數組C,其中第i個元素是待排序數組A中值等於i的元素的個數,然後根據數字C將A中的元素排到正確的位置上個,它只能對數組進行排序
function countSort(array) {
const newArray = [], C = [];
let min = array[0];
let max = array[0];
for (let i = 0; i < array.length; i++) {
if (min >= array[i]) {
min = array[i];
}
if (max <= array[i]) {
max = array[i];
}
if (C[array[i]] = C[array[i]]) {
C[array[i]]++;
} else {
C[array[i]] = 1;
}
}
for (let j = min; j < max; j++) {
C[j + 1] = (C[j + 1] || 0) + (C[j] || 0);
}
for (let k = array.length - 1; k >= 0; k--) {
newArray[C[array[k]] - 1] = array[k];
C[array[k]]--;
}
return newArray;
}
- 桶排序(Bucket Sort)
桶排序是計數排序的升級版。它利用了函數的映射關系,高效與否的關鍵就在於這個映射函數的確定。桶排序 (Bucket sort)的工作的原理:假設輸入數據服從均勻分布,將數據分到有限數量的桶裏,每個桶再分別排序(有可能再使用別的排序算法或是以遞歸方式繼續使用桶排序進行排序
-
基數排序(Radix Sort)
基數排序也是非比較的排序算法,對每一位進行排序,從最低位開始排序,復雜度為O(kn),為數組長度,k為數組中的數的最大的位數;基數排序是按照低位先排序,然後收集;再按照高位排序,然後再收集;依次類推,直到最高位。有時候有些屬性是有優先級順序的,先按低優先級排序,再按高優先級排序。最後的次序就是高優先級高的在前,高優先級相同的低優先級高的在前。基數排序基於分別排序,分別收集,所以是穩定的。
原文:https://www.jianshu.com/p/96f5c19e13df
十大經典排序算法的JS版