五种排序问题

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

排序是将乱序变成有序,对于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)

最后

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

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

相关推荐
搞点夜点心3 分钟前
算法课习题汇总(2)
算法
大二转专业8 分钟前
408算法题leetcode--第10天
考研·算法·leetcode
.别止步春天.8 分钟前
Python中lambda表达式的使用——完整通透版
数据结构·python·算法
C7211BA12 分钟前
使用随机森林模型在digits数据集上执行分类任务
算法·随机森林·分类
cc蒲公英12 分钟前
vue2中使用vue-office库预览pdf /docx/excel文件
前端·vue.js
一嘴一个橘子13 分钟前
js 将二进制文件流,下载为excel文件
javascript
RaidenQ15 分钟前
2024.9.20 Python模式识别新国大EE5907,PCA主成分分析,LDA线性判别分析,GMM聚类分类,SVM支持向量机
python·算法·机器学习·支持向量机·分类·聚类
Kenneth風车20 分钟前
【机器学习(九)】分类和回归任务-多层感知机 (MLP) -Sentosa_DSML社区版
人工智能·算法·低代码·机器学习·分类·数据分析·回归
Sam902924 分钟前
【Webpack--013】SourceMap源码映射设置
前端·webpack·node.js
曳渔31 分钟前
Java-数据结构-二叉树-习题(三)  ̄へ ̄
java·开发语言·数据结构·算法·链表