排序算法 - js
js交换两个值的三种方法
方式1:算术运算
function swap1(arr, i, j) {
let temp = arr[i];
arr[i] = arr[j];
arr[j] = temp
}
方式2:ES6解构
不需要第三方变量
function swap2(arr, i, j) {
[arr[j], arr[i]] = [arr[i], arr[j]]
}
方式3:数组的特性
function swap3(arr, i, j) {
const temp = [arr[i], arr[j]]
arr[i] = temp[1]
arr[j] = temp[0]
}
冒泡排序
实现思路
- 通过
相邻元素
比较和交换 - 使得每一趟遍历,最后的一个数数都是
最大
的 - 循环都能找到未排序的子数组,直到排序完成。
图解
bubbleSort
/**
* @Name:
* @author: liuk
* @Description: 冒泡排序
* @data: 2023/4/13
**/
// Bubble Sort
const bubbleSort = (arr) => {
const len = arr.length;
if (!len) return []
for (let i = 0; i < len; i++) {
for (let j = 0; j < len - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
swap(arr, j, j + 1)
}
}
}
return arr
}
参考视频
选择排序
实现思路
- 通过
已排序序列末尾元素
- 与
剩余元素
的最小值的比较和交换(索引
) - 使得每一趟遍历,已排序序列从小到大排序,直到排序完成。
剩余元素为遍历节点
之后
的全部元素
图解
selectionSort
/**
* @Name:
* @author: liuk
* @Description: 选择排序
* @data: 2023/4/13
**/
// Selection Sort
const selectionSort = (arr) => {
const len = arr.length
let minIndex;
if (!len) return []
for (let i = 0; i < len; i++) {
minIndex = i
for (let j = i; j < len; j++) {
if (arr[j] < arr[minIndex]) {
minIndex = j
}
}
swap(arr, minIndex, i)
}
return arr
}
参考视频
插入排序
实现思路
- 通过当前遍历节点的
值
- 与
已排序序列
的每个值
进行比较和交换(值
) - 使得每一趟遍历,遍历节点前都为已排序序列,直到排序完成。
图解
insertionSort
/**
* @Name:
* @author: liuk
* @Description: 插入排序
* @data: 2023/4/13
**/
// Insertion Sort
const insertionSort = (arr) => {
const len = arr.length;
let current;
if (!len) return [];
for (let i = 1; i < len; i++) {
current = arr[i]
let j = i - 1;//上一个元素
while (j >= 0 && current < arr[j]) {
arr[j + 1] = arr[j]
j--
}
arr[j + 1] = current
}
return arr
}
参考视频
希尔排序
实现思路
- 设置好
间隔序列
- 每个间隔序列代表一趟排序,根据对应的增量gap,分别进行直接
插入排序
- 最后gap为1时,进行最后一次直接插入排序,完成排序
图解
shellSort
/**
* @Name:
* @author: liuk
* @Description: 希尔排序
* @data: 2023/4/17
**/
// Shell Sort
const shellSort = (arr) => {
const len = arr.length;
let gap = Math.floor(len / 2); // 初始化步长
let current;
while (gap) { // 逐步缩小步数
for (let i = gap; i < len; i++) {
current = arr[i]
let j = i - gap;//上一个元素
while (j >= 0 && current < arr[j]) {
arr[j + gap] = arr[j]
j-=gap
}
arr[j + gap] = current
}
gap = Math.floor(gap / 2)
}
return arr
}
参考视频
归并排序(分治)
实现思路
- 把长度为n的输入序列分成两个长度为
n/2
的子序列; - 对这两个子序列分别采用
归并排序
; - 将两个排序好的子序列合并成一个最终的排序序列。
图解
mergeSort
/**
* @Name:
* @author: liuk
* @Description: 分治排序
* @data: 2023/4/17
**/
// Merge Sort
// 自上而下的递归
const mergeSort = (arr) => {
const len = arr.length;
if (len < 2) return arr
const mid = Math.floor(len / 2);// 分
const left = arr.slice(0, mid);// 治(占领)
const right = arr.slice(mid)
return merge(mergeSort(left), mergeSort(right))
function merge(left, right) {
const res = []
while (left.length && right.length) {
if (left[0] <= right[0]) {
res.push(left.shift())
} else {
res.push(right.shift())
}
}
while (left.length) {
res.push(left.shift())
}
while (right.length) {
res.push(right.shift())
}
return res
}
}
参考视频
快速排序
实现思路
- 选择一个中间元素为
基准点
- 把比基准点小的元素放在它的左边,比它大的放在右边
- 不断
递归
基数左右的序列,直到排序完成
图解
quickSort
/**
* @Name:
* @author: liuk
* @Description: 快速排序
* @data: 2023/4/18
**/
// Quick Sort
const quickSort = (arr) => {
const len = arr.length
if (len <= 1) {
return arr
}
const baseIndex = Math.floor(len / 2)
const base = arr.splice(baseIndex, 1)[0];//取出基准点的值
let left = [];
let right = [];
for (let i = 0; i < arr.length; i++) {// 这里的length时变化的
if (arr[i] < base) {
left.push(arr[i]);
} else {
right.push(arr[i]);
}
}
return quickSort(left).concat([base], quickSort(right));
}