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

探究排序算法:比较与非比较排序算法及性能分析

探究排序算法:比较与非比较排序算法及性能分析

排序算法是计算机科学中的基本问题,它涉及将一组元素按照特定的顺序排列。本文将深入介绍比较排序算法和非比较排序算法,包括每个算法的原理、Java代码示例以及它们的性能分析和比较。

比较排序算法

1. 冒泡排序(Bubble Sort)

原理:冒泡排序通过多次遍历数组,比较相邻元素并交换,使较大的元素逐渐“冒泡”到数组的尾部。

代码示例

public class BubbleSort {public static void bubbleSort(int[] array) {int n = array.length;for (int i = 0; i < n - 1; i++) {for (int j = 0; j < n - i - 1; j++) {if (array[j] > array[j + 1]) {int temp = array[j];array[j] = array[j + 1];array[j + 1] = temp;}}}}public static void main(String[] args) {int[] array = {64, 34, 25, 12, 22, 11, 90};bubbleSort(array);System.out.println("冒泡排序结果:");for (int num : array) {System.out.print(num + " ");}}
}

2. 插入排序(Insertion Sort)

原理:插入排序将数组分为已排序和未排序两部分,逐个将未排序元素插入到已排序部分的正确位置。

代码示例

public class InsertionSort {public static void insertionSort(int[] array) {int n = array.length;for (int i = 1; i < n; i++) {int key = array[i];int j = i - 1;while (j >= 0 && array[j] > key) {array[j + 1] = array[j];j--;}array[j + 1] = key;}}public static void main(String[] args) {int[] array = {12, 11, 13, 5, 6};insertionSort(array);System.out.println("插入排序结果:");for (int num : array) {System.out.print(num + " ");}}
}

3. 选择排序(Selection Sort)

原理:选择排序在未排序部分找到最小元素,然后与已排序部分的末尾元素交换,逐步构建有序序列。

代码示例

public class SelectionSort {public static void selectionSort(int[] array) {int n = array.length;for (int i = 0; i < n - 1; i++) {int minIndex = i;for (int j = i + 1; j < n; j++) {if (array[j] < array[minIndex]) {minIndex = j;}}int temp = array[minIndex];array[minIndex] = array[i];array[i] = temp;}}public static void main(String[] args) {int[] array = {64, 25, 12, 22, 11};selectionSort(array);System.out.println("选择排序结果:");for (int num : array) {System.out.print(num + " ");}}
}

4. 希尔排序(Shell Sort)

原理:希尔排序是插入排序的改进,通过将数组分为多个子序列来进行排序,逐渐减小步长,最终使整个数组基本有序。

代码示例

public class ShellSort {public static void shellSort(int[] array) {int n = array.length;for (int gap = n / 2; gap > 0; gap /= 2) {for (int i = gap; i < n; i++) {int temp = array[i];int j = i;while (j >= gap && array[j - gap] > temp) {array[j] = array[j - gap];j -= gap;}array[j] = temp;}}}public static void main(String[] args) {int[] array = {12, 34, 54, 2, 3};shellSort(array);System.out.println("希尔排序结果:");for (int num : array) {System.out.print(num + " ");}}
}

5. 快速排序(Quick Sort)

原理:快速排序使用分治法,选择一个基准元素,将数组分成左右两部分,左边的元素小于基准,右边的元素大于基准,然后对左右子数组递归地应用快速排序。

代码示例

public class QuickSort {public static void quickSort(int[] array, int low, int high) {if (low < high) {int pivotIndex = partition(array, low, high);quickSort(array, low, pivotIndex - 1);quickSort(array, pivotIndex + 1, high);}}public static int partition(int[] array, int low, int high) {int pivot = array[high];int i = low - 1;for (int j = low; j < high; j++) {if (array[j] < pivot) {i++;int temp = array[i];array[i] = array[j];array[j] = temp;}}int temp = array[i + 1];array[i + 1] = array[high];array[high] = temp;return i + 1;}public static void main(String[] args) {int[] array = {10, 7, 8, 9, 1, 5};int n = array.length;quickSort(array, 0, n - 1);System.out.println("快速排序结果:");for (int num : array) {System.out.print(num + " ");}}
}

6. 归并排序(Merge Sort)

原理:归并排序是一种分治算法,将数组逐步分成两个子数组,分别排序后再合并成一个有序数组。

代码示例

public class MergeSort {public static void mergeSort(int[] array, int left, int right) {if (left < right) {int mid = (left + right) / 2;mergeSort(array, left, mid);mergeSort(array, mid + 1, right);merge(array, left, mid, right);}}public static void merge(int[] array, int left, int mid, int right) {int n1 = mid - left + 1;int n2 = right - mid;int[] leftArray = new int[n1];int[] rightArray = new int[n2];for (int i = 0; i < n1; i++) {leftArray[i] = array[left + i];}for (int j = 0; j < n2; j++) {rightArray[j] = array[mid + 1 + j];}int i = 0, j = 0, k = left;while (i < n1 && j < n2) {if (leftArray[i] <= rightArray[j]) {array[k] = leftArray[i];i++;} else {array[k] = rightArray[j];j++;}k++;}while (i < n1) {array[k] = leftArray[i];i++;k++;}while (j < n2) {array[k] = rightArray[j];j++;k++;}}public static void main(String[] args) {int[] array = {12, 11, 13, 5, 6, 7};int n = array.length;mergeSort(array, 0, n - 1);System.out.println("归并排序结果:");for (int num : array) {System.out.print(num + " ");}}
}

非比较排序算法

1. 计数排序(Counting Sort)

原理:计数排序适用于元素范围较小的情况,它统计每个元素出现的次数,然后根据统计信息重新构建有序序列。

代码示例

public class CountingSort {public static void countingSort(int[] array) {int n = array.length;int max = Arrays.stream(array).max().getAsInt();int min = Arrays.stream(array).min().getAsInt();int range = max - min + 1;int[] count = new int[range];int[] output = new int[n];for (int num : array) {count[num - min]++;}for (int i = 1; i < range; i++) {count[i] += count[i - 1];}for (int i = n - 1; i >= 0; i--) {output[count[array[i] - min] - 1] = array[i];count[array[i] - min]--;}for (int i = 0; i < n; i++) {array[i] = output[i];}}public static void main(String[] args) {int[] array = {4, 2, 2, 8, 3, 3, 1};countingSort(array);System.out.println("计数排序结果:");for (int num : array) {System.out.print(num + " ");}}
}

2. 桶排序(Bucket Sort)

原理:桶排序将数据分成多个桶,每个桶内部使用其他排序算法(通常是插入排序),然后将桶内有序的数据合并起来。

代码示例

public class BucketSort {public static void bucketSort(double[] array) {int n = array.length;List<Double>[] buckets = new List[n];for (int i = 0; i < n; i++) {buckets[i] = new ArrayList<>();}for (int i = 0; i < n; i++) {int bucketIndex = (int) (n * array[i]);buckets[bucketIndex].add(array[i]);}for (int i = 0; i < n; i++) {Collections.sort(buckets[i]);}int index = 0;for (int i = 0; i < n; i++) {for (double num : buckets[i]) {array[index++] = num;}}}public static void main(String[] args) {double[] array = {0.42, 0.32, 0.33, 0.52, 0.37, 0.47, 0.51};bucketSort(array);System.out.println("桶排序结果:");for (double num : array) {System.out.print(num + " ");}}
}

3. 基数排序(Radix Sort)

原理:基数排序逐位对元素进行排序,先按最低位排序,再按次低位排序,直到最高位。

代码示例

public class RadixSort {public static void radixSort(int[] array) {int n = array.length;int max = Arrays.stream(array).max().getAsInt();for (int exp = 1; max / exp > 0;exp *= 10) {countingSortByDigit(array, n, exp);}}public static void countingSortByDigit(int[] array, int n, int exp) {int[] output = new int[n];int[] count = new int[10];for (int i = 0; i < n; i++) {count[(array[i] / exp) % 10]++;}for (int i = 1; i < 10; i++) {count[i] += count[i - 1];}for (int i = n - 1; i >= 0; i--) {output[count[(array[i] / exp) % 10] - 1] = array[i];count[(array[i] / exp) % 10]--;}for (int i = 0; i < n; i++) {array[i] = output[i];}}public static void main(String[] args) {int[] array = {170, 45, 75, 90, 802, 24, 2, 66};radixSort(array);System.out.println("基数排序结果:");for (int num : array) {System.out.print(num + " ");}}
}

排序算法的性能分析和比较

排序算法的性能在不同场景下会有所不同。比较排序算法的平均时间复杂度如下:

  • 冒泡排序:O(n^2)
  • 插入排序:O(n^2)
  • 选择排序:O(n^2)
  • 希尔排序:取决于步长序列,一般在 O(n log n) 到 O(n^2) 之间
  • 快速排序:O(n log n) 平均,最坏情况为 O(n^2)
  • 归并排序:O(n log n)
  • 堆排序:O(n log n)

非比较排序算法的时间复杂度如下:

  • 计数排序:O(n + k),其中 k 是数据范围
  • 桶排序:O(n^2) 最坏情况,平均情况较好
  • 基数排序:O(n * k),其中 k 是数字的位数

综合来看,在大多数情况下,快速排序和归并排序是较优的选择,具有较快的平均性能。计数排序和基数排序在特定情况下也能表现优异。

排序算法的选择还应考虑到稳定性、空间复杂度、是否原地排序等因素。根据具体场景和需求,选择合适的排序算法可以有效提高程序的性能。

相关文章:

探究排序算法:比较与非比较排序算法及性能分析

探究排序算法&#xff1a;比较与非比较排序算法及性能分析 排序算法是计算机科学中的基本问题&#xff0c;它涉及将一组元素按照特定的顺序排列。本文将深入介绍比较排序算法和非比较排序算法&#xff0c;包括每个算法的原理、Java代码示例以及它们的性能分析和比较。 比较排…...

如何输出高质量软文,媒介盒子教你4大技巧

作为一名软文作者&#xff0c;只有知道软文写作的要求&#xff0c;才能打造一篇成功的软文&#xff0c;以便为企业或产品带来较高的关注度和曝光率&#xff0c;提高企业的知名度和品牌形象。下面就随小编一起来看看吧&#xff01; 1、吸引眼球的标题 标题是软文写作的灵魂&am…...

用centos7镜像做yum仓库

用centos7镜像做yum仓库&#xff0c;公司全部服务器使用。 小白教程&#xff0c;一看就会&#xff0c;一做就成。 1.先下载对应版本的centos7的DVD版或Everything版 我用的是DVD的&#xff0c;比Everything版小&#xff0c;功能也挺全&#xff0c;这里里centos7.5的镜像做实验…...

【无法联网】电脑wifi列表为空的解决方案

打开电脑, 发现wifi列表为空, 点击设置显示未连接 首先检查是不是网卡驱动有问题, cmd, devmgmt.msc 找到网络适配器, 看看网卡前面是否有感叹号, 如果没有则说明网卡没问题, 有问题则重装驱动 看看网络协议是否设置正确 找到"控制面板\所有控制面板项\网络和共享中心&…...

Ajax-Axios的快速入门

Ajax 概念&#xff1a;Asynchronous Javascript Anderson XML&#xff0c;异步的JavaScript和XML 作用&#xff1a;数据交换&#xff1a;通过Ajax可以给服务器发送请求&#xff0c;并获取服务器相应数据 异步交互&#xff1a;可以在不重新加载整个页面的情况下&#xff0c;与…...

mysql insert出现主键冲突错误的解决方法

mysql insert出现主键冲突错误的解决方法 insert 时防止出现主键冲突错误的方法 在mysql中插入数据的时候常常因为主键存在而冲突报错&#xff0c;下面有两个解决方法&#xff1a; 1 在insert 语句中添加ignore 关键字 insert ignore into table (id,name) values (1,username)…...

Visual Studio2022史诗级更新,增加多个提高生产力的功能

Visual Studio 2022发布了17.7x版&#xff0c;这次更新中&#xff0c;增加多个提高生产力的功能以及性能进一步改进。 如果要体验新功能&#xff0c;需要将Visual Studio 2022的版本升级到17.7及以上 下面我们看看新增的功能以及改进的功能&#xff01; 目录 文件比较自动修复代…...

理解HTTPS/TLS/SSL(一)基础概念+配置本地自签名证书

文章目录 没有HTTPS时的样子场景模拟WireShark的Capture Filter和Display Filter设置Capture Filter启动程序设置Display Filter过滤抓到的包 结论 关于为什么加密更简洁有力的回答对称加密和非对称加密和CA证书密钥交换对称加密非对称加密CA机构和证书如何解决客户端和CA机构之…...

前端需要理解的Vue知识

1 模板语法 Vue使用基于 HTML 的模板语法&#xff0c;能声明式地将其组件实例的数据绑定到DOM。所有Vue 模板可以被符合规范的浏览器和 HTML 解析器解析。Vue 会将模板编译成高度优化的 JavaScript 代码。结合响应式系统&#xff0c;当应用状态变更时&#xff0c;Vue 能够智能…...

【Go 基础篇】Go语言中的自定义错误处理

错误是程序开发过程中不可避免的一部分&#xff0c;而Go语言以其简洁和高效的特性闻名。在Go中&#xff0c;自定义错误&#xff08;Custom Errors&#xff09;是一种强大的方式&#xff0c;可以为特定应用场景创建清晰的错误类型&#xff0c;以便更好地处理和调试问题。本文将详…...

LeetCode面试经典150题(day 1)

LeetCode是一个免费刷题的一个网站&#xff0c;想要通过笔试的小伙伴可以每天坚持刷两道算法题。 接下来&#xff0c;每天我将更新LeetCode面试经典150题的其中两道算法题&#xff0c;一边巩固自己&#xff0c;一遍希望能帮助到有需要的小伙伴。 88.合并两个有序数组 给你两个…...

嵌入式linux之QT交叉编译环境搭建(最简单实测通用版)

这里总结下用于嵌入式linux下的QT交叉编译环境搭建&#xff0c;留作备忘&#xff0c;分享给有需要的小伙伴。不管你的是什么嵌入式linux环境&#xff0c;实测过的通用方法总结。 环境准备 需要准备的环境要求如下&#xff1a; 1.虚拟机(vmvare15.5) 2.ubuntu18.04-x64的linu…...

线性代数的学习和整理14: 线性方程组求解

目录 1 线性方程组 2 有解&#xff0c;无解 3 解的个数 1 线性方程组 A*xy 3根直线的交点&#xff0c;就是解 无解的情况 无解&#xff1a; 三线平行无解&#xff1a;三线不相交 有解 有唯一解&#xff1a;三线相交于一点有无数解&#xff1a;三条线重叠 2 齐次线性方程组…...

Web Components详解-Custom Elements

目录 引言 演变过程 概述 使用方式 创建标签 定义标签 使用标签 获取标签 异步定义标签 升级标签 完整案例 结语 相关代码 参考文章 引言 随着项目体量的增大&#xff0c;组件化和模块化的优势也愈发明显了&#xff0c;构建可重复使用、独立、可互操作的组件变得…...

批量将excel文件按照分类生成多个excel文件

要批量将Excel文件按照分类生成多个Excel文件&#xff0c;文件名为分类名&#xff0c;可以使用Python中的pandas库来实现。下面是示例代码&#xff1a; import pandas as pd import os def split_excel_by_category(file_path, category_column, output_folder): # 读取Ex…...

PCL 点云组件聚类

文章目录 一、简介二、实现代码三、实现效果参考资料一、简介 该算法与欧式聚类、DBSCAN聚类很是类似,聚类过程如下所述: 1. 首先,我们需要提供一个种子点集合,对种子点集合进行初始的聚类操作,聚类的评估器(即聚类条件),可以指定为法向评估,也可以是距离评估,以此我…...

学习Linux的注意事项(使用经验;目录作用;服务器注意事项)

本篇分享学习Linux过程中的一些经验 文章目录 1. Linux系统的使用经验2. Linux各目录的作用3. 服务器注意事项 1. Linux系统的使用经验 Linux严格区分大小写Linux中所有内容以文件形式保存&#xff0c;包括硬件&#xff0c;Linux是以管理文件的方式操作硬件 硬盘文件是/dev/s…...

Java字符串

文章目录 String类String的特性String对象的创建String常用方法 StringBuilder类StringBuffer类StringBuffer对象的创建StringBuffer类的常用方法 String、StringBuffer、StringBuilder区别 存放的位置 java.lang.*; 继承的父类 java.lang.Object 实现的接口 java.io.Serializa…...

vue3中props值类型和值的类型

...

windows下安装go环境 和vscode中go扩展

1. 首先安装GO Go下载地址&#xff1a;go.dev 选择相对应的版本&#xff0c;下载&#xff0c;运行安装程序&#xff0c;并打开命令提示符&#xff0c;运行 go env &#xff0c;确认已经安装go 注意关注其中GOPATH和GOROOT&#xff0c;这两个地址可以在系统环境变量中进行设置…...

Python|GIF 解析与构建(5):手搓截屏和帧率控制

目录 Python&#xff5c;GIF 解析与构建&#xff08;5&#xff09;&#xff1a;手搓截屏和帧率控制 一、引言 二、技术实现&#xff1a;手搓截屏模块 2.1 核心原理 2.2 代码解析&#xff1a;ScreenshotData类 2.2.1 截图函数&#xff1a;capture_screen 三、技术实现&…...

挑战杯推荐项目

“人工智能”创意赛 - 智能艺术创作助手&#xff1a;借助大模型技术&#xff0c;开发能根据用户输入的主题、风格等要求&#xff0c;生成绘画、音乐、文学作品等多种形式艺术创作灵感或初稿的应用&#xff0c;帮助艺术家和创意爱好者激发创意、提高创作效率。 ​ - 个性化梦境…...

论文解读:交大港大上海AI Lab开源论文 | 宇树机器人多姿态起立控制强化学习框架(二)

HoST框架核心实现方法详解 - 论文深度解读(第二部分) 《Learning Humanoid Standing-up Control across Diverse Postures》 系列文章: 论文深度解读 + 算法与代码分析(二) 作者机构: 上海AI Lab, 上海交通大学, 香港大学, 浙江大学, 香港中文大学 论文主题: 人形机器人…...

树莓派超全系列教程文档--(62)使用rpicam-app通过网络流式传输视频

使用rpicam-app通过网络流式传输视频 使用 rpicam-app 通过网络流式传输视频UDPTCPRTSPlibavGStreamerRTPlibcamerasrc GStreamer 元素 文章来源&#xff1a; http://raspberry.dns8844.cn/documentation 原文网址 使用 rpicam-app 通过网络流式传输视频 本节介绍来自 rpica…...

【磁盘】每天掌握一个Linux命令 - iostat

目录 【磁盘】每天掌握一个Linux命令 - iostat工具概述安装方式核心功能基础用法进阶操作实战案例面试题场景生产场景 注意事项 【磁盘】每天掌握一个Linux命令 - iostat 工具概述 iostat&#xff08;I/O Statistics&#xff09;是Linux系统下用于监视系统输入输出设备和CPU使…...

【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)

🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...

[Java恶补day16] 238.除自身以外数组的乘积

给你一个整数数组 nums&#xff0c;返回 数组 answer &#xff0c;其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法&#xff0c;且在 O(n) 时间复杂度…...

Java 二维码

Java 二维码 **技术&#xff1a;**谷歌 ZXing 实现 首先添加依赖 <!-- 二维码依赖 --><dependency><groupId>com.google.zxing</groupId><artifactId>core</artifactId><version>3.5.1</version></dependency><de…...

视觉slam十四讲实践部分记录——ch2、ch3

ch2 一、使用g++编译.cpp为可执行文件并运行(P30) g++ helloSLAM.cpp ./a.out运行 二、使用cmake编译 mkdir build cd build cmake .. makeCMakeCache.txt 文件仍然指向旧的目录。这表明在源代码目录中可能还存在旧的 CMakeCache.txt 文件,或者在构建过程中仍然引用了旧的路…...

LINUX 69 FTP 客服管理系统 man 5 /etc/vsftpd/vsftpd.conf

FTP 客服管理系统 实现kefu123登录&#xff0c;不允许匿名访问&#xff0c;kefu只能访问/data/kefu目录&#xff0c;不能查看其他目录 创建账号密码 useradd kefu echo 123|passwd -stdin kefu [rootcode caozx26420]# echo 123|passwd --stdin kefu 更改用户 kefu 的密码…...