以下是Java中几种常见排序算法的实现,包括冒泡排序、选择排序、插入排序、快速排序和归并排序。

各排序算法特点说明:

  1. 冒泡排序

    • 原理:重复比较相邻元素,将大的元素逐步"冒泡"到数组末尾
    • 特点:稳定排序,适合小规模数据,可优化(加入交换标记提前退出)
    • 空间复杂度:O(1)(原地排序)
  2. 选择排序

    • 原理:每次从剩余元素中找到最小元素,放到已排序区间末尾
    • 特点:不稳定(可能改变相等元素的相对顺序),交换次数少
    • 空间复杂度:O(1)(原地排序)
  3. 插入排序

    • 原理:将元素逐个插入到前面已排序的区间中合适的位置
    • 特点:稳定排序,对近乎有序的数据效率很高(接近O(n))
    • 空间复杂度:O(1)(原地排序)
  4. 快速排序

    • 原理:通过分区操作将数组分为两部分,递归排序子数组
    • 特点:实际应用中最快的排序算法之一,不稳定,最坏情况性能差
    • 空间复杂度:O(log n)(递归栈空间)
  5. 归并排序

    • 原理:将数组分成两半分别排序,再合并两个有序子数组
    • 特点:稳定排序,性能稳定(始终O(n log n)),需要额外空间
    • 空间复杂度:O(n)(需要临时数组)
import java.util.Arrays;public class SortingAlgorithms {// 1. 冒泡排序(稳定,O(n²))public static void bubbleSort(int[] arr) {if (arr == null || arr.length <= 1) return;int n = arr.length;// 外层循环控制需要进行多少轮比较for (int i = 0; i < n - 1; i++) {boolean swapped = false;// 内层循环每轮将最大元素"冒泡"到末尾for (int j = 0; j < n - 1 - i; j++) {if (arr[j] > arr[j + 1]) {// 交换元素int temp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = temp;swapped = true;}}// 如果本轮没有交换,说明数组已有序,提前退出if (!swapped) break;}}// 2. 选择排序(不稳定,O(n²))public static void selectionSort(int[] arr) {if (arr == null || arr.length <= 1) return;int n = arr.length;// 外层循环控制未排序区间的起点for (int i = 0; i < n - 1; i++) {// 找到未排序区间中最小元素的索引int minIndex = i;for (int j = i + 1; j < n; j++) {if (arr[j] < arr[minIndex]) {minIndex = j;}}// 将最小元素与未排序区间的第一个元素交换int temp = arr[i];arr[i] = arr[minIndex];arr[minIndex] = temp;}}// 3. 插入排序(稳定,O(n²),适合近乎有序的数据)public static void insertionSort(int[] arr) {if (arr == null || arr.length <= 1) return;int n = arr.length;// 从第二个元素开始,将其插入到前面的有序区间for (int i = 1; i < n; i++) {int key = arr[i]; // 当前要插入的元素int j = i - 1;// 移动有序区间中大于key的元素while (j >= 0 && arr[j] > key) {arr[j + 1] = arr[j];j--;}// 将key插入到正确位置arr[j + 1] = key;}}// 4. 快速排序(不稳定,平均O(n log n),最坏O(n²))public static void quickSort(int[] arr) {if (arr == null || arr.length <= 1) return;quickSort(arr, 0, arr.length - 1);}private static void quickSort(int[] arr, int left, int right) {if (left < right) {// 分区操作,返回基准元素的正确位置int pivotIndex = partition(arr, left, right);// 递归排序基准元素左右两侧的子数组quickSort(arr, left, pivotIndex - 1);quickSort(arr, pivotIndex + 1, right);}}private static int partition(int[] arr, int left, int right) {int pivot = arr[right]; // 以最右侧元素作为基准int i = left - 1; // i指向小于基准的元素的最后位置// 遍历数组,将小于基准的元素放到左侧for (int j = left; j < right; j++) {if (arr[j] <= pivot) {i++;// 交换元素int temp = arr[i];arr[i] = arr[j];arr[j] = temp;}}// 将基准元素放到正确位置int temp = arr[i + 1];arr[i + 1] = arr[right];arr[right] = temp;return i + 1; // 返回基准元素的索引}// 5. 归并排序(稳定,O(n log n),需要额外空间)public static void mergeSort(int[] arr) {if (arr == null || arr.length <= 1) return;mergeSort(arr, 0, arr.length - 1, new int[arr.length]);}private static void mergeSort(int[] arr, int left, int right, int[] temp) {if (left < right) {int mid = left + (right - left) / 2; // 避免溢出// 递归排序左右两半mergeSort(arr, left, mid, temp);mergeSort(arr, mid + 1, right, temp);// 合并两个有序子数组merge(arr, left, mid, right, temp);}}private static void merge(int[] arr, int left, int mid, int right, int[] temp) {int i = left; // 左子数组的起始索引int j = mid + 1; // 右子数组的起始索引int k = left; // 临时数组的起始索引// 合并两个子数组到临时数组while (i <= mid && j <= right) {if (arr[i] <= arr[j]) {temp[k++] = arr[i++];} else {temp[k++] = arr[j++];}}// 复制左子数组剩余元素while (i <= mid) {temp[k++] = arr[i++];}// 复制右子数组剩余元素while (j <= right) {temp[k++] = arr[j++];}// 将临时数组中的元素复制回原数组for (k = left; k <= right; k++) {arr[k] = temp[k];}}// 测试public static void main(String[] args) {int[] arr = {64, 34, 25, 12, 22, 11, 90};int[] copy;copy = Arrays.copyOf(arr, arr.length);bubbleSort(copy);System.out.println("冒泡排序: " + Arrays.toString(copy));copy = Arrays.copyOf(arr, arr.length);selectionSort(copy);System.out.println("选择排序: " + Arrays.toString(copy));copy = Arrays.copyOf(arr, arr.length);insertionSort(copy);System.out.println("插入排序: " + Arrays.toString(copy));copy = Arrays.copyOf(arr, arr.length);quickSort(copy);System.out.println("快速排序: " + Arrays.toString(copy));copy = Arrays.copyOf(arr, arr.length);mergeSort(copy);System.out.println("归并排序: " + Arrays.toString(copy));}
}

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

如若内容造成侵权/违法违规/事实不符,请联系英文站点网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Python爬虫实战:研究Pandas,构建地理信息数据采集和分析系统

1. 引言 1.1 研究背景 地理数据作为描述地球表面空间要素的数据,包含了丰富的空间位置、分布特征和属性信息,在城市规划、环境监测、商业分析等众多领域发挥着不可替代的作用。随着 "数字地球"、"智慧城市" 等概念的提出和发展,地理数据的重要性日益凸…

nvm安装node后出现报错: “npm 不是内部或外部命令,也不是可运行的程序 或批处理文件”

一、问题描述 使用nvm安装node后&#xff0c;使用npm命令报错如下 报错1&#xff1a;npm : 无法将“npm”项识别为 cmdlet、函数、脚本文件或可运行程序的名称。请检查名称的拼写&#xff0c;如果包括路径&#xff0c;请确保路径正确&#xff0c;然后再试一次。报错2&#xf…

【高等数学】第十二章 无穷级数——第二节 常数项级数的审敛法

上一节&#xff1a;【高等数学】第十二章 无穷级数——第一节 常数项级数的概念和性质 总目录&#xff1a;【高等数学】 目录 文章目录1. 正项级数及其审敛法1. 正项级数及其审敛法 正项级数 各项都是正数或零的级数称为正项级数正项级数收敛 正项级数 ∑n1∞un\displaystyle\…

图观 流渲染场景编辑器

一、 产品简介图观 流渲染场景编辑器&#xff0c;以编辑器插件形式&#xff0c;在Unreal Engine中轻松编辑并发布数字孪生场景。支持 GIS 全球/局部 数字孪生场景构建&#xff0c;并预置 图观技术架构工程模板&#xff0c;支持对 场景效果、镜头视野&#xff0c;环境时间气象、…

Visual Studio 函数头显示引用个数

在visual studio 里面有自带的显示引用方案 codeLens

数据结构的哈希表冲突解决方法

哈希表是一种高效的数据结构,通过哈希函数将键映射到存储位置。但由于哈希函数可能将不同键映射到相同位置(称为哈希冲突),需要有效的方法来解决冲突。以下是常见的冲突解决策略,每种方法都有其原理、优缺点和适用场景。我将逐步解释这些方法,确保内容清晰可靠。 1. 开放…

MySQL 基础概念与简单使用

MySQL 基础概念与简单使用 一、数据库基本概念 1、数据库定义 数据库&#xff08;Database&#xff09;是存储在计算机内、有组织、可共享的数据集合&#xff0c;用于高效地管理大量数据。 2、数据库分类 按数据模型分类&#xff1a; 关系型数据库&#xff08;如 MySQL、Oracle…

关系模型的数据结构

在关系数据库这个世界里&#xff0c;所有东西&#xff08;包括你要记录的人、物、事&#xff0c;以及它们之间的联系&#xff09;都用一种叫做“关系”的结构来表示。而这种“关系”的灵魂&#xff0c;就是“码”&#xff08;Key&#xff09;。1. 核心思想&#xff1a;万物皆“…

180 课时吃透 Go 语言游戏后端系列0:序言

零基础能学习 Go 游戏后端开发吗&#xff1f; 当然能学啦&#xff01;别担心&#xff0c;就算你之前对编程一窍不通&#xff0c;也完全没问题。我特意准备了180课时的开发课程&#xff0c;由浅入深、从理论到实践带领大家学会使用GO语言进行游戏后端开发。 编程就像学一门新语…

Android-SerialPort-API-master源码 串口调试 权限分析 定制

我把界面美化了一下Android-SerialPort-API-master源码 1.加了发送按钮 2.加上固定/dev/ttyGS1和GS9串口权限问题已经查清楚了。app与PosServer都是使用google的SerialPort方案。我做的app 都多使用一个函数available()&#xff0c;这个函数是非常有用的。在上位机发送单条指令…

KVM 入门使用手册

KVM 入门使用手册 1. 概述 2. 安装 在 Ubuntu/Debian 上安装 在 RHEL/CentOS/Fedora 上安装 3. 网络配置 查看默认网络 使用桥接网络 (推荐用于服务器) 4. 创建虚拟机 方法一:使用图形界面 (virt-manager) 方法二:使用命令行 (virt-install) 5. 管理虚拟机 使用 `virsh` 命令…

Devise Ruby身份验证解决方案全攻略

文章目录 前言Devise到底是什么&#xff1f;为什么选择Devise&#xff1f;环境准备Devise安装指南第一步&#xff1a;添加Devise到你的Gemfile第二步&#xff1a;初始化Devise第三步&#xff1a;生成用户模型第四步&#xff1a;运行数据库迁移 Devise核心模块详解Database Auth…

68-python操作SQLite

1. 了解SQLite SQLite&#xff0c;是一款轻型的数据库&#xff0c;是遵守ACID的关系型数据库管理系统&#xff0c;它包含在一个相对小的C库中。它是D.RichardHipp建立的公有领域项目。它的设计目标是嵌入式的&#xff0c;而且已经在很多嵌入式产品中使用了它&#xff0c;它占用…

在Qt项目中使用QtConcurrent::run,实现异步等待和同步调用

在使用Qt进行开发时&#xff0c;经常需要使用异步方法&#xff0c;不同于C#的async/await&#xff0c;Qt中提供了QtConcurrent::run接口方法可供调用&#xff0c;习惯了C#的await&#xff0c;便想着能不能封装几个类似的函数在项目中使用&#xff0c;探索了下&#xff0c;有如下…

视频分类 pytorchvideo

目录 1. 速度 vs 精度分析 mvit: r2plus1d_r50 推理代码&#xff1a; x3d_xs推理代码&#xff1a; R(21)D X3D&#xff08;轻量级&#xff0c;速度快&#xff09; I3D&#xff08;经典 3D CNN&#xff09; 替换分类层&#xff08;适配你的任务&#xff09; https://gith…

OpenTiny NEXT 内核新生:生成式UI × MCP,重塑前端交互新范式!

近期&#xff0c;我们推出 OpenTiny NEXT —— OpenTiny的下一代企业级前端智能开发解决方案。这不仅是一次技术升级&#xff0c;更是一场用户交互范式的变革&#xff1a;从传统的人机交互升级成为人机交互范式和智能体交互范式的融合。我们坚信&#xff0c;每一个企业应用都值…

深度神经网络1——梯度问题+标签数不够问题

要解决一个复杂问题&#xff0c;可能要训练更深的神经网络&#xff0c;可能会10层及以上&#xff0c;每层包含数百个神经元&#xff0c;成千上万个连接。这样大的神经网络在训练的时候可能会遇到以下问题&#xff1a;这样在进行反向传播的时候&#xff0c;随着层数越来越低会遇…

(笔记)内存文件映射mmap

内存文件映射是一种将文件内容映射到进程的虚拟地址空间的技术&#xff0c;使得文件可以被视为内存的一部分&#xff0c;从而允许程序直接对这部分内存进行读写操作&#xff0c;而无需传统的文件 I/O 调用。这种方法不仅简化了文件操作&#xff0c;还提高了处理效率。 在Linux…

Golang中的NaN(Not a Number)

Golang中的NaN&#xff08;Not a Number&#xff09; 在Go语言中&#xff0c;NaN是浮点数&#xff08;特别是float32和float64&#xff09;中的一个特殊值&#xff0c;表示未定义或不可表示的数值。 go中&#xff0c;除数为0时并不会返回error或者nil&#xff0c;而是返回无穷大…

微软图引擎GraphEngine深度解析:分布式内存计算的技术革命

❝ "在大数据的汪洋中&#xff0c;图引擎就像是一艘能够高速穿越复杂关系网络的超级快船" 引言&#xff1a;当内存遇上图计算的火花 在这个数据爆炸的时代&#xff0c;传统的关系型数据库已经难以应对复杂关系数据的查询挑战。当Facebook的社交网络拥有数十亿用户关…