当前位置: 首页 > news >正文

算法-- js排序

汇总

注:以下log n 是 O(log2n)
在这里插入图片描述注:快速排序实际应用中通常最优,但需避免最坏情况。

1 快速排序

[快速排序的思路]

  • 分区:从数组中任意选择一个“基准”,所有比基准小的元素放在基准前面,比基准大的元素放在基准的后面。
  • 递归:递归地对基准前后的子数组进行分区。
[快速排序]
- 时间复杂度:
时间复杂度:​最优/平均情况O(n*logN), 最坏情况O(n^2)。
n*logN: 当每次划分能大致将数组分为两部分时(如基准值选择接近中位数),递归深度为 logn,每层处理 n 个元素
n^2: 当数组已有序或基准值总是极值(如第一个或最后一个元素),导致每次划分仅减少一个元素,递归深度为 n

PS:递归的时间复杂度是O(logN)(劈成两半,递归前left后right,基本劈成两半递归的操作都是logN)
分区操作的时间复杂度是O(n)。

- 空间复杂度:O(logN)(递归造成的栈空间的使用)

//没明白为什么递归深度是 logn?--简单来说是:"拆分两半"这个动作log2 n次
答:快速排序的递归深度为logn是因为在理想情况下​(每次划分都能将数组均匀分成两部分),递归树的深度与二分查找类似。以下是具体解释:
​均匀划分的数学原理每次划分后,数组被分成两个子数组,长度约为2n​。递归调用会持续将子数组对半分割,直到子数组长度为1。此时递归深度d满足:
n/(2^d)=1d=log2 n
因此深度为O(logn)


function quickSort(arr) {
  // 递归终止条件:数组长度 ≤1 时直接返回
  /* 这里也说明一下 为啥要 小于等于1 , 因为有可能 出现左边数组为空的情况 ,
     不能是 ==1 那样就会出现 程序崩溃的情况 , 这样==0时没有return值也就是递归
     不会结束所以报错Maximum call stack size exceeded */
  if (arr.length <= 1) {
    return arr;
  }

  const left = [];
  const right = [];
  const pivot = arr[0]; // 基准值取第一个元素

  // 从第二个元素开始遍历(避免越界)
  for (let i = 1; i < arr.length; i++) {
    if (arr[i] < pivot) {
      left.push(arr[i]);
    } else {
      right.push(arr[i]);
    }
  }

  // 递归处理左右子数组,拼接结果
  return [...quickSort(left), pivot, ...quickSort(right)];
}

// 使用示例
const arr = [2, 4, 5, 3, 1];
const sortedArr = quickSort(arr);
console.log(sortedArr); // 输出: [1, 2, 3, 4, 5]

2 冒泡排序

[冒泡排序的思路]

  • 比较所有的相邻元素,如果第一个比第二个大,则交换它们。
  • 一轮下来,可以保证最后一个数是最大的。
  • 执行n-1轮,就可以完成排序。
[冒泡排序]
- 时间复杂度
1.两个嵌套循环
2.时间复杂度:O(n^2)--这个时间复杂度是不太好的排序时间复杂度
- 空间复杂度:O(1)
function bubbleSort(arr) {
    // 先写第一轮冒泡;
    // 另外注意:arr.length-1
    // for (let j = 0; j < arr.length-1; j++) {
    //     if (arr[j] > arr[j + 1]) {
    //         let temp = arr[j]
    //         arr[j] = arr[j + 1]
    //         arr[j + 1] = temp
    //     }
    // }
    // 多轮冒泡
    for (let i = arr.length - 1; i > 0; i--) {
        for (let j = 0; j < i; j++) {
            if (arr[j] > arr[j + 1]) {
                let temp = arr[j]
                arr[j] = arr[j + 1]
                arr[j + 1] = temp
            }
        }
    }
    return arr
}
let arr = [2, 4, 3, 5, 1]
let res = bubbleSort(arr)
console.log('res:', res)

3 插入排序

[插入排序的思路]

  1. 初始化:将第一个元素视为已排序序列。
  2. 插入过程
  • 待插入元素暂存temp=arr[i]:从第二个元素(ax)开始,暂存其值为temp。
  • 大数后移:向前扫描:从 ax 的前一个元素开始反向遍历,将所有大于 temp 的元素后移一位。
  • 插入位置:当遇到第一个小于等于 temp 的元素 ay 时,将 temp 插入到 ay 的后面。
  1. 重复:对后续所有未排序元素执行上述操作。
[插入排序]
- 时间复杂度
1.两个嵌套循环。
2.时间复杂度:O(n^2)。空间复杂度:
-空间复杂度:O(1)
原因:仅需常数级别的额外空间(如临时变量temp),属于原地排序算法

function insertSort(arr) {
    for (let i = 1; i < arr.length; i++) {
        const temp = arr[i] // 待插入元素
        let j = i // 移动索引
        while (j > 0) {
            if (arr[j - 1] > temp) {
                arr[j] = arr[j - 1] // 元素后移
                j--
            } else {
                break;
            }
        }
        arr[j] = temp // 待插入元素-插入到正确位置
    }
    return arr
}
let arr = [2, 4, 3, 5, 1]
let res = insertSort(arr)
console.log('res:', res)
  
// ![注意]:这样写会报错,因为j = i + 1、arr[j]会超出范围
// function insertSort(arr) {
//     for (let i = 0; i < arr.length; i++) {
//         let j = i + 1
//         const temp = arr[i]
//         while (j > 0) {
//             if (arr[j] < temp) {
//                 arr[j - 1] = arr[j]
//                 j--
//             } else {
//                 break;
//             }
//         }
//         arr[j] = temp
//     }
//     return arr
// }

4 选择排序

[选择排序的思路]

  • 找到数组中的最小值,选中它并将其放置在第一位。
  • 接着找到第二小的值,选中它并将其放置在第二位。
  • 以此类推,执行n-1轮。
[选择排序]
- 时间复杂度
两个嵌套循环;时间复杂度:O(n^2)。--性能不太好的排序算法

- 时间复杂度:O(1) -- 原地排序
function selectionSort(arr) {
  for (let i = 0; i < arr.length - 1; i++) {
    let minIndex = i;
    // 在未排序部分中寻找最小值
    for (let j = i + 1; j < arr.length; j++) {
      if (arr[j] < arr[minIndex]) {
        minIndex = j;
      }
    }
    // 将最小值交换到已排序部分的末尾
    if (minIndex !== i) {
      [arr[i], arr[minIndex]] = [arr[minIndex], arr[i]]; // ES6解构赋值交换
    }
  }
  return arr; // 返回排序后的数组(可选)
}

// 使用示例
const arr = [5, 4, 3, 2, 1];
const sortedArr = selectionSort(arr);
console.log(sortedArr); // 输出: [1, 2, 3, 4, 5]

C++排序版本见:算法-- C++排序

相关文章:

  • 43常用控件_使用qrc文件管理资源
  • 多类型医疗自助终端智能化升级路径(代码版.上)
  • [docker] 简单操作场景
  • 【Java设计模式】第6章 抽象工厂模式讲解
  • Linux系统学习Day0——了解和熟悉Linux系统的远程终端登录和数据传输
  • 远程主机可能不符合glibc和libstdc++ VS Code服务器的先决条件
  • 批量转换图片颜色模型为 GMK/CMYK/灰度等
  • 08-Spring MVC 请求处理流程全解析
  • webrtc-stats
  • 3.神经网络
  • Linux系统(Ubuntu和树莓派)的远程操作练习
  • 第十四届蓝桥杯大赛软件赛省赛C/C++ 大学 B 组
  • 初始JavaEE篇 —— SpringBoot 统一功能处理
  • c++--------- stack queue
  • 大语言模型(LLM)全解析:从原理到实战应用
  • 具身推理器:协同视觉搜索、推理和行动,实现具身交互任务
  • openssl源码分析之加密模式(modes)
  • java 集合进阶
  • 顺序表:从数组到高效数据管理的进化之路
  • Android studio打包uniapp插件
  • 沃旭能源因成本上升放弃英国海上风电项目,或损失近40亿元
  • 江西省直机关工委副书记熊亮华履新宜春市委常委、宣传部部长
  • 西南大学教授、重庆健美运动奠基人之一李启圣逝世
  • 鸿蒙电脑正式亮相,五年布局积累超2700项核心专利
  • 太原一高中生指出博物馆多件藏品标识不当,馆方已邀请他和专家共同探讨
  • 多地跟进官宣下调公积金贷款利率,最低降至2.1%