常用排序,快速排序,归并排序算法讲解

排序有很多种算法,常听的十大排序有:冒泡排序、选择排序、插入排序、快速排序、归并排序、堆排序、希尔排序、计数排序、基数排序、桶排序。

这里只介绍两个常用的算法。

排序:

  1. 快速排序
  2. 归并排序

你可能想知道什么时候该用哪个:

快速排序使用场景:快速排序平均时间复杂度为O(n log n),最坏情况下为O(n²),不太稳定,但优点是不占用额外空间,快速排序为原地排序。 在实践中,快速排序通常优于其他时间复杂度为 O(n log n) 的算法,

归并排序使用场景:时间复杂度为O(n log n)。无论情况好坏都相对稳定。优点是稳定,但需要占用额外的O(n)空间。


快速排序

思路:选择一个基准元素,将所有小于基准的元素放置在其左侧,将所有大于基准的元素放置在其右侧。这种操作称为“分区”。然后分别对基准左侧和右侧的两个子元素执行相同的操作。

现在开始快速排序的基本步骤思路:

1: 数据数组

在这里插入图片描述
2: 选择基准

在这里插入图片描述

3: 设置左边界和右边界

在这里插入图片描述
4: 如果右边界小于基准值,则调换左边界和右边界的值,接着左边界i++,随后右边界j++(如果循环未结束)。否则仅j++

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

如果不理解,请仔细阅读第四标题的内容:如果右边界小于基准值,则调换左边界和右边界的值,接着左边界i++,随后右边界j++(如果循环未结束)。否则仅j++

5: 循环结束后,交换左边界和基准的值

在这里插入图片描述

6: 根据基准,截取两部分的值

在这里插入图片描述
7:将左右两部分分别执行 1-6 的步骤

在这里插入图片描述

JavaScript实现代码:

function myQuickSort(array, left = 0, right = array.length - 1) {
    if (left < right) {
        // 获取分区后枢轴的位置
        let pivotIndex = pivotIndexMeth(array, left, right)
        // 递归调用
        myQuickSort(array, left, pivotIndex - 1)
        // 递归调用
        myQuickSort(array, pivotIndex + 1, right)
    }
    return array
}

function pivotIndexMeth(array, left, right) {
    // 使用最右边的元素作为枢轴
    let pivot = array[right]
    // 从左边开始
    let i = left;
    // 遍历数组
    for (let j = left; j < right; j++) {
        // 如果元素小于枢轴,就交换它和当前的“i”元素
        if (array[j] < pivot) {
            [array[i], array[j]] = [array[j], array[i]]
            i++
        }
    }
    // 最后,将枢轴放置在正确的位置
    [array[i], array[right]] = [array[right], array[i]]
    // 返回枢轴的位置
    return i;
}

console.log(myQuickSort([7, 2, 3, 1, 6, 8, 4, 5]))

归并排序

思路:将一个大列表分成两个较小的子列表,然后分别对两个子列表进行排序,最后将两个已排序的子列表合并为一个完整的排序列表。

现在开始归并排序的基本步骤思路:

1: 数据数组

在这里插入图片描述

2: 求出中心点,分割数据

在这里插入图片描述
3: 将分割后的数据继续分割

在这里插入图片描述

4: 将分割后的数据继续分割

在这里插入图片描述
5: 直至分割成一个单位长度的数组之后,进行大小对比排序

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

JavaScript实现代码:

function myMergeSort(array) {
    // 获取数组长度
    let len = array.length;
    // 如果数组长度小于2,返回
    if (len < 2) {
        return array;
    }
    // 获取中间值
    let middle = Math.floor(len / 2)
    // 获取左边的数组
    let left = array.slice(0, middle)
    // 获取右边的数组
    let right = array.slice(middle)
    // 递归调用
    return merge(myMergeSort(left), myMergeSort(right))
}

function merge(left, right) {
    // 定义一个数组
    let result = [];
    // 如果左边和右边的数组都有值
    while (left.length && right.length) {
        // 如果左边的第一个值小于右边的第一个值
        if (left[0] < right[0]) {
            // 将左边的第一个值放入数组
            result.push(left.shift())
        } else {
            // 将右边的第一个值放入数组
            result.push(right.shift())
        }
    }
    // 如果左边的数组有值
    while (left.length) {
        result.push(left.shift())
    }
    // 如果右边的数组有值
    while (right.length) {
        result.push(right.shift())
    }
    return result;
}

console.log(myMergeSort([7, 2, 3, 1, 6, 8, 4, 5]))

如果解释有误或需要补充,感谢您指正。

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

一拖再拖 一拖再拖

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值