基础的搜索和排序你懂了嘛

341 阅读3分钟

前言

开启掘金成长之旅!这是我参与「掘金日新计划 · 2 月更文挑战」的第 1 天,点击查看活动详情

每天都给自己先打个气,加油加油,送给大家的一句话:人生不可能总是顺心如意,但持续朝着阳光走,影子就会躲在身后。刺眼却是对的方向,逆风更适合飞翔。

五种常见的排序算法

  • 排序是什么:把某个乱序的数组变成升序或者降序的方法
  • js中的排序:数组的sort方法
  • 冒泡排序选择排序插入排序归并排序快速排序这几种排序方法你都会了嘛?
  • 顺序搜索二分搜索搜索方式

在介绍这几种排序方法之前,先给大家推荐一个很好用的算法网站

冒泡排序

  • 实现冒泡排序的思路
    • 比较所有相邻元素,如果第一个比第二个大,则交换他们
    • 一轮下来,可以保证最后的一个数是最大的
    • 执行n-1轮,就可以完成排序
  • 下面是实现的方式:
  Array.prototype.bubbleSort = function(){
      for(let i = 0 ; i<this.length-1; i++){
          for(let j =0 ;j<this.length - i -1 ;j++){
              if(this[j] > this[j+1]){
                  let temp = this[j]
                  this[j] = this[j+1]
                  this[j+1] = temp
              }
          }
      }
  }
let arr = [5,4,3,2,1]
arr.bubbleSort()
  • 分析时间复杂度:o(n^2)

选择排序

  • 实现选择排序的思路
    1. 找到数组中的最小值,选中它并将其放在第一位
    2. 接着找到第二小的值,选中它并将其放在第二位
    3. 以此类推,执行n-1轮
  • 实现方式
 Array.prototype.selectionSort = function(){
    for(let i = 0 ;i<this.length - 1;i++){
        let indexMin = i
        for(let j = i ;j<this.length;j++){
            if(this[j] <this[indexMin]){
                indexMin = j
            }
        }
        if(indexMin !== i){
            let temp = this[i]
            this[i] = this[indexMin]
            this[indexMin] = temp 
        }
    }
}
const arr = [5,4,3,2,1]
arr.selectionSort()
  • 时间复杂度:o(n^2)

插入排序算法

  • 实现思路
    • 我们从第二个开始,比较当前元素前面的所有元素。
    • 找到一个比他大的元素,就把这个元素向后移一位。
    • 直到没有比他大的元素了,这个位置就是它的归宿
  • 实现方式
 Array.prototype.insertionSort = function(){
    for(let i = 1 ;i<this.length;i++){
        let temp = this[i]
        let j = i
        while(j > 0){
            if(this[j - 1] > temp){
                this[j] = this[j - 1]
            }else{
                break
            }
            j--
        }
        this[j] = temp
    }
}
let arr = [5,4,3,2,1]
arr.insertionSort()
console.log(arr);

归并排序

  • 归并排序思路
    • 分:把数组劈成两半,在递归对子数组进行“分操作”,直到分成一个个单数的数
    • 合:把两个数合并为有序数组,再对有序数组进行合并,直到全部子数组合并为一个完整的数组
  • 合并两个有序数组
    • 新建一个空数组res,用于存在最终排序后的数组
    • 比较两个有序数组的头部,较小者出队并推入res中
    • 如果两个数组还有值,就重复第二步
  • 实现方式
 Array.prototype.mergeSort = function(){
    const rec = (arr) => {
        if(arr.length === 1) return arr
        const mid = Math.floor(arr.length/2)
        const left = arr.slice(0,mid)
        const right = arr.slice(mid,arr.length)
        const orderLeft = rec(left)
        const orderRight = rec(right)
        const res = []
        while(orderLeft.length || orderRight.length){
            if(orderLeft.length && orderRight.length){
                res.push(orderLeft[0] < orderRight[0]?orderLeft.shift():orderRight.shift())
            }else if(orderLeft.length){
                res.push(orderLeft.shift())
            }else if(orderRight.length){
                res.push(orderRight.shift)
            }
        }
        return res
    }
    const res = rec(this)
    console.log(res);
    res.forEach((n,i) => this[i] = n)
}
let arr = [5,4,3,2,1]
arr.mergeSort()
console.log(arr);
  • 时间复杂度分析
    • 分的时间复杂度为O(logN)
    • 合的时间复杂度为O(n)
    • 时间复杂度为O(n*logn)

两种搜索算法

顺序搜索

  • 实现思路
    • 遍历数组
    • 找到跟目标值相等的元素,就返回他的下标
    • 遍历结束后,没有搜索到目标值,就返回-1
  • 实现代码
  Array.prototype.sequentialSearch = function(item) {
      for (let index = 0; index < this.length; index++) {
         if(this[index] === item){
          return index
         }
      }
      return -1
  }
  const res = [1,2,3,4].sequentialSearch(3)
  • 时间复杂度分析:O(n)

二分搜索

  • 实现思路
    • 从数组的中间元素开始,如果中间元素正好是目标值,则搜索结束
    • 如果目标值大于或者小鱼中间元素,则在大于或小于中间元素的那一半数组中搜索
  • 实现代码
 Array.prototype.binarySearch = function(item){
    let low = 0
    let high = this.length -1
    while(low <= high){
        const mid = Math.floor((low + high)/2)
        const element = this[mid]
        if(element< item){
            low = mid + 1
        }else if(element > item){
            high = mid -1
        }else{
            return mid
        }
    }
    return -1
}
const res = [1,2,3,4,5].binarySearch(5)
  • 时间复杂度分析O(logN)

说个题外话:大家觉得这个二分搜索,像不像我们平时喝酒猜数字的游戏,哈哈哈,想着我们喝的不是酒,喝出来的还是一个算法,有什么问题,请大佬们请教