五种排序问题

排序中的快排很容易被百度面到

排序是将乱序变成有序,对于js这门语言来说,本身是不难的,因为自带一个sort方法,但是面试的时候面试官肯定不会让你用这个方法去实现排序,所以你还是得掌握下五种排序问题

算法中排序可以分为两类,一个是基础排序算法,一个是进阶排序算法,基础排序算法有冒泡排序,选择排序,插入排序,进阶排序算法有快速排序,归并排序,下面依次讲解,均以升序为例

基础排序算法

基础排序容易想到,但是效率低

冒泡排序

思想:重复遍历数列,依次比较两个相邻的元素,顺序错误则交换位置,直到没有任何元素需要交换为止

既然是相邻,那么第一个元素若是下标i,那么第二个就是i + 1,顺序不同则交换位置,这里我们可以直接用解构写法去交换位置

ini 复制代码
let arr = [2, 3, 1, 4, 5]
// 2,1,3,4,5
// 1,2,3,4,5

function bubbleSort(arr){
    const len = arr.length
    for(let i = 0; i < len; i++){
        for(let j = i + 1; j < len; j++){
            if(arr[i] > arr[j]){
                // arr[i] = arr[j]
                // temp = arr[i]
                // arr[j] = temp
                [arr[i], arr[j]] = [arr[j], arr[i]]
            }
        }
    }
    return arr
}

空间复杂度为0,时间复杂度为n * n

选择排序

思想:每次从待排序的元素中选择最小的元素与第一个元素互换位置,然后从剩余的未排序元素中继续选择最小的元素,与待排序的第一个元素互换位置,直到顺序为止

两层循环,第一层确定好最小元素的下标,然后第二层去找是否有比最小值更小的元素,找到后会确定最终的最小元素的下标,然后再去比较下标,下标是否变更了,变更了就去互换位置

ini 复制代码
let arr = [5, 3, 2, 4, 1]
// 1, 3, 2, 4, 5
// 1, 2, 3, 4, 5

function selectSort(arr){
    const len = arr.length
    let minIndex 
    for(let i = 0; i < len; i++){
        minIndex = i
        for(let j = i; j < len; j++){
            if(arr[j] < arr[minIndex]){
                minIndex = j
            }
        }
        if(minIndex != i){
            [arr[i], arr[minIndex]] = [arr[minIndex], arr[i]]
        }
    }
    return arr
}

空间复杂度为0,时间复杂度为n * n

插入排序

思想:将数组分为已排序和未排序的两部分,初始时已排序部分只包含第一个元素,然后逐步将未排序部分的元素插入到已排序部分的正确位置,直到所有元素都被排序完

先不管第一个元素,因为是有序的,先拿到第二个元素,从下标1开始,现在开始插队,j - 1代表有序中的下标,只要该元素比后面无序的第一个大,那就将其插入到有序的前一个(这个过程是先占好位置,再赋值新值过去),j--使新元素能够插入到能插入的最前面去

ini 复制代码
let arr = [5, 3, 2, 4, 1]
// 3, 5, 2, 4, 1
// 2, 3, 5, 4, 1
// 2, 3, 4, 5, 1
// 1, 2, 3, 4, 5

function insertSort(arr){
    const len = arr.length
    let temp
    for(let i = 1; i < len; i++){
        temp = arr[i]
        let j = i
        while(j > 0 && arr[j - 1] > temp){
            arr[j] = arr[j - 1]
            j--
        }
        arr[j] = temp
    }
    return arr
}

空间复杂度为0,时间复杂度为n * n

进阶排序算法

快速排序(快排)

快排考察的最多,快排之所以称之为快排就是因为快,所以时间复杂度肯定小于n * n

并且快排的代码实现非常简单

思想:采用分而治之的思想,通过一趟排序将数组分割成独立的两部分,其中一部分的元素都要比另一部分的元素小,然后对这两部分继续递归地进行快排,直到整个序列有序

基准值可从任意位置取,这里我取第一个,比基准值小的放左边,大的放右边,然后分别对两边进行相同操作,既然是递归,那就需要有个出口,就是当数组的长度为1时

css 复制代码
let arr = [5, 1, 3, 6, 2, 4, 7]
// [5, 1, 3, 4, 2] [6, 7]
// [1, 2] [3, 5, 4] [6] [7]
// [1] [2] [3, 4] [5] [6] [7]
// [1] [2] [3] [4] [5] [6] [7]

function quickSort(arr) {
    if(arr.length <= 1)  return arr
    const len = arr.length
    const base = arr[0]
    let left = [], right = []
    for(let i = 1; i < len; i++){
        if(arr[i] < base){
            left.push(arr[i])
        }else{
            right.push(arr[i])
        }
    }
    return [...quickSort(left), base, ...quickSort(right)]
}

空间复杂度为n,时间复杂度为n * log(n)

归并排序

归并排序比快排要难些

思想:依旧是采用分而治之的思想,将数组不断地分割成两个子数组,直到每个数组只有一个元素,然后再将相邻地子数组两两合并,如何划分就如何合并,但是合并过程中需要排序,此时的排序比较两部分的第一部分,小的就放前面

合并的过程就是排序的过程,因此得名归并排序

ini 复制代码
let arr = [5, 1, 3, 6, 2, 4, 7]

function mergeSort(arr) {
    if (arr.length <= 1) return arr

    const mid = Math.floor(arr.length / 2);
    const leftArr = arr.slice(0, mid);
    const rightArr = arr.slice(mid);

    const merge = (leftArr, rightArr) => {
        let res = [];
        let leftIdx = 0;
        let rightIdx = 0;
        // 比较左右两部分的元素,依次将较小的元素加入结果数组中
        while (leftIdx < leftArr.length && rightIdx < rightArr.length) {
            if (leftArr[leftIdx] < rightArr[rightIdx]) {
                res.push(leftArr[leftIdx]);
                leftIdx++;
            } else {
                res.push(rightArr[rightIdx]);
                rightIdx++;
            }
        }
        // 将剩余的元素加入结果数组
        while (leftIdx < leftArr.length) {
            res.push(leftArr[leftIdx]);
            leftIdx++;
        }
        while (rightIdx < rightArr.length) {
            res.push(rightArr[rightIdx]);
            rightIdx++;
        }
        return res;
    }

    return merge(mergeSort(leftArr), mergeSort(rightArr));
}

空间复杂度为n,时间复杂度为n * log(n)

最后

以上五种排序算法你都需要做到可以手写,尤其是快排最容易被问到

另外有不懂之处欢迎在评论区留言,如果觉得文章对你学习有所帮助,还请"点赞+评论+收藏"一键三连,感谢支持!

相关推荐
霍先生的虚拟宇宙网络几秒前
webp 网页如何录屏?
开发语言·前端·javascript
温吞-ing2 分钟前
第十章JavaScript的应用
开发语言·javascript·ecmascript
彪8253 分钟前
第十章 JavaScript的应用 习题
javascript·css·ecmascript·html5
jessezappy21 分钟前
jQuery-Word-Export 使用记录及完整修正文件下载 jquery.wordexport.js
前端·word·jquery·filesaver·word-export
旧林8431 小时前
第八章 利用CSS制作导航菜单
前端·css
yngsqq1 小时前
c#使用高版本8.0步骤
java·前端·c#
肥猪猪爸2 小时前
使用卡尔曼滤波器估计pybullet中的机器人位置
数据结构·人工智能·python·算法·机器人·卡尔曼滤波·pybullet
Myli_ing2 小时前
考研倒计时-配色+1
前端·javascript·考研
余道各努力,千里自同风2 小时前
前端 vue 如何区分开发环境
前端·javascript·vue.js
PandaCave2 小时前
vue工程运行、构建、引用环境参数学习记录
javascript·vue.js·学习