常见的排序算法(6种)

本文详细介绍了冒泡排序、插入排序、选择排序、快速排序、归并排序和堆排序的基本概念,重点关注它们的最优和最差时间复杂度,以及稳定性特点,并提供了手写实现代码示例。在数据基本有序时,简单排序如插入排序表现最佳。
摘要由CSDN通过智能技术生成

需要掌握的点为排序的最优和最差时间复杂度和稳定性,以及手写实现

在这里插入图片描述
ps : 稳定性:排序后 2 个相等键值的顺序和排序之前它们的顺序相同

冒泡排序

…比较简单不写了

插入排序

        function Insertion(arr) {
            let len = arr.length;
            let preIndex, current;
            for (let i = 1; i < len; i++) { // 从第二个数开始循环
                preIndex = i - 1; // 当前数的前一个index开始对比
                current = arr[i]; // 当前需要插入的数据,用current空间参数存起来
                while (preIndex >= 0 && current < arr[preIndex]) { // 进入二次循环,该循环用来对比排序完成的数与当前需要插入的数据
                    arr[preIndex + 1] = arr[preIndex]; // 因为当前值已经被抽出,它的序号比需要对比的数的最大序列大1,所以当满足条件,可以把preIndex + 1的序列的值赋值为 // preIndex
                    preIndex--; // 继续循环
                }
                arr[preIndex + 1] = current; // 外层完成一次循环后,把找到的当前小于current 的前一位数替换成插入元素
            }
            return arr;
        }


        var arr = [3, 5, 7, 1, 4, 56, 12, 78, 25, 0, 9, 8, 42, 37];
        Insertion(arr);

选择排序

        function selectSort(arr) {
            for (let i = 0; i < arr.length - 1; i++) {
                let min = i;
                for (let j = min + 1; j < arr.length; j++) {
                    if (arr[min] > arr[j]) {
                        min = j;
                    }
                }
                let tmp = arr[min];
                arr[min] = arr[i];
                arr[i] = tmp;
            }
            return arr;
        }
        const arr = [6, 4, 5, 1, 8, 0, 2, 3, 9, 7];
        console.log(selectSort(arr));// [ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 ]

快速排序

  • 最好的情况:每次选的pivot几乎能把数据均分成两半,这样递归树的深度就是logN,这样快排的时间复杂度为O(NlogN)
  • 最坏的情况:每次找的pivot将数组分成两部分,其中有一部分是空,这样递归树就变成了一棵倾斜的树。树的深度为n-1,这样时间复杂度就变成了O(N^2).

一般当数据有序或者局部有序的时候会出现这种坏的情况,比如数组正序或者逆序,(数字完全相同的时候也是有序的特殊情况)。

解决方法: 选pivot的时候可以随机选,而不是每次选第一个或者最后一个
对子数组进行快排序的时候可以先扫描一遍,如果子数组有序就不用再快排了。

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

归并排序

        function mergeSort(arr) {
            let len = arr.length
            if (len < 2) {
                return arr
            }
            let middle = Math.floor(len / 2)
            //拆分成两个子数组
            let left = arr.slice(0, middle)
            let right = arr.slice(middle, len)
            //递归拆分
            let mergeSortLeft = mergeSort(left)
            let mergeSortRight = mergeSort(right)
            //合并
            return merge(mergeSortLeft, mergeSortRight)
        }
        const merge = (left, right) => {
            const result = [];

            while (left.length && right.length) {
                // 注意: 判断的条件是小于或等于,如果只是小于,那么排序将不稳定.
                if (left[0] <= right[0]) {
                    result.push(left.shift()); //每次都要删除left或者right的第一个元素,将其加入result中
                } else {
                    result.push(right.shift());
                }
            }
            //将剩下的元素加上
            while (left.length) result.push(left.shift());

            while (right.length) result.push(right.shift());

            return result;
        };

数组基本有序的情况下,简单排序方法(冒泡,插入,选择)中插入排序的效果最好

堆排序

关键是建立堆

参考文章:
JS实现十大排序算法
快排的最好最坏情况

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值