Javascript 实现冒泡排序、选择排序、插入排序、归并排序、快速排序、希尔排序、堆排序

1. 冒泡排序、选择排序、插入排序。

它们的平均时间复杂度都为 O(n2)。
在这里插入图片描述

1.1 冒泡排序

冒泡排序只会操作相邻的两个数据。
每次冒泡操作都会对相邻的两个元素进行比较,看是否满足大小关系要求。如果不满足就让它俩互换。
一次冒泡会让至少一个元素移动到它应该在的位置,重复 n 次,就完成了 n 个数据的排序工作。

// 冒泡排序
const bubbleSort = arr => {
    const length = arr.length;
    if (length <= 1) return;
    // i < length - 1 是因为外层只需要 length-1 次就排好了,第 length 次比较是多余的。
    for (let i = 0; i < length - 1; i++) {
        // j < length - i - 1 是因为内层的 length-i-1 到 length-1 的位置已经排好了,不需要再比较一次。
        for (let j = 0; j < length - i - 1; j++) {
            if (arr[j] > arr[j + 1]) {
                [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]]
            }
        }
    }
    return arr;
};
  • 第一,冒泡排序是原地排序算法

  • 第二,冒泡排序是稳定的排序算法

  • 第三,冒泡排序的时间复杂度是多少 ?

    • 最佳情况:T(n) = O(n),当数据已经是正序时。
    • 最差情况:T(n) = O(n2),当数据是反序时。
    • 平均情况:T(n) = O(n2)。

1.2 插入排序

  • 假定第一项已经排序了。
  • 后内层循环对当前元素前面有序表进行待插入位置查找,并进行移动。

在这里插入图片描述

// 插入排序
const insertionSort = arr => {
    const length = arr.length;
    if (length <= 1) return;

    for (let i = 1; i < length; i++) {
        let preIndex = i - 1; //待比较元素的下标(前一个元素下标)

        let current = arr[i]; //获取当前元素

        while (preIndex >= 0 && arr[preIndex] > current) {
            //前置条件之一: 待比较元素比当前元素大
            arr[preIndex + 1] = arr[preIndex]; //将待比较元素后移一位
            preIndex--; //游标前移一位
        }
        if (preIndex + 1 != i) {
            //避免同一个元素赋值给自身
            arr[preIndex + 1] = current; //将当前元素插入预留空位
        }
    }
    return arr;
};

1.3 选择排序

const selectionSort = arr => {
    const len = arr.length;
    let minIndex, temp;
    for (let i = 0; i < len - 1; i++) {

        minIndex = i;

        for (let j = i + 1; j < len; j++) {

            if (arr[j] < arr[minIndex]) {
                // 寻找最小的数
                minIndex = j; // 将最小数的索引保存
            }
        }
        [arr[i], arr[minIndex]] = [arr[minIndex], arr[i]]
    }
    return arr;
};

2. 归并排序、快速排序、希尔排序、堆排序

它们的平均时间复杂度都为 O(nlogn)

2.1 归并排序

快排和归并用的都是分治思想 归并排序不是原地排序算法

const mergeSort = (arr) => {
    if (arr.length < 2) return arr;

    let mid = Math.floor(arr.length / 2);
    let left = arr.slice(0, mid);
    let right = arr.slice(mid, arr.length);

    return merge(mergeSort(left), mergeSort(right))



}

const merge = (left, right) => {
    const res = [];
    while (left.length && right.length) {
        if (left[0] <= right[0]) {
            res.push(left.shift())
        } else {
            res.push(right.shift())
        }
    }

    while (left.length) res.push(left.shift());
    while (right.length) res.push(right.shift())

    return res;

}

在这里插入图片描述

2.2 快速排序

快速排序的特点就是快,而且效率高!它是处理大数据最快的排序算法之一。

快排是原地排序算法。

// 快速排序
const quickSort = arr => {
    if (arr.length <= 1) {
        return arr;
    }
    //取基准点
    const midIndex = Math.floor(arr.length / 2);
    //取基准点的值,splice(index,1) 函数可以返回数组中被删除的那个数 arr[index+1]
    const midIndexVal = arr.splice(midIndex, 1);
    const left = []; //存放比基准点小的数组
    const right = []; //存放比基准点大的数组
    //遍历数组,进行判断分配
    for (let i = 0; i < arr.length; i++) {
        if (arr[i] < midIndexVal) {
            left.push(arr[i]); //比基准点小的放在左边数组
        } else {
            right.push(arr[i]); //比基准点大的放在右边数组
        }
    }
    //递归执行以上操作,对左右两个数组进行操作,直到数组长度为 <= 1
    return quickSort(left).concat(midIndexVal, quickSort(right));
};

归并和快排的区别

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

堆排序和希尔排序 后补。。

https://cloud.tencent.com/developer/article/1475120

  • 5
    点赞
  • 46
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值