概述
最容易想到的排序,从旧数组中找到一个最小的,不断放入新的数组中。(不使用数组的slice等方法是因为会使效率变得更慢)
let arr = [3, 5, 6, 7, 1, 2, 4, 9, 8]
function getMin(arr) {
if (arr == null || arr.length == 0) return
let index = -1
for (let i = 0; i < arr.length; i++) {
if (arr[i] != null && arr[i] < arr[index] || arr[i] != null && index == -1) {
index = i
}
}
let result = arr[index]
arr[index] = null
return result
}
function sort(arr) {
let newArr = new Array(arr.length)
for (let i = 0; i < newArr.length; i++) {
newArr[i] = getMin(arr)
}
return newArr
}
console.log(sort(arr))
冒泡排序
任何排序的本质都是比较和交换。
let arr = [3, 5, 6, 7, 1, 2, 4, 9, 8]
function compare(b, a) {
return b > a;
}
function exchange(arr, a, b) {
let temp = arr[a]
arr[a] = arr[b]
arr[b] = temp
}
function sort(arr) {
for (let j = 0; j < arr.length - 1; j++) {
// arr.length - 1 - i 单轮比较 索引到倒数第二个数
// 外层循环影响内层循环 每次少比较 i 次(末尾的数不断确定)
for (let i = 0; i < arr.length - 1 - i; i++) {
if (compare(arr[i], arr[i + 1])) {
exchange(arr, i, i + 1)
}
}
}
}
sort(arr)
console.log(arr)
详解可见:【排序算法】史上最通俗易懂的【冒泡排序】详解-CSDN博客
选择排序
任何一种排序算法,都没有优劣之分,只有适不适合的场景。
越混乱越适合快速排序,越有序越适合冒泡排序。选择排序在性能上居中。
let arr = [3, 5, 6, 7, 1, 2, 4, 9, 8]
function compare(b, a) {
return b > a;
}
function exchange(arr, a, b) {
let temp = arr[a]
arr[a] = arr[b]
arr[b] = temp
}
function sort(arr) {
for (let i = 0; i < arr.length - 1; i++) {
let minIndex = i
for (let j = i; j < arr.length; j++) {
if (compare(arr[minIndex], arr[j])) {
minIndex = j
}
}
if (minIndex != i) {
exchange(arr, i, minIndex)
}
}
}
sort(arr)
console.log(arr)
详解见:排序算法--选择排序--详解及代码_选择排序法-CSDN博客
快速排序(浪费性能但精简版)
以下版本浪费了性能,但是极大降低了理解难度。
思路分析:选一个中间值,然后遍历其他值,比中间值大的放一边,比中间值小的放另一边。再分别递归左右数组。
let arr = [3, 5, 6, 7, 1, 2, 4, 9, 8]
function quickSort(arr) {
if (arr == null || arr.length == 0) return []
let middle = arr[0]
let left = []
let right = []
for (let i = 1; i < arr.length; i++) {
if (arr[i] < middle) {
left.push(arr[i])
} else {
right.push(arr[i])
}
}
left = quickSort(left)
right = quickSort(right)
left.push(middle)
return left.concat(right)
}
console.log(quickSort(arr))
快速排序(完整版)
整体思路:
随机找一个基准值,开始双指针遍历,分别在左指针找到一个大于基准值的数,在右指针找到一个小于基准值的数,并将他们交换位置。为左右指针的一次循环。
然后将左指针和基准值交换(这里注意判断相等的情况),此时由基准值分割了数组,一边小的,一边大的。
随后递归即可完成排序。
function swap(arr, i, j) {
let temp = arr[i]
arr[i] = arr[j]
arr[j] = temp
}
function quickSort(s, l, r) {
if (l < r) {
let i = l, j = r, x = s[l];
while (i < j) {
while (i < j && s[j] > x) {
j--;
}
while (i < j && s[i] <= x) {
i++;
}
swap(s, i, j)
}
swap(s, l, i)
quickSort(s, l, i - 1);
quickSort(s, i + 1, r);
}
}
// 使用示例
let arr = [1, 4, 3, 5, 2];
quickSort(arr, 0, arr.length - 1);
console.log(arr); // 输出 [1, 2, 3, 4, 5]
s[i] <= x 这里的 = 不能丢,否则边界判断出问题