在日常开发中,我们经常会碰到排序的需求,js 中数组的排序一般会想到 sort 方法。那有没有自己写过排序的方法呢?今天我们来自己写几个排序方法
给定一个数组: [5, 2, 4, 6, 1, 3],请你按照升序方式对它进行排序。
- 插入法:
我首先想到的是维护一份新数组,然后循环给定数组的每个元素,每次循环都去对比新数组中的元素,找到符合条件的位置,然后插入该位置。
function INSERTION_SORT(nums) {
const res = [nums[0]]
for (let i = 1, len = nums.length; i < len; i++) {
const temp = res[i - 1]
if (nums[i] < temp) {
const index = res.findIndex(num => nums[i] <= num)
res.splice(index, 0, nums[i])
} else {
res.push(nums[i])
}
}
return res
}
INSERTION_SORT([5, 2, 4, 6, 1, 3]) // [1, 2, 3, 4, 5, 6]
上面的解法用到了 findIndex 和 splice,那我在想能不能不用数组已有的方法去解这道题呢?
其实利用数组的位置可以很好地解出这道题目。
循环遍历给定数组的每个元素,维护一个当前位置的变量,用该变量去对比给定数组当前位置左边的每个元素,如果该变量小于左边一个元素,那么左边一个元素往右边移动一个位置,以此类推,直到该变量大于或等于左边的元素。最后在适当的位置插入该变量。
function INSERTION_SORT(nums) {
for (let i = 1, len = nums.length; i < len; i++) {
const temp = nums[i]
let j = i - 1
while (j > -1 && temp < nums[j]) {
nums[j + 1] = nums[j]
j -= 1
}
nums[j + 1] = temp
}
return nums
}
INSERTION_SORT([5, 2, 4, 6, 1, 3]) // [1, 2, 3, 4, 5, 6]
- 分治法
递归思想:
-
分解原问题为诺干子问题,这些子问题是原问题的规模较小的实例
-
解决这些子问题, 递归地求解各种子问题。然后,若子问题的规模足够小,则直接求解。
-
合并这些子问题的解为原问题的解
function MERGE_SORT(nums) {
if (nums.length <= 1) return nums
const midIndex = Math.floor(nums.length / 2)
const mid = nums.splice(midIndex, 1)
const left = []
const right = []
for (let i = 0, len = nums.length; i < len; i++) {
if (nums[i] < mid) {
left.push(nums[i])
} else {
right.push(nums[i])
}
}
return MERGE_SORT(left).concat(mid, MERGE_SORT(right))
}
MERGE_SORT([5, 2, 4, 6, 1, 3]) // [1, 2, 3, 4, 5, 6]
- 冒泡法
循环给定数组长度次,每次循环都从左往右取数组元素去对比该元素右边的元素,如果比右边元素大则交换两个元素的位置,否则继续下一元素去对比该元素右侧元素。(解释的比较绕口,不知道该如何组织语言)
function BUBBLE_SORT(nums) {
for (let i = 0; i < nums.length - 1; i++) {
for (let j = 0; j <BUBBLE_SORT nums.length - i - 1; j++) {
if (nums[j] > nums[j + 1]) {
const temp = nums[j]
nums[j] = nums[j + 1]
nums[j + 1] = temp
} else {
continue
}
}
}
return nums
}
BUBBLE_SORT([5, 2, 4, 6, 1, 3]) // [1, 2, 3, 4, 5, 6]
出个思考题:给定一个数组: [5, 2, 4, 6, 1, 3],请你分别使用插入法、分治法和冒泡法以降序方式对它进行排序。