冒泡排序
冒泡排序是升序排列 核心思想:让数组的当前项和后一项进行比较,如果当前项比后一项大,就交换位置。 时间复杂度:O(n^2) 空间复杂度:O(1)
const arr = [12, 8, 24, 16, 1, 34, 23, 12, 54]
const bubble = (arr) => {
for (let i = 0; i < arr.length - 1; i++) {
for (let j = 0; j < arr.length - 1 - i; j++) {
if (arr[j] > arr[j + 1]) {
[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]]
}
}
}
return arr
}
console.log(bubble(arr))
选择排序
核心思想:选择第一个索引的位置,和后面的元素依次比较,如果后面的元素小于第一个元素,记录索引,此轮结束时交换位置,经过一轮比较后可以选出此轮的最小值。 时间复杂度:O(n^2) 空间复杂度:O(1)
const selectSore = (arr) => {
let min
for (let i = 0; i < arr.length - 1; i++) {
min = i
for (let j = i + 1; j < arr.length; j++) {
if (arr[min] > arr[j]) {
min = j
}
}
[arr[i], arr[min]] = [arr[min], arr[i]]
}
return arr
}
插入排序
插入排序是简单排序(冒泡、选择、插入),插入排序是效率最高的。
核心思想:
- 从第一个元素开始,这个元素可以认为已经被排序(循环的下表从1开始,0默认已被排序)
- 取出下一个元素,在已经排序的元素中,从后向前遍历
- 如果这个元素大于新的元素,就把这个元素移到下一个位置
- 重复上一个步骤,直到已经排序的元素小于或等于新元素的位置
- 将新元素插入到这个位置以后,重复上面的步骤
时间复杂度:O(n^2) 空间复杂度:O(1)
const insertSort = (arr) => {
const handle = []
handle.push(arr[0])
for (let i = 1; i < arr.length; i++) {
let A = arr[i]
for (let j = handle.length - 1; j >= 0; j--) {
let B = handle[j]
if (A > B) {
handle.splice(j + 1, 0, A)
break
}
if(j === 0){
handle.unshift(A)
}
}
}
return handle
}
const insertSortTwo = (arr) => {
let temp
for (let i = 0; i < arr.length; i++) {
let j = i
temp = arr[i]
while (j > 0 && arr[j - 1] > temp) {
arr[j] = arr[j - 1]
j--
}
arr[j] = temp
}
return arr
}
希尔排序
希尔排序本质是一种插入排序,但是他对数组进行了等间隔的分组处理,在每一组中做插入排序。 核心思想:按一定的间隔对数组进行分组,在每一个分组中进行插入排序,把较小的值放到靠前的位置;随后逐次缩小间隔,继续进行插入排序,直到间隔为1再做插入排序后结束。 时间复杂度:O(nlogn)
const shellSort = (arr) => {
let gap = Math.floor(arr.length - 1)
while (gap > 0) {
for (let i = 0; i < arr.length; i++) {
let j = i
temp = arr[i]
while (j > 0 && arr[j - 1] > temp) {
arr[j] = arr[j - 1]
j--
}
arr[j] = temp
}
gap = Math.floor(gap / 2)
}
return arr
}
归并排序
拆分和归并 核心思想:把数组分成前后两部分,然后分别进行排序,再将两部分合并在一起。
const merge = (left, right) => {
let temp = []
while (left.length > 0 && right.length > 0) {
if (left[0] <= right[0]) {
temp.push(left.shift())
}
else {
temp.push(right.shift())
}
}
return temp.concat(left, right)
}
const mergeSort = (arr) => {
if (arr.length === 1) return arr
let mid = Math.floor(arr.length / 2)
let left = arr.slice(0, mid)
let right = arr.slice(mid)
return merge(mergeSort(left), mergeSort(right))
}
console.log(mergeSort(arr))
快速排序
分治法:将原本的问题拆分成规模更小但是与之相似的子问题,递归解决子问题,然后将子问题进行合并。 核心思想:
- 选择一个元素作为基准(privot),所有比基准小的放在元素放在基准左侧,所有比基准大的元素放在基准右边,分区操作结束后,基准所处的位置就是最后排序后的位置。
- 对基准左边和右边的两个子集,不断地重读第一步和第二步操作,直到最后只剩下最后一个元素为止。
const arr = [12, 8, 24, 16, 1, 34, 23, 12, 54]
const quickSort = (arr) => {
if (arr.length <= 1) return arr
const privotIndex = Math.floor(arr.length / 2)
const privot = arr.splice(privotIndex, 1)[0]
const left = []
const right = []
arr.map(item => {
if (item < privot) {
left.push(item)
}
else {
right.push(item)
}
})
return quickSort(left).concat(privot, quickSort(right))
}
console.log(quickSort(arr))
|