冒泡排序就是重复“从序列右边开始比较相邻两个数字的大小,再根据结果交换两个数字 的位置”这一操作的算法。在这个过程中,数字会像泡泡一样,慢慢从右往左“浮”到序列的 顶端,所以这个算法才被称为“冒泡排序”。
function lineSort(list) {
for (let i = 0; i < list.length; i++) {
for (let j = i; j < list.length - 1; j++) {
if (list[j] > list[j + 1]) {
list[j] = list[j + 1] + list[j]
list[j + 1] = list[j] - list[j + 1]
list[j] = list[j] - list[j + 1]
}
}
}
}
比如: 3 1 5 2 4
已经出来了,尽管只需要遍历 10 次就可以,但是还是要遍历更多次
选择排序就是重复“从待排序的数据中寻找最小值,将其与序列最左边的数字进行交换” 这一操作的算法。在序列中寻找最小值时使用的是线性查找。
function selectSory(list) {
// 记录最小值
let minIdx
for (let i = 0; i < list.length; i++) {
minIdx = i
for (let j = i; j < list.length; j++) {
// 计算出最小值
if (list[j] < list[minIdx]) minIdx = j
}
if (i !== minIdx) {
list[i] = list[minIdx] + list[i]
list[minIdx] = list[i] - list[minIdx]
list[i] = list[i] - list[minIdx]
}
}
}
查找次数过多,和冒泡排序差不多
采用分治法 大于的去右边,小于的去左边
function quickSort(arr = []) {
if (arr.length <= 1) {
return arr
}
const [left, right] = [[], []]
const flag = arr.shift()
for (let i = 0; i < arr.length; i++) {
// 小于flag在左边
if (arr[i] < flag) {
left.push(arr[i])
} else {
// 大于等于在右边
right.push(arr[i])
}
}
// 递归再合并
return [...quickSort(left), flag, ...quickSort(right)]
}
以上是容易理解的版本,但是空间复杂度不够,可以采用原地交换的方式
function quickSort2(arr = [], low = 0, height = arr.length - 1) {
if (low === height) return arr
let left = low
let right = height
const pivot = arr[Math.floor((left + right) / 2)]
while (left < right) {
// 从左往右找到比中间值大的
while (arr[left] < pivot) {
left += 1
}
// 从右往左找到比中间值小的
while (arr[right] > pivot) {
right -= 1
}
// 找到两个可以调换的调换一下
;[arr[left], arr[right]] = [arr[right], arr[left]]
}
quickSort2(arr, low, left)
quickSort2(arr, low + 1, height)
}