Array.sort 演算法原理(插入排序\快速排序in-place實現)
javascript Array.sort 原理實現
v8 引擎排序演算法原始碼(710 line)
js sort原理
十大經典演算法
js 提供了 sort 方法,方便對陣列進行排序,然而不同引擎對 js 的 sort 方法解析可能存在差異,本文基於 v8 引擎對排序 sort 的實現,分析其使用的 插入排序 和 快速排序 。
本文不致力於分析 v8 引擎原始碼,僅分析內部使用的兩種演算法
插入排序
下面是一張動圖演示。
基本思想
從左往右遍歷陣列,每次將遍歷的項插入到前面的已經排序好的有序陣列中,通過構建有序序列,對於未排序資料,在已排序序列中從後向前掃描,找到相應位置並插入。
演算法步驟
預設第一項已經排序
從陣列第二項開始遍歷,取出當前遍歷的新元素。
從當前項前一個往前查詢,如果查詢的項比新元素大,就向後移動一位
找到新元素在有序序列中的位置(查詢的項比新元素小,那新元素因為位於該元素後,也就是空出的空位中)放入新元素
繼續遍歷,重複2-4.
程式碼實現
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 思想的快速排序
演算法思想
快速排序的基本思想:通過一趟排序將待排記錄分隔成獨立的兩部分,其中一部分記錄的關鍵字均比另一部分的關鍵字小,則可分別對這兩部分記錄繼續進行排序,以達到整個序列有序。
演算法步驟
選基準:在資料結構中選擇一個元素作為基準(pivot)
劃分割槽:參照基準元素值的大小,劃分無序區,所有小於基準元素的資料放入一個區間,所有大於基準元素的資料放入另一區間,分割槽操作結束後,基準元素所處的位置就是最終排序後它應該所處的位置
遞迴:對初次劃分出來的兩個無序區間,遞迴呼叫第 1步和第 2步的演算法,直到所有無序區間都只剩下一個元素為止。
程式碼實現
這裡根據分割槽操作的實現方法分為下面兩種實現方式
挖坑把基準元素往中間夾逼方式
取出第一項作為基準元素(可理解為第一項空出坑位)
從後往前找小於基準元素的元素,填入坑位,空出後面的坑位。
從前往後找大於基準元素的元素,填入後方空位,空出前面坑位
重複2-3
當位置正好到中間時結束,把基準元素放入最後空出的空位
/**
- 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;
}
相關文章
- python實現氣泡排序、插入排序以及快速排序演算法Python排序演算法
- 排序演算法 - 快速插入排序和希爾排序排序演算法
- Java實現氣泡排序和插入排序演算法Java排序演算法
- .NET 排序 Array.Sort<T> 實現分析排序
- JavaScript實現:插入排序!!!JavaScript排序
- 實時插入排序演算法排序演算法
- 排序演算法-Java實現快速排序演算法排序演算法Java
- 排序演算法之快速排序的實現排序演算法
- 用JavaScript實現插入排序JavaScript排序
- 排序演算法__折半插入排序排序演算法
- go 實現氣泡排序和插入排序Go排序
- php插入排序,快速排序,歸併排序,堆排序PHP排序
- Python八大演算法的實現,插入排序、希爾排序、氣泡排序、快速排序、直接選擇排序、堆排序、歸併排序、基數排序。Python演算法排序
- php實現 氣泡排序,插入排序,選擇排序PHP排序
- 快速排序演算法C++實現排序演算法C++
- 希爾排序使用直接插入排序、二分插入排序的C++程式碼實現演算法排序C++演算法
- 用JS實現氣泡排序和插入排序JS排序
- 選擇排序和插入排序(C++實現)排序C++
- PHP 排序演算法之插入排序PHP排序演算法
- 排序演算法之折半插入排序排序演算法
- 陪玩平臺原始碼中的排序演算法,插入排序的實現原始碼排序演算法
- 排序演算法:插入排序演算法 PHP 版排序演算法PHP
- 常用演算法-插入排序演算法排序
- [資料結構與演算法]-排序演算法之插入排序(insertion sort)及其實現(Java)資料結構演算法排序Java
- 排序演算法__直接插入排序排序演算法
- 排序演算法:直接插入排序排序演算法
- 排序演算法入門之「插入排序」排序演算法
- 排序演算法(3)插入排序(Insertion Sort)排序演算法
- 排序演算法——直接插入排序排序演算法
- 排序演算法之「插入排序(Insertion Sort)」排序演算法
- 二十、快速排序演算法——JAVA實現(遞迴)排序演算法Java遞迴
- 利用java實現插入排序、歸併排序、快排和堆排序Java排序
- 排序演算法:二分插入排序排序演算法
- Java常見排序演算法之插入排序Java排序演算法
- Array.sort排序問題排序
- 畫江湖之演算法篇【排序演算法】插入排序演算法排序
- 畫江湖之演算法篇 [排序演算法] 插入排序演算法排序
- 排序演算法原理總結和Python實現排序演算法Python