js 提供了 sort
方法,方便對數組進行排序,然而不一樣引擎對 js
的 sort
方法解析可能存在差別,本文基於 v8
引擎對排序 sort
的實現,分析其使用的 插入排序
和 快速排序
。javascript
本文不致力於分析 v8 引擎源碼,僅分析內部使用的兩種算法html
下面是一張動圖演示。java
從左往右遍歷數組,每次將遍歷的項插入到前面的已經排序好的有序數組中,經過構建有序序列,對於未排序數據,在已排序序列中從後向前掃描,找到相應位置並插入。git
function InsertionSort(arr, from = 0, to = arr.length) {
// 從數組第二項遍歷
for (var i = from + 1; i < to; i++) {
// 取出新元素
var element = arr[i];
// 重新元素位置向前查找
for (var j = i - 1; j >= from; j--) {
// 緩存查找的項
var tmp = arr[j];
// 計算是不是須要插入的位置
// 此處可修改插入邏輯,正序倒序
var order = tmp - element;
if (order > 0) {
// 不是插入位置,查找項後移
arr[j + 1] = tmp;
} else {
// 是插入位置,退出循環,插入元素
break;
}
}
// 退出循環插入元素
arr[j + 1] = element;
}
};
複製代碼
快速排序,又稱劃分交換排序。以分治法爲策略實現的快速排序算法。這裏主要實現 in-place 思想的快速排序github
快速排序的基本思想:經過一趟排序將待排記錄分隔成獨立的兩部分,其中一部分記錄的關鍵字均比另外一部分的關鍵字小,則可分別對這兩部分記錄繼續進行排序,以達到整個序列有序。算法
這裏根據分區操做的實現方法分爲下面兩種實現方式數組
/** * https://www.runoob.com/w3cnote/quick-sort.html * 快速排序算法 * @param {*} arr * @param {*} left * @param {*} right */
function quickSort(arr, left = 0, right = arr.length - 1) {
function partition(arr, left, right) {
const povit = arr[left];
while (left < right) {
while (left < right && arr[right] >= povit) {
right--;
}
if (left < right) {
arr[left] = arr[right]; //將s[right]填到s[left]中,s[right]就造成了一個新的坑
left++;
}
while (left < right && arr[left] < povit) {
left++;
}
if (left < right) {
arr[right] = arr[left]; //將s[right]填到s[left]中,s[right]就造成了一個新的坑
right--;
}
}
arr[left] = povit;
return left;
}
if (left < right) {
// 分治
const partitionIndex = partition(arr, left, right);
quickSort(arr, left, partitionIndex);
quickSort(arr, partitionIndex + 1, right);
}
return arr;
}
複製代碼
function quickSort1(arr) {
// 交換
function swap(arr, a, b) {
[arr[a],arr[b]] = [arr[b],arr[a]]
}
// 分區
function partition(arr, left, right) {
/** * 開始時不知最終pivot的存放位置,能夠先將pivot交換到後面去 * 這裏直接定義最右邊的元素爲基準 */
const pivot = arr[right];
/** * 存放小於pivot的元素時,是緊挨着上一元素的,不然空隙裏存放的多是大於pivot的元素, * 故聲明一個storeIndex變量,並初始化爲left來依次緊挨着存放小於pivot的元素。 */
let storeIndex = left;
for (let i = left; i < right; i++) {
if (arr[i] < pivot) {
/** * 遍歷數組,找到小於的pivot的元素,(大於pivot的元素會跳過) * 將循環i次時獲得的元素,經過swap交換放到storeIndex處, * 並對storeIndex遞增1,表示下一個可能要交換的位置 */
swap(arr, storeIndex, i);
storeIndex++;
}
}
// 最後: 將pivot交換到storeIndex處,基準元素放置到最終正確位置上
swap(arr, right, storeIndex);
return storeIndex;
}
function sort(arr, left, right) {
if (left > right) return;
const storeIndex = partition(arr, left, right);
sort(arr, left, storeIndex - 1);
sort(arr, storeIndex + 1, right);
}
sort(arr, 0, arr.length - 1);
return arr;
}
複製代碼