排序与搜索算法

206 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第14天,点击查看活动详情

前言

排序与搜索

排序:把某个乱序的数组变成升序或降序的数组

搜索:找出数组中某个元素的下标

时间复杂度

时间复杂度.png

空间复杂度

空间复杂度.png

排序

排序稳定性.jpg

1. 冒泡排序(时间复杂度n^2)

冒泡排序.png

//冒泡排序 
for(var i = 0; i < nums.length - 1; i++) { 
    for(var j = 0; j < nums.length - i - 1; j++) { 
        if(nums[j] > nums[j+1]) { 
            [nums[j],nums[j+1]] = [nums[j+1],nums[j]] 
        } 
    } 
} 
return nums

2. 选择排序(时间复杂度n^2)

选择排序.jpg

for(var i = 0; i < nums.length; i++) {     
    for(var j = i + 1; j < nums.length; j++) {         
        if(nums[i] > nums[j]) {             
            [nums[i],nums[j]] = [nums[j],nums[i]]         
        }     
    } 
} 
return nums

3. 插入排序(时间复杂度n^2)

插入排序.jpg 从数组第二个元素开始,往前比较

for(var i = 1; i < nums.length; i++) {     
    for(var j = 0; j < i; j++) {         
        if(nums[i] < nums[j]) {             
            [nums[i],nums[j]] = [nums[j],nums[i]]         
        }     
    } 
} 
return nums

4. 归并排序mergeSort(时间复杂度nlogn)

比前面的排序更好,时间复杂度更低

分:把数组劈成两半,再递归对子数组进行“分”操作,直到分成一个个单独的数

合:把两个数组合并为有序数组,再对有序数组进行合并,直到全部子数组合并为一个完整数组

  • 新建一个空数组res,用于存放最终排序后的数组
  • 比较两个有序数组的头部,较小者出队并推入res中
  • 如果两个数组还有值,就重复第二步

归并排序.jpg

rec = (nums) => {          
    //首先把数组劈成两半,再递归对子数组进行“分”操作,     let mid = Math.floor(nums.length / 2)     
    let left = nums.slice(0,mid)     
    let right = nums.slice(mid,nums.length)     
    //直到分成一个个单独的数 //递归终止条件     
    if(nums.length === 1) {         
        return nums;     
    }     
    let orderLeft = rec(left)     
    let orderRight = rec(right)     
    //把两个数组合并为有序数组,再对有序数组进行合并,直到全部子数组合并为一个完整数组     
    //新建一个空数组res,用于存储最终排序后的数组     
    let res = []     
    //比较两个有序数组的头部,较小者出队并推入res中     
    //如果两者还有值,就重复第二步     
    while(orderLeft.length || orderRight.length) {
        if(orderLeft.length && orderRight.length) {
           res.push(orderLeft[0] < orderRight[0] ? orderLeft.shift() : orderRight()) 
        }else if(orderLeft.length) {             
            res.push(orderLeft.shift())         
        }else if(orderRight.length){             
            res.push(orderRight.shift())         
        }     
    }     
    return res 
} 
let nums = rec(nums) 
return nums

5. 快速排序(时间复杂度:O(nlogN))

快速排序采用了分而治之思想

分而治之是算法设计中的一种方法,对于一个规模为n的问题,若该问题可以容易地解决(如说规模n较小),则直接解决;否则将其分解为k个规模较小的子问题,这些子问题互相独立且与原问题形式相同,递归地解决这些子问题,然后将各子问题的解合并得到原问题的解。

快速排序.png 分区:从数组中任意选择一个“基准”,所有比基准小的元素放在基准前面,比基准大的元素放在基准的后面。

递归:递归地对基准前后的子数组进行分区

var len = arr.length 
if(len < 2){ return arr } 
var basis = arr[0] 
var left = [] 
var right = [] 
for(let i = 1; i < len; i++) { 
    if(arr[i] < basis) { 
        left.push(arr[i]) 
    } else { 
        right.push(arr[i]) 
    } 
} 
return MySort(left).concat([basis], MySort(right))

搜索算法

1. 顺序搜索sequentialSearch(时间复杂度O(n))

  • 遍历数组
  • 找到跟目标值相等的元素,就返回它的下标
  • 遍历结束后,如果没有搜索到目标值,就返回-1

2. 二分搜索binarySearch(时间复杂度O(logn))

注意:前提:数组是有序的

  • 从数组中间元素开始,如果中间元素正好是目标值,则搜索结束
  • 如果目标值大于或小于中间元素,则在大于或小于中间元素的那一半数组中搜索
let low = 0 
let high = this.length - 1 
while(low <= hign) { 
    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 
}

总结

排序复杂度.png

最后

排序算法只写了一部分,不完整,后续可能会补上,最后,感谢观看!

狗狗.jpeg