java的几种排序算法(详细)

  1. 冒泡排序(Bubble Sort)
    • 基本原理
      • 冒泡排序是一种简单的比较排序算法。它重复地走访要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小(或越大)的元素会经由交换慢慢 “浮” 到数列的顶端(或底端),就像气泡在水中逐渐向上浮起一样。
    • 具体步骤
      • 从数列的第一个元素开始,比较相邻的两个元素。例如,对于一个整数数列int[] arr = {5, 4, 3, 2, 1},首先比较arr[0](5)和arr[1](4),因为5 > 4,所以交换它们的位置,数列变为{4, 5, 3, 2, 1}
      • 接着比较arr[1](5)和arr[2](3),交换位置后得到{4, 3, 5, 2, 1}。按照这样的方式,依次比较相邻的元素,经过第一轮比较后,最大的元素就会 “浮” 到数列的末尾,此时数列变为{4, 3, 2, 1, 5}
      • 然后进行第二轮比较,从第一个元素开始,重复上述步骤,但是这次只需要比较到倒数第二个元素,因为最大的元素已经在最后位置确定了。经过第二轮比较,第二大的元素会移动到倒数第二个位置。
      • 持续这个过程,总共需要进行n - 1轮比较(n是数列的长度),直到整个数列排序完成。
    • 时间复杂度和空间复杂度
      • 时间复杂度:
        • 最坏情况:当数列是倒序排列时,需要进行n(n - 1)/2次比较和交换操作,时间复杂度为。例如,对于一个长度为 5 的倒序数列{5, 4, 3, 2, 1},第一轮需要比较 4 次,第二轮需要比较 3 次,以此类推,总共需要比较次,符合(时,)的公式。
        • 最好情况:当数列已经是正序排列时,只需要进行n - 1次比较,没有交换操作,时间复杂度为。
        • 平均情况:时间复杂度为,因为在平均情况下,元素的顺序是比较杂乱的,需要进行大量的比较和交换操作。
      • 空间复杂度:因为冒泡排序只需要几个额外的变量来进行元素交换,不需要额外的存储空间来存储数据,所以空间复杂度为。
    • 代码示例
public class BubbleSort {public static void bubbleSort(int[] arr) {int n = arr.length;for (int i = 0; i < n - 1; i++) {for (int j = 0; j < n - i - 1; j++) {if (arr[j] > arr[j + 1]) {// 交换元素int temp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = temp;}}}}
}

  1. 插入排序(Insertion Sort)
    • 基本原理
      • 插入排序的基本操作是将一个数据插入到已经排好序的有序数列中,从而得到一个新的、长度加 1 的有序数列。它的工作方式就像人们排序一手扑克牌一样,开始时,左手为空并且桌上的牌面向下。然后,每次从桌上拿起一张牌并将它插入到左手中正确的位置。为了找到这张牌的正确位置,需要将它与手中已有的牌从右到左进行比较。
    • 具体步骤
      • 对于一个数列int[] arr = {5, 3, 4, 6, 1},假设第一个元素arr[0](5)已经是有序的。
      • 从第二个元素arr[1](3)开始,将它与前面的元素(此时只有arr[0])进行比较。因为3 < 5,所以将 3 插入到 5 的前面,此时数列变为{3, 5, 4, 6, 1}
      • 接着处理arr[2](4),将 4 与前面已经排序好的元素({3, 5})从右到左进行比较。首先与 5 比较,因为4 < 5,交换它们的位置,得到{3, 4, 5, 6, 1}
      • 以此类推,每次将一个新元素插入到前面已经排序好的数列中的合适位置,直到整个数列排序完成。
    • 时间复杂度和空间复杂度
      • 时间复杂度:
        • 最坏情况:当数列是倒序排列时,每次插入一个元素都需要移动前面的所有元素,总共需要进行n(n - 1)/2次比较和移动操作,时间复杂度为。例如,对于数列{5, 4, 3, 2, 1},插入 4 时需要移动 1 个元素,插入 3 时需要移动 2 个元素,以此类推,总共需要移动次,符合(时,)的公式。
        • 最好情况:当数列已经是正序排列时,只需要进行n - 1次比较,没有元素移动操作,时间复杂度为。
        • 平均情况:时间复杂度为,因为在平均情况下,元素的插入操作也需要比较和移动一定数量的元素。
      • 空间复杂度:插入排序只需要几个额外的变量来进行元素比较和移动,不需要额外的存储空间来存储数据,所以空间复杂度为。
    • 代码示例
public class InsertionSort {public static void insertionSort(int[] arr) {int n = arr.length;for (int i = 1; i < n; i++) {int key = arr[i];int j = i - 1;while (j >= 0 && arr[j] > key) {arr[j + 1] = arr[j];j = j - 1;}arr[j + 1] = key;}}
}

  1. 选择排序(Selection Sort)
    • 基本原理
      • 选择排序的基本思想是在未排序的数列中找到最小(或最大)的元素,将其与数列的第一个(或最后一个)未排序元素交换位置。然后,在剩下的未排序元素中继续这个操作,直到所有元素都排序完成。
    • 具体步骤
      • 对于一个数列int[] arr = {5, 4, 3, 2, 1},首先在整个数列中找到最小的元素,即 1。然后将 1 与第一个元素 5 交换位置,此时数列变为{1, 4, 3, 2, 5}
      • 接着在剩下的未排序元素{4, 3, 2, 5}中找到最小的元素,即 2。将 2 与第二个元素 4 交换位置,得到{1, 2, 3, 4, 5}
      • 按照这样的方式,每次从剩余的未排序元素中选择最小的元素,并将其放置到合适的位置,直到整个数列排序完成。
    • 时间复杂度和空间复杂度
      • 时间复杂度:
        • 无论数列的初始顺序如何,选择排序都需要进行 `n (n - 1)/2次比较操作来找到最小(或最大)元素,时间复杂度为O(n^2)$。例如,对于一个长度为5的数列,第一轮需要比较4次来找到最小元素,第二轮需要比较3次来找到剩余元素中的最小元素,以此类推,总共需要比较次,符合(时,$5×(5 - 1)/2 = 10$)的公式。
        • 交换操作的次数最多为n - 1次,因为每次交换都将一个元素放置到最终位置。
      • 空间复杂度:选择排序只需要几个额外的变量来进行元素比较和交换,不需要额外的存储空间来存储数据,所以空间复杂度为。
    • 代码示例
public class SelectionSort {public static void selectionSort(int[] arr) {int n = arr.length;for (int i = 0; i < n - 1; i++) {int min_idx = i;for (int j = i + 1; j < n; j++) {if (arr[j] < arr[min_idx]) {min_idx = j;}}// 交换元素int temp = arr[min_idx];arr[min_idx] = arr[i];arr[i] = temp;}}
}

  1. 快速排序(Quick Sort)
    • 基本原理
      • 快速排序是一种分治算法。它的基本思想是选择一个基准元素(pivot),通过一趟排序将待排序的数据分割成独立的两部分,其中一部分的所有数据都比基准元素小,另一部分的所有数据都比基准元素大。然后,分别对这两部分数据进行快速排序,整个排序过程可以递归地进行,直到整个数列排序完成。
    • 具体步骤
      • 例如,对于一个数列int[] arr = {5, 2, 8, 1, 9},选择第一个元素 5 作为基准元素(pivot)。
      • 设置两个指针,一个从数列的左边开始(left),一个从数列的右边开始(right)。
      • 从右向左移动right指针,找到第一个小于基准元素的元素,即 1。同时,从左向右移动left指针,找到第一个大于基准元素的元素,即 8。
      • 交换 1 和 8 的位置,此时数列变为{5, 2, 1, 8, 9}
      • 继续移动指针,直到leftright相遇。此时,将基准元素 5 与left指针指向的元素(1)交换位置,得到{1, 2, 5, 8, 9}。这样,就将数列分成了两部分,左边部分{1, 2}都小于 5,右边部分{8, 9}都大于 5。
      • 然后对左右两部分{1, 2}{8, 9}分别进行快速排序,直到整个数列排序完成。
    • 时间复杂度和空间复杂度
      • 时间复杂度:
        • 平均情况:时间复杂度为。这是因为每次划分可以将数列分为大致相等的两部分,递归的深度为,每层需要的时间来划分。例如,对于一个长度为 8 的数列,第一次划分后得到两个长度约为 4 的子数列,第二次划分后得到四个长度约为 2 的子数列,以此类推,划分的次数大约为次,每次划分需要比较和移动元素,时间复杂度约为。
        • 最坏情况:当数列已经是正序或倒序排列,并且每次选择的基准元素都是最大或最小元素时,快速排序退化为冒泡排序,时间复杂度为。
      • 空间复杂度:
        • 最坏情况:需要的栈空间来存储递归调用的信息,因为在最坏情况下,递归深度为n
        • 平均情况:空间复杂度为,因为在平均情况下,递归深度为。
    • 代码示例
public class QuickSort {public static void quickSort(int[] arr, int low, int high) {if (low < high) {int pivotIndex = partition(arr, low, high);quickSort(arr, low, pivotIndex - 1);quickSort(arr, pivotIndex + 1, high);}}private static int partition(int[] arr, int low, int high) {int pivot = arr[low];int i = low + 1;int j = high;while (true) {while (i <= j && arr[i] <= pivot) {i++;}while (i <= j && arr[j] > pivot) {j--;}if (i > j) {break;}int temp = arr[i];arr[i] = arr[j];arr[j] = temp;}int temp = arr[low];arr[low] = arr[j];arr[j] = temp;return j;}
}
  1. 归并排序(Merge Sort)
    • 基本原理
      • 归并排序也是一种分治算法。它的基本思想是将一个数列分成两个子数列,对每个子数列进行排序,然后将排序好的子数列合并成一个有序的数列。这个过程可以递归地进行,直到子数列的长度为 1,此时数列已经排序完成。
    • 具体步骤
      • 例如,对于一个数列int[] arr = {5, 3, 8, 1, 9}
      • 首先将数列分成两个子数列,即{5, 3}{8, 1, 9}
      • 继续对这两个子数列进行划分,得到{5}{3}{8}{1}{9},此时子数列的长度为 1,已经是有序的。
      • 然后开始合并过程,先合并{5}{3},得到{3, 5}。接着合并{8}{1},得到{1, 8}。再合并{1, 8}{9},得到{1, 8, 9}
      • 最后合并{3, 5}{1, 8, 9},得到{1, 3, 5, 8, 9},此时整个数列排序完成。
    • 时间复杂度和空间复杂度
      • 时间复杂度:
        • 无论数列的初始顺序如何,归并排序的时间复杂度都是。因为每次划分需要的时间,总共需要划分次,每次合并需要的时间。例如,对于一个长度为 8 的数列,第一次划分得到两个长度为 4 的子数列,第二次划分得到四个长度为 2 的子数列,以此类推,划分次数为次。每次合并两个子数列时,需要比较和移动元素,时间复杂度为。
      • 空间复杂度:归并排序需要一个临时数组来存储合并后的元素,所以空间复杂度为。
    • 代码示例
public class MergeSort {public static void mergeSort(int[] arr) {if (arr.length > 1) {int mid = arr.length / 2;int[] left = new int[mid];int[] right = new int[arr.length - mid];for (int i = 0; i < mid; i++) {left[i] = arr[i];}for (int i = mid; i < arr.length; i++) {right[i - mid] = arr[i];}mergeSort(left);mergeSort(right);merge(arr, left, right);}}private static void merge(int[] arr, int[] left, int[] right) {int i = 0, j = 0, k = 0;while (i < left.length && j < right.length) {if (left[i] <= right[j]) {arr[k++] = left[i++];} else {arr[k++] = right[j++];}}while (i < left.length) {arr[k++] = left[i++];}while (j < right.length) {arr[k++] = right[j++];}}
}

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

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

相关文章

vue项目env文件的使用(vue cli2和vue cli3)

Vue CLI 2 环境 在 Vue CLI 2 中&#xff0c;需要安装 dotenv 包来加载和使用环境变量。 步骤&#xff1a; 安装 dotenv&#xff1a;首先安装 dotenv 包 npm install dotenv --save创建 .env 文件&#xff1a;在项目的根目录下创建一个 .env 文件&#xff0c;并在其中定义你的…

全面解析 Transformer:改变深度学习格局的神经网络架构

目录 一、什么是 Transformer&#xff1f; 二、Transformer 的结构解析 1. 编码器&#xff08;Encoder&#xff09; 2. 解码器&#xff08;Decoder&#xff09; 3. Transformer 模型结构图 三、核心技术&#xff1a;注意力机制与多头注意力 1. 注意力机制 2. 多头注意力&…

使用YOLO系列txt目标检测标签的滑窗切割:批量处理图像和标签的实用工具

使用YOLO系列txt目标检测标签的滑窗切割&#xff1a;批量处理图像和标签的实用工具 使用YOLO的TXT目标检测标签的滑窗切割&#xff1a;批量处理图像和标签的实用工具背景1. 代码概述2. 滑窗切割算法原理滑窗切割步骤&#xff1a;示例&#xff1a; 3. **代码实现**1. **加载标签…

Java ArrayList 详解

Java ArrayList 详解 ArrayList 是 Java 集合框架&#xff08;Collection Framework&#xff09;中最常用的类之一&#xff0c;是一种基于动态数组的数据结构&#xff0c;属于 List 接口的实现类。它允许存储重复的元素&#xff0c;有序&#xff0c;支持随机访问&#xff0c;且…

springboot/ssm线上教育培训办公系统Java代码web项目在线课程作业源码

springboot/ssm线上教育培训办公系统Java代码web项目在线课程作业源码 基于springboot(可改ssm)htmlvue项目 开发语言&#xff1a;Java 框架&#xff1a;springboot/可改ssm vue JDK版本&#xff1a;JDK1.8&#xff08;或11&#xff09; 服务器&#xff1a;tomcat 数据库&…

Rust学习笔记_13——枚举

Rust学习笔记_10——守卫 Rust学习笔记_11——函数 Rust学习笔记_12——闭包 枚举 文章目录 枚举1. 定义1.1 无值变体1.2 有值变体1.3 枚举与泛型的结合 2. 使用2.1 和匹配模式一起使用2.2 枚举作为类型别名 3. 常用枚举类型 在Rust编程语言中&#xff0c;枚举&#xff08;enum…

容器运行应用及Docker命令

文章目录 一、使用容器运行Nginx应用1_使用docker run命令运行Nginx应用1 观察下载容器镜像过程2 观察容器运行情况 2_访问容器中运行的Nginx服务1 确认容器IP地址2 容器网络说明3 使用curl命令访问 二、Docker命令1_Docker命令获取帮助方法2_Docker官网提供的命令说明3_docker…

深入浅出:php-学习入门全攻略

文章目录 1. 为什么选择 PHP&#xff1f;2. 安装 PHP 环境2.1 Windows 系统安装步骤 1&#xff1a;下载 PHP步骤 2&#xff1a;解压并配置步骤 3&#xff1a;配置环境变量步骤 4&#xff1a;验证安装 2.2 Mac 系统安装步骤 1&#xff1a;使用 Homebrew 安装步骤 2&#xff1a;验…

【热门主题】000075 探索嵌入式硬件设计的奥秘

前言&#xff1a;哈喽&#xff0c;大家好&#xff0c;今天给大家分享一篇文章&#xff01;并提供具体代码帮助大家深入理解&#xff0c;彻底掌握&#xff01;创作不易&#xff0c;如果能帮助到大家或者给大家一些灵感和启发&#xff0c;欢迎收藏关注哦 &#x1f495; 目录 【热…

数据分析(一): 掌握STDF 掌握金钥匙-码农切入半导体的捷径

中国的半导体行业必然崛起&#xff01;看清这个大势&#xff0c;就会有很多机会。 今天&#xff0c;我们一起来了解一下半导体行业的一朵金花&#xff1a;STDF。 实际上这只是一种文件格式&#xff0c;但是当你熟练掌握解析这种文件的时候&#xff0c;你就已经打开在这个基础…

PostgreSQLt二进制安装-contos7

1、安装依赖 yum install -y gcc readline readline-devel zlib-devel net-tools perl wget numactl libicu-devel bison flex openssl-devel pam pam-devel libxml2 libxml2-devel libxslt libxslt-devel openldap openldap-devel 2、创建目录 mkdir -p /data/postgresql/{…

Latex转word(docx)或者说PDF转word 一个相对靠谱的方式

0. 前言 投文章过程中总会有各种各样的要求&#xff0c;其中提供word格式的手稿往往是令我头疼的一件事。尤其在多公式的文章中&#xff0c;其中公式转换是一个头疼的地方&#xff0c;还有很多图表&#xff0c;格式等等&#xff0c;想想就让人头疼欲裂。实践中摸索出一条相对靠…

AWS创建ec2实例并连接成功

aws创建ec2实例并连接 aws创建ec2并连接 1.ec2创建前准备 首先创建一个VPC隔离云资源并且有公有子网 2.创建EC2实例 1.启动新实例或者创建实例 2.创建实例名 3.选择AMI使用linux(HVM) 4.选择实例类型 5.创建密钥对下载到本地并填入密钥对名称 6.选择自己创建的VPC和公有子网…

“放弃Redis Desktop Manager使用Redis Insight”:日常使用教程(Redis可视化工具)

文章目录 更新Redis Insight连接页面基础解释自动更新key汉化暂时没有找到方法&#xff0c; Redis Desktop Manager在连接上右键在数据库上右键在key上右键1、添加连接2、key过期时间 参考文章 更新 (TωT)&#xff89;~~~ β&#xff59;ё β&#xff59;ё~ 现在在维护另一…

如何用注册机破解Reflexive游戏

相信有许多小朋友&#xff08;像我以前一样&#xff09;已经迫不及待地准备准备对浩瀚的、像三星堆一般的Reflexive游戏合集进行考古挖掘工作了。不巧的是&#xff0c;打开游戏之后发现常常提示要付费才能解锁完整版。 一、下载注册机与破解文件 首先&#xff0c;在我的永硕网…

Java 多线程探秘:从线程池到死锁的奇幻之旅

1.简述一下你对线程池的理解 线程池是一种多线程处理形式&#xff0c;处理过程中将任务分为若干个线程&#xff0c;使用线程池可以有效地管理并发线程的数量&#xff0c;提高程序的响应速度和资源利用率。以下是关于线程池的一些关键点&#xff1a; 预创建线程&#xff1a;线…

一万台服务器用saltstack还是ansible?

一万台服务器用saltstack还是ansible? 选择使用 SaltStack 还是 Ansible 来管理一万台服务器&#xff0c;取决于几个关键因素&#xff0c;如性能、扩展性、易用性、配置管理需求和团队的熟悉度。以下是两者的对比分析&#xff0c;帮助你做出决策&#xff1a; SaltStack&…

PDF文件页面转换成图片怎么弄-免费PDF编辑工具分享

>>更多PDF文件处理应用技巧请前往 96缔盟PDF处理器 主页 查阅&#xff01; —————————————————————————————————————— 序言 我之前的文章也有介绍过如何使用96缔盟PDF处理器对PDF文件转换成图片&#xff0c;但是当时是使用DMPDFU…

从 scratch开始构建一个最小化的 Hello World Docker 镜像-docker的镜像源头

在这篇文章中&#xff0c;我们将学习如何从零开始构建一个最小化的 Docker 镜像&#xff0c;基于 scratch 镜像&#xff0c;并在其中运行一个简单的 “Hello World” 程序。 Scratch 是一个空白的基础镜像&#xff0c;适用于构建轻量化、独立的容器。由于 scratch 不包含任何系…

OpenHarmony-4.GPIO驱动

GPIO 1.功能简介 GPIO&#xff08;General-purpose input/output&#xff09;即通用型输入输出。GPIO又俗称为I/O口&#xff0c;I指的是输入(in&#xff09;&#xff0c;O指的是输出&#xff08;out&#xff09;。可以通过软件来控制其输入和输出&#xff0c;即I/O控制。通常&…