# 算法

# 冒泡排序

冒泡排序只会对相邻的两个元素进行比较大小关系,如果不满足条件就让俩元素互换位置
空间复杂度 O(1)
时间复杂度 O(n ^ 2)
稳定

# 未优化

// 冒泡排序
const bubbleSort = (arr) => {
    const length = arr.length
    if(length <= 1) return
    for(let i = 0;i < length -1;i++){
        for(let j = 0;j < length - i -1;j++){
            if(arr[j] > arr[j+1]){
                let temp = arr[j]
                arr[j] = arr[j+1]
                arr[j+1] = temp
            }
        }
    }
}

# 优化

// 冒泡排序
const bubbleSort = (arr) => {
    const length = arr.length
    if(length <= 1) return
    for(let i = 0;i < length -1;i++){
        let tag = false
        for(let j = 0;j < length - i -1;j++){
            if(arr[j] > arr[j+1]){
                let temp = arr[j]
                arr[j] = arr[j+1]
                arr[j+1] = temp
                tag = true
            }
        }
        // 如果冒泡没找到变化,可以中断遍历了
        if(!tag) break
    }
}

# 插入排序


空间复杂度 O(1)
时间复杂度 O(n ^ 2)
稳定

# 直接插入

思路:从后往前排序,保存当前下标元素记为current,与前面元素一一比较,如果前面元素比current大,则赋值给后一位,最后把current赋值给停止位

const insertionSort = (arr) => {
    let length = arr.length
    if(length <= 1) return

    let preIndex,current
    for(let i = 1;i<length;i++){
        current = arr[i] // 保存当前元素
        preIndex = i-1 // 待比较下标
        while(preIndex >= 0 && arr[preIndex] > current){
            arr[preIndex + 1] = arr[preIndex]
            preIndex--
        }
        if(preIndex + 1 !== i){
            arr[preIndex + 1] = current
        }
    }
}

# 拆半插入

每次新元素排序时,通过查找向前遍历终点,减少遍历次数,达到优化效果

const binaryInsertionSort = (arr) => {
    let length = arr.length
    if(length <= 1) return

    let current,i,j,m,low,high

    for(i = 1;i<length;i++){
        low = 0
        high = i-1
        current = arr[i]
        // 找到遍历终点
        while(low<=high){
            m = (low + high) >> 1
            if(arr[m] <= current){
                low = m + 1
            }else{
                high = m -1
            }
        }

        for(j = i;j > low;j--){
            arr[j] = arr[j-1]
        }
        arr[low] = current
    }
}

# 选择排序

选择排序算法的实现思路有点类似插入排序,也分已排序区间和未排序区间。但是选择排序每次会从未排序区间中找到最小的元素,将其放到已排序区间的末尾
空间复杂度 O(1)
时间复杂度 O(n ^ 2)
不稳定

const selectionSort = arr => {
    let length = arr.length
    let minIndex,current

    for(let i = 0;i<length-1;i++){
        minIndex = i
        current = arr[i]
        for(let j=i+1;j<length;j++){
            if(arr[j] < arr[minIndex]){
                minIndex = j
            }
        }
        arr[i] = arr[minIndex]
        arr[minIndex] = current
    }
}

# 归并排序

思路:通过把数组对半拆分成无数小的集合,分别合并
空间复杂度 O(nlogn)
时间复杂度 O(nlogn)
不稳定

const mergeSort = arr =>{
    let length = arr.length
    if(length <2) return arr
    let pivor = length >> 1
    let left = arr.slice(0,pivor)
    let right = arr.slice(pivor)
    return merge(mergeSort(left),mergeSort(right))
}
const merge = (left,right) =>{
    let result = []

    while(left.length && right.length){
        if(left[0] < right[0]){
            result.push(left.shift())
        }else{
            result.push(right.shift())
        }
    }
    result.push(...left,...right)
    return result
}

# 快速排序

思想:定义基准,从前后两个指针与基准值比较大小排序,取的下一次排序的分界线,递归排序

function quickSort(arr, left, right) {
  if(left >= right) return
  let pivor = partition(arr, left, right)
  quickSort(arr,left,pivor-1)
  quickSort(arr,pivor+1,right)
}

function partition(arr, left, right) {
  let index = left, base = arr[left]
  while (left < right) {
    while (left < right) {
      if (arr[right] < base) {
        arr[left] = arr[right]
        index = right
        break
      }
      right--
    }
    while (left < right) {
      if (arr[left] > base) {
        arr[right] = arr[left]
        index = left
        break
      }
      left++
    }
  }
  arr[index] = base
  return index
}

# 堆排序

# 动态规划

# 斐波那契数列

# 贪心算法

# 背包问题

🏗