feat: 添加快速排序

This commit is contained in:
LouisFonda 2024-02-26 21:33:49 +08:00
parent 86efe8d7b2
commit 7ff6821d63

150
sort/quick-sort.mjs Normal file
View File

@ -0,0 +1,150 @@
import { swap } from "../util/index.mjs"
/**
*
* @param {number[]} arr
*/
export function quickSort(arr) {
function QuickSort(arr, left, right) {
if (left < right) {
let index = partition(arr, left, right)
QuickSort(arr, left, index-1) // index是中心轴无需参与排序,若写成index会造成堆栈益处
QuickSort(arr, index+1, right)
}
}
QuickSort(arr,0, arr.length - 1)
return arr
}
/**
* @description 使用左右指针法来分数组
* @param {number[]} arr - 需要分治的函数
* @param {number} left - 开始的位置
* @param {number} right - 结束的位置
*/
function partition(arr, left, right) {
let pivot = arr[right] // 以right作为pivot
let pivotIndex = right
while (left < right) {
// left开始往右边找比pivot大的值
while (left < right && arr[left] <= pivot) {
left++
}
// right开始往左边找比pivot小的值
while (left < right && arr[right] >= pivot) {
right--
}
swap(arr, left, right)
}
swap(arr, left, pivotIndex)
return left
}
/**
*
* @param {number[]} arr - 需要快速排序的数组
*/
export function quickSort2(arr){
function QuickSort(arr, left, right) {
if (left < right) {
const pivot = partition2(arr, left, right)
QuickSort(arr,left,pivot -1)
QuickSort(arr, pivot+1, right)
}
}
QuickSort(arr,0, arr.length-1)
}
/**
* @description 使用挖坑法来分数组
* @param {number[]} arr - 需要分解的数组
* @param {number} left - 开始的位置
* @param {number} right - 结束的位置
*/
function partition2(arr, left, right){
let pivot = arr[right]
while(left < right) {
while(left<right && arr[left] <= pivot) {
left++
}
arr[right] = arr[left]
while(left<right && arr[right] >= pivot) {
right--
}
arr[left] = arr[right]
}
arr[left] = pivot
return left
}
/**
* @description 使用前后指针法分数组
* @param {number[]} arr - 需要排序的数组
*/
export function quickSort3(arr) {
function QuickSort(arr, left, right) {
if(left < right){
const pivot = partition4(arr, left, right)
QuickSort(arr, left, pivot-1)
QuickSort(arr, pivot+1, right)
}
}
QuickSort(arr, 0, arr.length -1)
}
/**
* @description 使用前后指针法
* @param {number[]} arr
* @param {number} left - 开始的位置
* @param {number} right - 结束的位置
*/
function partition3(arr, left, right){
let cur = left
let pre = left - 1
const pivot = arr[right] // 选取最后一个元素作为中枢
while(cur < right) {
if(arr[cur]< pivot) {
swap(arr, cur, ++pre)
}
cur++
}
/*
循环结束之后pre所处的元素之前都是小于pivot包含pre,右侧的元素都是大于或等于pivot的交换cur+1和pviot的值
*/
swap(arr, pre +1, right)
return pre + 1
}
/**
* @description 使用前后指针法(优化版)
* @param {number[]} arr
* @param {number} left - 开始的位置
* @param {number} right - 结束的位置
*/
function partition4(arr, left, right){
let cur = left
let pre = left - 1
const pivot = arr[right] // 选取最后一个元素作为中枢
while(cur < right) {
if(arr[cur] < pivot && ++pre != cur) {
swap(arr, pre, cur)
}
cur++
}
/*
循环结束之后pre所处的元素之前都是小于pivot包含pre,右侧的元素都是大于或等于pivot的交换cur+1和pviot的值
*/
swap(arr, pre +1, right)
return pre + 1
}
/*
1000000个数据测试下来发现partition partition3和4基本上无区别而且4只是减少了代码并没有减少执行
过程而且使代码变得难以理解不推荐使用推荐使用挖坑法来分数组
Function execution time: 464.513192 milliseconds
Function execution time: 418.692408 milliseconds
Function execution time: 467.99971000000005 milliseconds
*/