前端十种排序算法解析

news2025/6/9 17:28:13

1. 冒泡排序

1.1 说明

  1. 冒泡排序为一种常用排序算法,执行过程为从数组的第一个位置开始,相邻的进行比较,将最大的数移动到数组的最后位置
  2. 执行的时间复杂度与空间复杂度为 o(n^2)

1.2 执行过程

    1. 从数组的第一个位置开始,截止位置为 arr.length - 1 - i, 相邻比较元素值
    1. 如果前个元素值大于后个相邻元素值,交换两个元素的值
    1. 重复执行 2 步骤
    1. for 循环执行的次数完成及完成排序

1.3 实现代码

function bubbleSort(arr) {
  for (let i = 0; i < arr.length; i++) {
    for (let j = 0; j < arr.length - i - 1; j++) {
    //  比较相邻元素值,前个元素值大于后面元素的值就交换元素值
      if (arr[j] > arr[j + 1]) {
        [arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
      }
    }
  }
  return arr;
}

2. 选择排序

2.1 说明

  1. 选择排序为默认选择一个数为最大或最小值
  2. 默认选择第一个元素值为最小值,
  3. 默认拿第一个元素索引与后面元素比较,如果后面元素小于该元素值,最小索引值为该元素的索引

2.2 执行过程

  1. 定义一个minIndex = i; i从0开始
  2. 比较Arr[minIndex] > arr[minIndex + 1]
  3. 重复步骤 2 找出最小的元素索引
  4. 交换元素位置 arr[i] = arr[minIndex], arr[minIndex= arr[i]

2.3 实现代码

function selectSort(arr = []) {
    for(var i = 0; i < arr.length; i++) {
        var minIndex = i; // 假设选择第一个元素为最小值,最小值的开始索引值从为i,也就是从0开始
        for(var j = minIndex + 1; j < arr.length; j++) {
            // 相邻比较元素值,找出比选择数更小的值
            if (arr[j] < arr[minIndex]) {
                minIndex = j
            }
        }
        // 如果最小值的索引和当前选择值的索引值不相等,则交换元素值位置
        if (minIndex != i) {
            [arr[minIndex], arr[i]] = [arr[i], arr[minIndex]]
        }
    }
    return arr
}

3. 归并排序

3.1

  1. 归并排序为一种分治排序思想,通过将一个大数组分为多个子数组进行组内完成排序
  2. 将组内完成排序的子数组再进行合并完成数组排序

3.2 执行过程

    1. 从数组的一半位置拆分数组为左子数组(left),右子数组(right)
    1. 声明一个接受left,right两参数的函数,在函数内部分别比较两个子数组

3.3 实现代码

3.3.1

function mergeSort(arr = []) {
    if (arr.length < 2) return arr
    var merge = (left, right) => {
        // 定义两个数组开始比较的索引值都从第一个元素开始
        var i = 0; 
        var j = 0;
        // 定义一个比较完后的空数组
        var result = []
        while(i < left.length && j < right.length) {
            // 从两个数组的0位置开始比较,如果左数组第一个值小于右数组的第一个值,将做数组第一个值添加到空数组中,左数组索引值递增,再用左数组的第二个元素与右数组的第一个值比较,重复该步骤
            if (left[i] < right[j]) {
                result.push(left[i++])
            } else {
                result.push(right[j++])
            }
        }
        // 左数组剩余为比较的,默认添加到数组中
        while (i < left.length) {
            result.push(left[i++])
        }
        // 右数组剩余为比较的,默认添加到数组中
        while (j < right.length) {
            result.push(right[j++])
        }
        return result
    }
    var mid = Math.floor(arr.length / 2)
    var left = mergeSort(arr.slice(0, mid))
    var right = mergeSort(arr.slice(mid))
    return merge(left, right)
}

3.3.2

function mergeSort(arr) {
  if (arr.length <= 1) return arr;
  const mid = Math.floor(arr.length / 2);
  const left = mergeSort(arr.slice(0, mid));
  const right = mergeSort(arr.slice(mid));
  return merge(left, right);
}

function merge(left, right) {
  let result = [];
  while (left.length && right.length) {
    left[0] < right[0] ? result.push(left.shift()) : result.push(right.shift());
  }
  return result.concat(left, right);
}

4. 快速排序

4.1 说明

  1. 快速排序的思路为,找出一个基准数,然后从数组的两端开始,分别与基准数进行比较

4.2 实现代码

// 定义快速排序函数,参数为待排序的数组
function quickSort(array: number[]): number[] {
    // 定义辅助函数,用于排序
    function sort(left: number, right: number): void {
        // 如果左边的索引比右边的索引大,说明区间内已经没有数据,退出函数
        if (left >= right) {
            return;
        }
        // 取出基准数
        let pivot = array[left];
        // 定义两个指针
        let i = left;
        let j = right;
        // 开始排序
        while (i < j) {
            // 从右边开始搜索,直到找到比基准数小的数
            while (i < j && array[j] >= pivot) {
                j--;
            }
            // 如果找到了,则将该数存放在左边
            if (i < j) {
                array[i] = array[j];
                i++;
            }
            // 从左边开始搜索,直到找到比基准数大的数
            while (i < j && array[i] <= pivot) {
                i++;
            }
            // 如果找到了,则将该数存放在右边
            if (i < j) {
                array[j] = array[i];
                j--;
            }
        }
        // 将基准数存放在最终的位置上
        array[i] = pivot;
        // 递归处理基准数左边的数据
        sort(left, i - 1);
        // 递归处理基准数右边的数据
        sort(i + 1, right);
    }
    // 调用辅助函数,开始排序
    sort(0, array.length - 1);
    // 返回排序后的数组
    return array;
}

5. 插入排序

5.1 说明

插入排序的思想为选择一个数,与一个有序数组进行比较,找到小与该数的位置插入

5.2 实现代码

function insertionSort(arr: number[]): number[] {
  // 对于数组的每一个元素,从它开始到0位置,比较该元素和前一个元素的大小
  for (let i = 1; i < arr.length; i++) {
    let current = arr[i];
    let j = i - 1;
    // 如果该元素小于前一个元素,那么前一个元素向后移动,并继续向前比较
    while (j >= 0 && arr[j] > current) {
      arr[j + 1] = arr[j];
      j--;
    }
    // 如果该元素大于前一个元素,那么它将放到合适的位置
    arr[j + 1] = current;
  }
  // 返回排序后的数组
  return arr;
}
 
// 测试数据
const testArr = [5, 2, 9, 1, 5, 6];
// 调用插入排序函数
const sortedArr = insertionSort(testArr);
// 打印结果
console.log(sortedArr);

6. 希尔排序

6.1 说明

希尔排揎为插入排序的改进方法,先将数组分组,然后每个子数组再进行排序

6.2 实现代码

function shellSort(arr) {
  // 定义增量, 每次分组, 增量为数组长度的一半
  let gap = Math.floor(arr.length / 2);
  while (gap > 0) {
    // 按组进行排序
    for (let i = gap; i < arr.length; i++) {
      // 获取当前元素
      let current = arr[i];
      let j = i;
      // 将相邻元素比较, 满足条件就后移
      while (j >= gap && arr[j - gap] > current) {
        arr[j] = arr[j - gap];
        j -= gap;
      }
      // 将当前元素插入合适的位置
      arr[j] = current;
    }
    // 每次递减增量, 直到为1
    gap = Math.floor(gap / 2);
  }
  return arr;
}

7. 基数排序

7.1 说明

  1. 按位数进行排序
  2. 只适合整数

7.2 实现代码

function radixSort(arr) {
  // 找到数组中的最大数
  const max = Math.max(...arr);
  // 找到最大数的位数
  const maxDigitCount = String(max).length;
  // 遍历位数
  for (let k = 0; k < maxDigitCount; k++) {
    // 创建桶
    const digitBuckets = Array.from({ length: 10 }, () => []);
    // 遍历数组
    for (let i = 0; i < arr.length; i++) {
      // 获取位数对应的值
      const digit = getDigit(arr[i], k);
      // 将数添加到对应的数对应的桶中
      digitBuckets[digit].push(arr[i]);
    }
    // 依次合并桶中的数
    arr = [].concat(...digitBuckets);
  }
  
  return arr;
}

function getDigit(num, place) {
  return Math.floor(Math.abs(num) / Math.pow(10, place)) % 10;
}

8. 计数排序

8.1 说明

非比较排序,适用于整数

8.2 实现代码

function countingSort(arr) {
  // 获取最大数
  const max = Math.max(...arr);
  // 创建有序的数组
  const count = new Array(max + 1).fill(0);
  const output = new Array(arr.length);
  // 遍历进行计数
  arr.forEach(num => count[num]++);
  
  for (let i = 1; i < count.length; i++) {
    count[i] += count[i - 1];
  }
  
  for (let i = arr.length - 1; i >= 0; i--) {
    output[count[arr[i]] - 1] = arr[i];
    count[arr[i]]--;
  }
  
  return output;
}

9. 桶排序

9.1 说明

将元素分到有限数量的桶里再排序

9.2 实现代码

function bucketSort(arr, bucketSize = 5) {
  if (arr.length === 0) return arr;
  
  const min = Math.min(...arr);
  const max = Math.max(...arr);
  const bucketCount = Math.floor((max - min) / bucketSize) + 1;
  const buckets = new Array(bucketCount).fill().map(() => []);
  
  arr.forEach(num => {
    const bucketIndex = Math.floor((num - min) / bucketSize);
    buckets[bucketIndex].push(num);
  });
  
  const result = [];
  buckets.forEach(bucket => {
    insertionSort(bucket); // 可以使用其他排序算法
    result.push(...bucket);
  });
  
  return result;
}

10. 堆排序

10.1 说明

利用堆数据结构设计

10.2 实现代码

function heapSort(arr) {
  let len = arr.length;
  for (let i = Math.floor(len / 2) - 1; i >= 0; i--) {
    heapify(arr, len, i);
  }
  for (let i = len - 1; i > 0; i--) {
    [arr[0], arr[i]] = [arr[i], arr[0]];
    heapify(arr, i, 0);
  }
  return arr;
}

function heapify(arr, len, i) {
  let largest = i;
  let left = 2 * i + 1;
  let right = 2 * i + 2;
  if (left < len && arr[left] > arr[largest]) largest = left;
  if (right < len && arr[right] > arr[largest]) largest = right;
  if (largest !== i) {
    [arr[i], arr[largest]] = [arr[largest], arr[i]];
    heapify(arr, len, largest);
  }
}

总结

排序算法 时间复杂度(平均) 空间复杂度 稳定性
冒泡排序 O(n²) O(1) 稳定
选择排序 O(n²) O(1) 不稳定
归并排序 O(n log n) O(n) 稳定
快速排序 O(n log n) O(log n) 不稳定
插入排序 O(n²) O(1) 稳定
希尔排序 O(n log n) O(1) 不稳定
基数排序 O(nk) O(n + k) 稳定
计数排序 O(n + k) O(k) 稳定
桶排序 O(n + k) O(n + k) 稳定
堆排序 O(n log n) O(1) 不稳定

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2405635.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

使用vue3+ts+input封装上传组件,上传文件显示文件图标

效果图&#xff1a; 代码 <template><div class"custom-file-upload"><div class"upload"><!-- 显示已选择的文件 --><div class"file-list"><div v-for"(item, index) in state.filsList" :key&q…

【Linux】Ubuntu 创建应用图标的方式汇总,deb/appimage/通用方法

Ubuntu 创建应用图标的方式汇总&#xff0c;deb/appimage/通用方法 对于标准的 Ubuntu&#xff08;使用 GNOME 桌面&#xff09;&#xff0c;desktop 后缀的桌面图标文件主要保存在以下三个路径&#xff1a; 当前用户的桌面目录&#xff08;这是最常见的位置&#xff09;。所…

LangGraph--Agent工作流

Agent的工作流 下面展示了如何创建一个“计划并执行”风格的代理。 这在很大程度上借鉴了 计划和解决 论文以及Baby-AGI项目。 核心思想是先制定一个多步骤计划&#xff0c;然后逐项执行。完成一项特定任务后&#xff0c;您可以重新审视计划并根据需要进行修改。 般的计算图如…

Spring Boot 常用注解面试题深度解析

&#x1f91f;致敬读者 &#x1f7e9;感谢阅读&#x1f7e6;笑口常开&#x1f7ea;生日快乐⬛早点睡觉 &#x1f4d8;博主相关 &#x1f7e7;博主信息&#x1f7e8;博客首页&#x1f7eb;专栏推荐&#x1f7e5;活动信息 文章目录 Spring Boot 常用注解面试题深度解析一、核心…

Linux系统的CentOS7发行版安装MySQL80

文章目录 前言Linux命令行内的”应用商店”安装CentOS的安装软件的yum命令安装MySQL1. 配置yum仓库2. 使用yum安装MySQL3. 安装完成后&#xff0c;启动MySQL并配置开机自启动4. 检查MySQL的运行状态 MySQL的配置1. 获取MySQL的初始密码2. 登录MySQL数据库系统3. 修改root密码4.…

408第一季 - 数据结构 - 栈与队列

栈 闲聊 栈是一个线性表 栈的特点是后进先出 然后是一个公式 比如123要入栈&#xff0c;一共有5种排列组合的出栈 栈的数组实现 这里有两种情况&#xff0c;&#xff0c;一个是有下标为-1的&#xff0c;一个没有 代码不用看&#xff0c;真题不会考 栈的链式存储结构 L ->…

【RTP】Intra-Refresh模式下的 H.264 输出,RTP打包的方式和普通 H.264 流并没有本质区别

对于 Intra-Refresh 模式下的 H.264 输出,RTP 打包 的方式和普通 H.264 流并没有本质区别:你依然是在对一帧一帧的 NAL 单元进行 RTP 分包,只不过这些 NAL 单元内部有部分宏块是 “帧内编码” 而已。下面分步骤说明: 1. 原理回顾:RFC 6184 H.264 over RTP 按照 RFC 6184 …

Redis实战-消息队列篇

前言&#xff1a; 讲讲做消息队列遇到的问题。 今日所学&#xff1a; 异步优化消息队列基于stream实现异步下单 1. 异步优化 1.1 需求分析 1.1.1 现有下单流程&#xff1a; 1.查询优惠劵 2.判断是否是秒杀时间&#xff0c;库存是否充足 3.实现一人一单 在这个功能中&…

(三)Linux性能优化-CPU-CPU 使用率

CPU使用率 user&#xff08;通常缩写为 us&#xff09;&#xff0c;代表用户态 CPU 时间。注意&#xff0c;它不包括下面的 nice 时间&#xff0c;但包括了 guest 时间。nice&#xff08;通常缩写为 ni&#xff09;&#xff0c;代表低优先级用户态 CPU 时间&#xff0c;也就是进…

佰力博科技与您探讨材料介电性能测试的影响因素

1、频率依赖性 材料的介电性能通常具有显著的频率依赖性。在低频下&#xff0c;偶极子的取向极化占主导&#xff0c;介电常数较高&#xff1b;而在高频下&#xff0c;偶极子的取向极化滞后&#xff0c;导致介电常数下降&#xff0c;同时介电损耗增加。例如&#xff0c;VHB4910…

K8S认证|CKS题库+答案| 4. RBAC - RoleBinding

目录 4. RBAC - RoleBinding 免费获取并激活 CKA_v1.31_模拟系统 题目 开始操作&#xff1a; 1&#xff09;、切换集群 2&#xff09;、查看SA和role 3&#xff09;、编辑 role-1 权限 4&#xff09;、检查role 5&#xff09;、创建 role和 rolebinding 6&#xff0…

React 新项目

使用git bash 创建一个新项目 建议一开始就创建TS项目 原因在Webpack中改配置麻烦 编译方法:ts compiler 另一种 bable 最好都配置 $ create-react-app cloundmusic --template typescript 早期react项目 yarn 居多 目前npm包管理居多 目前pnpm不通用 icon 在public文件夹中…

AI编程在BOSS项目的实践经验分享

前言 在人工智能技术革新浪潮的推动下&#xff0c;智能编程助手正以前所未有的速度重塑开发领域。这些基于AI的代码辅助工具通过智能提示生成、实时错误检测和自动化重构等功能&#xff0c;显著提升了软件工程的全流程效率。无论是初入行业的开发者还是资深程序员&#xff0c;…

数学:”度量空间”了解一下?

度量空间是现代数学中一种基本且重要的抽象空间。以下是对它的详细介绍&#xff1a; 定义 相关概念 常见的度量空间举例 度量空间的类型 度量空间的作用 度量空间是拓扑空间的一种特殊情况&#xff0c;它为拓扑空间的研究提供了具体的模型和实例。同时&#xff0c;度量空间在…

jenkins脚本查看及备份

位置与备份 要完整备份 Jenkins 的所有脚本和相关配置&#xff0c;包括 Jenkinsfile、构建脚本&#xff08;如 .sh / .bat&#xff09;、Job 配置、插件、凭据等&#xff0c;你可以从两个层面入手&#xff1a; ✅ 一、完整备份 Jenkins 主目录&#xff08;最全面&#xff09; …

用电脑通过网口控制keysight示波器

KEYSIGHT示波器HD304MSO性能 亮点: 体验 200 MHz 至 1 GHz 的带宽和 4 个模拟通道。与 12 位 ADC 相比,使用 14 位模数转换器 (ADC) 将垂直分辨率提高四倍。使用 10.1 英寸电容式触摸屏轻松查看和分析您的信号。捕获 50 μVRMS 本底噪声的较小信号。使用独有区域触摸在几秒…

《如何使用MinGW-w64编译OpenCV和opencv_contrib》

《如何使用MinGW-w64编译OpenCV和opencv_contrib》 在Windows环境下使用MinGW编译OpenCV和opencv_contrib是一个常见需求,尤其是对于那些希望使用GCC工具链而非Visual Studio的开发者。下面我将详细介绍这个过程。 准备工作 首先需要安装和准备以下工具和库: MinGW(建议使…

模拟搭建私网访问外网、外网访问服务器服务的实践操作

目录 实验环境 实践要求 一、准备工作 1、准备四台虚拟机&#xff0c;分别标号 2、 防火墙额外添加两块网卡&#xff0c;自定义网络连接模式 3、 关闭虚拟机的图形管理工具 4、关闭防火墙 5、分别配置四台虚拟机的IP地址&#xff0c;此处举一个例子&#xff08;使用的临…

vue中Echarts的使用

文章目录 Echarts概述什么是EchartsEcharts的好处 Vue中Echarts的使用Echarts的安装Echarts的引入 Echarts概述 什么是Echarts Apache ECharts&#xff1a;一个基于 JavaScript 的开源可视化图表库。 其官网如下&#xff1a;https://echarts.apache.org/zh/index.html Echar…

【C++项目】负载均衡在线OJ系统-1

文章目录 前言项目结果演示技术栈&#xff1a;结构与总体思路compiler编译功能-common/util.hpp 拼接编译临时文件-common/log.hpp 开放式日志-common/util.hpp 获取时间戳方法-秒级-common/util.hpp 文件是否存在-compile_server/compiler.hpp 编译功能编写&#xff08;重要&a…