数据结构基础之排序算法
在数据结构中,常见的排序算法有以下几种:
- 冒泡排序(Bubble Sort):通过比较相邻元素并交换它们的位置,每轮将最大(或最小)的元素冒泡到末尾,重复执行直到排序完成。
function bubbleSort(arr) {const n = arr.length;for (let i = 0; i < n - 1; i++) {for (let j = 0; j < n - i - 1; j++) {if (arr[j] > arr[j + 1]) {[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];}}}return arr;
}const arr = [64, 34, 25, 12, 22, 11, 90];
console.log(bubbleSort(arr)); // Output: [11, 12, 22, 25, 34, 64, 90]
特点:简单易懂,但对于大型数据集效率较低。
时间复杂度:
最优情况:O(n)(当数组已经排序好时)。
平均情况:O(n^2)。
最坏情况:O(n^2)。
- 插入排序(Insertion Sort):将数组分为已排序和未排序两部分,每次从未排序部分选择一个元素插入到已排序部分的正确位置,重复执行直到排序完成。
function insertionSort(arr) {const n = arr.length;for (let i = 1; i < n; i++) {let key = arr[i];let j = i - 1;while (j >= 0 && arr[j] > key) {arr[j + 1] = arr[j];j--;}arr[j + 1] = key;}return arr;
}const arr = [64, 34, 25, 12, 22, 11, 90];
console.log(insertionSort(arr)); // Output: [11, 12, 22, 25, 34, 64, 90]
特点:适用于小型数据集和部分有序数组。
时间复杂度:
最优情况:O(n)(当数组已经排序好时)。
平均情况:O(n^2)。
最坏情况:O(n^2)。
- 选择排序(Selection Sort):每轮从未排序部分选择最小(或最大)的元素,将其与未排序部分的首元素交换,重复执行直到排序完成。
function selectionSort(arr) {const n = arr.length;for (let i = 0; i < n - 1; i++) {let minIdx = i;for (let j = i + 1; j < n; j++) {if (arr[j] < arr[minIdx]) {minIdx = j;}}[arr[i], arr[minIdx]] = [arr[minIdx], arr[i]];}return arr;
}const arr = [64, 34, 25, 12, 22, 11, 90];
console.log(selectionSort(arr)); // Output: [11, 12, 22, 25, 34, 64, 90]
特点:简单易懂,但对于大型数据集效率较低。
时间复杂度:
最优情况:O(n^2)。
平均情况:O(n^2)。
最坏情况:O(n^2)。
- 快速排序(Quick Sort):通过选取一个基准元素,将数组分成比基准元素小和大的两部分,然后递归地对两部分进行排序。
function quickSort(arr) {if (arr.length <= 1) return arr;const pivot = arr[0];const left = [];const right = [];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 = [64, 34, 25, 12, 22, 11, 90];
console.log(quickSort(arr)); // Output: [11, 12, 22, 25, 34, 64, 90]
特点:高效且被广泛使用的排序算法。
时间复杂度:
最优情况:O(n log n)。
平均情况:O(n log n)。
最坏情况:O(n^2)。
- 归并排序(Merge Sort):将数组不断分割成较小的子数组,然后再将子数组按顺序合并,重复执行直到排序完成。
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) {const mergedArr = [];let leftIdx = 0;let rightIdx = 0;while (leftIdx < left.length && rightIdx < right.length) {if (left[leftIdx] < right[rightIdx]) {mergedArr.push(left[leftIdx]);leftIdx++;} else {mergedArr.push(right[rightIdx]);rightIdx++;}}return [...mergedArr, ...left.slice(leftIdx), ...right.slice(rightIdx)];
}const arr = [64, 34, 25, 12, 22, 11, 90];
console.log(mergeSort(arr)); // Output: [11, 12, 22, 25, 34, 64, 90]
特点:稳定的排序算法,适用于大型数据集。
时间复杂度:
最优情况:O(n log n)。
平均情况:O(n log n)。
最坏情况:O(n log n)。
- 堆排序(Heap Sort):利用二叉堆(最大堆或最小堆)的特性进行排序,将堆顶元素与最后一个元素交换,然后重建堆,重复执行直到排序完成。
function heapSort(arr) {const n = arr.length;for (let i = Math.floor(n / 2) - 1; i >= 0; i--) {heapify(arr, n, i);}for (let i = n - 1; i >= 0; i--) {[arr[0], arr[i]] = [arr[i], arr[0]];heapify(arr, i, 0);}return arr;
}function heapify(arr, n, i) {let largest = i;const left = 2 * i + 1;const right = 2 * i + 2;if (left < n && arr[left] > arr[largest]) {largest = left;}if (right < n && arr[right] > arr[largest]) {largest = right;}if (largest !== i) {[arr[i], arr[largest]] = [arr[largest], arr[i]];heapify(arr, n, largest);}
}const arr = [64, 34, 25, 12, 22, 11, 90];
console.log(heapSort(arr)); // Output: [11, 12, 22, 25, 34, 64, 90]
特点:高效的原地排序算法。
时间复杂度:
最优情况:O(n log n)。
平均情况:O(n log n)。
最坏情况:O(n log n)。
- 希尔排序(Shell Sort):是插入排序的一种改进算法,通过分组进行插入排序,逐渐缩小分组间隔,直到分组间隔为1。
function shellSort(arr) {const n = arr.length;for (let gap = Math.floor(n / 2); gap > 0; gap = Math.floor(gap / 2)) {for (let i = gap; i < n; i++) {let temp = arr[i];let j;for (j = i; j >= gap && arr[j - gap] > temp; j -= gap) {arr[j] = arr[j - gap];}arr[j] = temp;}}return arr;
}const arr = [64, 34, 25, 12, 22, 11, 90];
console.log(shellSort(arr)); // Output: [11, 12, 22, 25, 34, 64, 90]
特点:插入排序的改进版本,适用于中等大小的数据集。
时间复杂度:
最优情况:O(n log^2 n)(取决于步长序列)。
平均情况:取决于步长序列。
最坏情况:取决于步长序列。
- 计数排序(Counting Sort):适用于一定范围内的整数排序,通过统计每个元素出现的次数,然后计算每个元素的位置,重复执行直到排序完成。
function countingSort(arr) {const n = arr.length;let max = Math.max(...arr);let min = Math.min(...arr);const range = max - min + 1;const count = Array(range).fill(0);const output = Array(n);for (let i = 0; i < n; i++) {count[arr[i] - min]++;}for (let i = 1; i < range; i++) {count[i] += count[i - 1];}for (let i = n - 1; i >= 0; i--) {output[count[arr[i] - min] - 1] = arr[i];count[arr[i] - min]--;}for (let i = 0; i < n; i++) {arr[i] = output[i];}return arr;
}const arr = [64, 34, 25, 12, 22, 11, 90];
console.log(countingSort(arr)); // Output: [11, 12, 22, 25, 34, 64, 90]
特点:适用于小范围整数排序。
时间复杂度:O(n + k),其中 n 是输入数组元素个数,k 是输入范围大小。
- 桶排序(Bucket Sort):将元素根据一定规则放入不同的桶中,每个桶内部进行排序,然后按顺序合并桶内的元素,重复执行直到排序完成。
function bucketSort(arr, bucketSize = 5) {if (arr.length === 0) return arr;const max = Math.max(...arr);const min = Math.min(...arr);const bucketCount = Math.floor((max - min) / bucketSize) + 1;const buckets = Array(bucketCount).fill().map(() => []);for (let i = 0; i < arr.length; i++) {const bucketIndex = Math.floor((arr[i] - min) / bucketSize);buckets[bucketIndex].push(arr[i]);}arr.length = 0;for (let i = 0; i < buckets.length; i++) {insertionSort(buckets[i]);arr.push(...buckets[i]);}return arr;
}const arr = [64, 34, 25, 12, 22, 11, 90];
console.log(bucketSort(arr)); // Output: [11, 12, 22, 25, 34, 64, 90]
特点:适用于均匀分布的数据。
时间复杂度:O(n + k),其中 n 是输入数组元素个数,k 是桶的个数。
- 基数排序(Radix Sort):按照位数将元素分配到不同的桶中,然后按顺序合并桶内的元素,重复执行直到所有位数排序完成。
function radixSort(arr) {const max = Math.max(...arr);const maxLength = String(max).length;let bucket = Array.from({ length: 10 }, () => []);for (let i = 0; i < maxLength; i++) {for (let j = 0; j < arr.length; j++) {const digit = Math.floor(arr[j] / 10 ** i) % 10;bucket[digit].push(arr[j]);}arr.length = 0;for (let k = 0; k < bucket.length; k++) {arr.push(...bucket[k]);bucket[k].length = 0;}}return arr;
}const arr = [64, 34, 25, 12, 22, 11, 90];
console.log(radixSort(arr)); // Output: [11, 12, 22, 25, 34, 64, 90]
特点:适用于数字位数相同的整数排序。
时间复杂度:O(d * (n + k)),其中 d 是最大数字的位数,n 是输入数组元素个数,k 是输入范围大小。
每种排序算法都有不同的时间复杂度和适用场景。在实际应用中,根据数据规模和性能要求选择合适的排序算法是很重要的。
相关文章:
数据结构基础之排序算法
在数据结构中,常见的排序算法有以下几种: 冒泡排序(Bubble Sort):通过比较相邻元素并交换它们的位置,每轮将最大(或最小)的元素冒泡到末尾,重复执行直到排序完成。 fun…...
Spark(37):Streaming DataFrame 和 Streaming DataSet 创建
目录 0. 相关文章链接 1. 概述 2. socket source 3. file source 3.1. 读取普通文件夹内的文件 3.2. 读取自动分区的文件夹内的文件 4. kafka source 4.1. 导入依赖 4.2. 以 Streaming 模式创建 Kafka 工作流 4.3. 通过 Batch 模式创建 Kafka 工作流 5. Rate Source…...
SpringBoot集成Thymeleaf
Spring Boot 集成 Thymeleaf 模板引擎 1、Thymeleaf 介绍 Thymeleaf 是适用于 Web 和独立环境的现代服务器端 Java 模板引擎。 Thymeleaf 的主要目标是为开发工作流程带来优雅的自然模板,既可以在浏览器中正确显示的 HTML,也可以用作静态原型…...
算法练习(2):牛客在线编程03 二叉树
package jz.bm;import jz.TreeNode;import java.util.*;public class bm3 {/*** BM23 二叉树的前序遍历*/public int[] preorderTraversal (TreeNode root) {ArrayList<Integer> list new ArrayList<>();preOrder(root, list);int[] res new int[list.size()];fo…...
回归预测 | MATLAB实现TCN-BiLSTM时间卷积双向长短期记忆神经网络多输入单输出回归预测
回归预测 | MATLAB实现TCN-BiLSTM时间卷积双向长短期记忆神经网络多输入单输出回归预测 目录 回归预测 | MATLAB实现TCN-BiLSTM时间卷积双向长短期记忆神经网络多输入单输出回归预测预测效果基本介绍模型描述程序设计参考资料 预测效果 基本介绍 1.MATLAB实现TCN-BiLSTM时间卷积…...
Linux 系列 常见 快捷键总结
强制停止 Ctrl C 退出程序、退出登录 Ctrl D 等价 exit 查看历史命令 history !命令前缀,自动匹配上一个命令 (历史命令中:从最新——》最老 搜索) ctrl r 输入内去历史命令中检索 # 回车键可以直接执行 ctrl a 跳到命令开头 …...
OA系统构建排座
目录 一.排座的介绍,作用 1.排座介绍 A.前端实现 B.数据库实现 C.后端实现 2.排座作用 A.座位预订 B.座位安排 C. 实时座位状态显示 二.利用Layui实现排座 1.基础版(通过htmlcssjs实现) A.基础版源码(html): 2.进阶版 …...
微信小程序 居中、居右、居底和横向、纵向布局,文字在图片中间,网格布局
微信小程序居中、居右、横纵布局 1、水平垂直居中(相对父类控件)方式一:水平垂直居中 父类控件: display: flex;align-items: center;//子控件垂直居中justify-content: center;//子控件水平居中width: 100%;height: 400px //注意…...
【C++】总结2
文章目录 1.final和override关键字2.extern "C"的用法3.野指针和垂悬指针(悬空指针)4.指针指向的内存被释放是什么意思5.C和C的类型安全6.C中的重载、重写(覆盖)和隐藏的区别 1.final和override关键字 final和override是C11引入的关键字&…...
vue2项目中使用svg图标
在开发项目的时候经常会用到svg矢量图,而且我们使用SVG以后,页面上加载的不再是图片资源, 这对页面性能来说是个很大的提升,而且我们SVG文件比img要小的很多,放在项目中几乎不占用资源。 1、安装SVG依赖插件并配置加载器和路径 npm instal…...
阿里云盘自动每日签到无需部署无需服务器(仅限学习交流使用)
一、前言 阿里云盘自动每日签到,无需部署,无需服务器 执行思路:使用金山文档的每日定时任务,执行阿里云盘签到接口。 二、效果展示: 三、步骤: 1、进入金山文档网页版 金山文档官网:https:…...
Blazor前后端框架Known-V1.2.7
V1.2.7 Known是基于C#和Blazor开发的前后端分离快速开发框架,开箱即用,跨平台,一处代码,多处运行。 Gitee: https://gitee.com/known/KnownGithub:https://github.com/known/Known 概述 基于C#和Blazor…...
工业边缘计算为什么?
在工厂环境中使用边缘计算并不新鲜。可编程逻辑控制器(PLC)、微控制器、服务器和PC进行本地数据处理,甚至是微型数据中心都是边缘技术,已经在工厂系统中存在了几十年。在车间里看到的看板系统,打卡系统,历史…...
Training-Time-Friendly Network for Real-Time Object Detection 论文学习
1. 解决了什么问题? 目前的目标检测器很少能做到快速训练、快速推理,并同时保持准确率。直觉上,推理越快的检测器应该训练也很快,但大多数的实时检测器反而需要更长的训练时间。准确率高的检测器大致可分为两类:推理时…...
HTTP改HTTPS
tomcat中http协议改https 第一步,配置server.xml <?xml version"1.0" encoding"UTF-8"?> <Server port"8005" shutdown"SHUTDOWN"><Listener className"org.apache.catalina.startup.VersionLogger…...
网络层中一些零碎且易忘的知识点
异构网络:指传输介质、数据编码方式、链路控制协议以及数据单元格式和转发机制不同,异构即物理层和数据链路层均不同RIP、OSPF、BGP分别是哪一层的协议: -RIPOSPFBGP所属层次应用层网络层应用层封装在什么协议中UDPIPTCP 一个主机可以有多个I…...
【RabbitMQ】之高可用集群搭建
目录 一、RabbitMQ 集群原理 1、默认集群原理2、镜像集群原理3、负载均衡方案 二、RabbitMQ 高可用集群搭建 1、RabbitMQ 集群搭建2、配置镜像队列3、HAProxy 环境搭建4、Keepalived 环境搭建 一、RabbitMQ 集群简介 1、默认集群原理 3-1、RabbitMQ 集群简介 单台 RabbitM…...
【node.js】01-fs读写文件内容
目录 一、fs.readFile() 读取文件内容 二、fs.writeFile() 向指定的文件中写入内容 案例:整理txt 需求: 代码: 一、fs.readFile() 读取文件内容 代码: //导入fs模块,从来操作文件 const fs require(fs)// 2.调…...
GitHub仓库如何使用
核心:GitHub仓库如何使用 目录 1.创建仓库: 2.克隆仓库到本地: 3.添加、提交和推送更改: 4.分支管理: 5.拉取请求(Pull Requests): 6.合并代码: 7.其他功能&…...
雪花算法,在分布式环境下实现高效的ID生成
其实雪花算法比较简单,可能称不上什么算法就是一种构造UID的方法。 点1:UID是一个long类型的41位时间戳,10位存储机器码,12位存储序列号。 点2:时间戳的单位是毫秒,可以同时链接1024台机器,每台…...
调用支付宝接口响应40004 SYSTEM_ERROR问题排查
在对接支付宝API的时候,遇到了一些问题,记录一下排查过程。 Body:{"datadigital_fincloud_generalsaas_face_certify_initialize_response":{"msg":"Business Failed","code":"40004","sub_msg…...
Mybatis逆向工程,动态创建实体类、条件扩展类、Mapper接口、Mapper.xml映射文件
今天呢,博主的学习进度也是步入了Java Mybatis 框架,目前正在逐步杨帆旗航。 那么接下来就给大家出一期有关 Mybatis 逆向工程的教学,希望能对大家有所帮助,也特别欢迎大家指点不足之处,小生很乐意接受正确的建议&…...
什么是库存周转?如何用进销存系统提高库存周转率?
你可能听说过这样一句话: “利润不是赚出来的,是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业,很多企业看着销售不错,账上却没钱、利润也不见了,一翻库存才发现: 一堆卖不动的旧货…...
Qwen3-Embedding-0.6B深度解析:多语言语义检索的轻量级利器
第一章 引言:语义表示的新时代挑战与Qwen3的破局之路 1.1 文本嵌入的核心价值与技术演进 在人工智能领域,文本嵌入技术如同连接自然语言与机器理解的“神经突触”——它将人类语言转化为计算机可计算的语义向量,支撑着搜索引擎、推荐系统、…...
数据库分批入库
今天在工作中,遇到一个问题,就是分批查询的时候,由于批次过大导致出现了一些问题,一下是问题描述和解决方案: 示例: // 假设已有数据列表 dataList 和 PreparedStatement pstmt int batchSize 1000; // …...
OPenCV CUDA模块图像处理-----对图像执行 均值漂移滤波(Mean Shift Filtering)函数meanShiftFiltering()
操作系统:ubuntu22.04 OpenCV版本:OpenCV4.9 IDE:Visual Studio Code 编程语言:C11 算法描述 在 GPU 上对图像执行 均值漂移滤波(Mean Shift Filtering),用于图像分割或平滑处理。 该函数将输入图像中的…...
《C++ 模板》
目录 函数模板 类模板 非类型模板参数 模板特化 函数模板特化 类模板的特化 模板,就像一个模具,里面可以将不同类型的材料做成一个形状,其分为函数模板和类模板。 函数模板 函数模板可以简化函数重载的代码。格式:templa…...
Linux 内存管理实战精讲:核心原理与面试常考点全解析
Linux 内存管理实战精讲:核心原理与面试常考点全解析 Linux 内核内存管理是系统设计中最复杂但也最核心的模块之一。它不仅支撑着虚拟内存机制、物理内存分配、进程隔离与资源复用,还直接决定系统运行的性能与稳定性。无论你是嵌入式开发者、内核调试工…...
Python Ovito统计金刚石结构数量
大家好,我是小马老师。 本文介绍python ovito方法统计金刚石结构的方法。 Ovito Identify diamond structure命令可以识别和统计金刚石结构,但是无法直接输出结构的变化情况。 本文使用python调用ovito包的方法,可以持续统计各步的金刚石结构,具体代码如下: from ovito…...
Git常用命令完全指南:从入门到精通
Git常用命令完全指南:从入门到精通 一、基础配置命令 1. 用户信息配置 # 设置全局用户名 git config --global user.name "你的名字"# 设置全局邮箱 git config --global user.email "你的邮箱example.com"# 查看所有配置 git config --list…...
