Java实现快速排序算法详解及优化

引言

快速排序(QuickSort)是常用的排序算法之一,以其高效性和简洁性著称。它通常在大数据量排序中表现出色。本文将详细讲解如何使用Java实现快速排序算法,并结合图解和实例代码,帮助您全面理解这一高级排序算法。同时,我们还将探讨快速排序的优化方法,以进一步提高其性能。

快速排序算法的原理

快速排序是一种分治算法。它的核心思想是选择一个基准元素(pivot),通过一趟排序将待排序序列分成两个子序列,其中一个子序列的所有元素都小于基准元素,另一个子序列的所有元素都大于基准元素。然后递归地对两个子序列进行排序,直到整个序列有序。

算法步骤

  1. 选择基准元素:通常选择数组的第一个元素、最后一个元素或中间元素作为基准。
  2. 分区:将数组分成两个子数组,使得左子数组的所有元素小于基准,右子数组的所有元素大于基准。
  3. 递归排序:对两个子数组分别进行递归排序。

图解快速排序

为了更清晰地展示快速排序的过程,以下使用一个简单示例并分步骤图解:

初始数组: 10, 7, 8, 9, 1, 5
选择基准元素: 5
分区后数组: 1, 5, 8, 9, 10, 7
递归排序左子数组: 1
递归排序右子数组: 8, 9, 10, 7
选择基准元素: 7
分区后数组: 7, 8, 9, 10
递归排序左子数组: 空
递归排序右子数组: 8, 9, 10
选择基准元素: 9
分区后数组: 8, 9, 10
最终排序结果: 1, 5, 7, 8, 9, 10

Java实现快速排序

public class QuickSort {/*** 实现快速排序算法* @param arr 待排序的数组* @param low 起始索引* @param high 结束索引*/public static void quickSort(int[] arr, int low, int high) {if (low < high) {// 获取分区索引int pi = partition(arr, low, high);// 对左右子数组进行递归排序quickSort(arr, low, pi - 1);quickSort(arr, pi + 1, high);}}/*** 分区方法* @param arr 待排序的数组* @param low 起始索引* @param high 结束索引* @return 分区索引*/public static int partition(int[] arr, int low, int high) {int pivot = arr[high];int i = (low - 1); // 最小元素索引for (int j = low; j < high; j++) {// 如果当前元素小于或等于 pivotif (arr[j] <= pivot) {i++;// 交换 arr[i] 和 arr[j]int temp = arr[i];arr[i] = arr[j];arr[j] = temp;}}// 交换 arr[i+1] 和 pivotint temp = arr[i + 1];arr[i + 1] = arr[high];arr[high] = temp;return i + 1;}public static void main(String[] args) {// 初始化数组int[] arr = {10, 7, 8, 9, 1, 5};int n = arr.length;// 调用快速排序方法quickSort(arr, 0, n - 1);// 输出排序后的数组System.out.println("排序后的数组:");for (int i = 0; i < n; i++) {System.out.print(arr[i] + " ");}}
}

快速排序的优化方法

三数取中法

选择基准元素时,常规方法是选择第一个元素或最后一个元素。然而,这些方法在某些情况下(例如,数组已经有序)可能导致性能下降。三数取中法是一个有效的优化策略,通过选择数组的第一个元素、中间元素和最后一个元素中的中位数作为基准。

图解三数取中法

初始数组: 10, 7, 8, 9, 1, 5
选择第一个元素: 10
选择中间元素: 8
选择最后一个元素: 5
排序三个元素: 5, 8, 10
选择中间值8作为基准
分区后数组: 1, 5, 7, 8, 9, 10

Java实现三数取中法

public class OptimizedQuickSort {/*** 实现优化后的快速排序算法* @param arr 待排序的数组* @param low 起始索引* @param high 结束索引*/public static void quickSort(int[] arr, int low, int high) {if (low < high) {// 获取优化后的分区索引int pi = partition(arr, low, high);// 对左右子数组进行递归排序quickSort(arr, low, pi - 1);quickSort(arr, pi + 1, high);}}/*** 优化后的分区方法* @param arr 待排序的数组* @param low 起始索引* @param high 结束索引* @return 分区索引*/public static int partition(int[] arr, int low, int high) {int pivot = medianOfThree(arr, low, high);int i = (low - 1); // 最小元素索引for (int j = low; j < high; j++) {// 如果当前元素小于或等于 pivotif (arr[j] <= pivot) {i++;// 交换 arr[i] 和 arr[j]int temp = arr[i];arr[i] = arr[j];arr[j] = temp;}}// 交换 arr[i+1] 和 pivotint temp = arr[i + 1];arr[i + 1] = arr[high];arr[high] = temp;return i + 1;}/*** 三数取中法选择基准元素* @param arr 待排序的数组* @param low 起始索引* @param high 结束索引* @return 基准元素*/public static int medianOfThree(int[] arr, int low, int high) {int mid = low + (high - low) / 2;if (arr[low] > arr[mid]) {swap(arr, low, mid);}if (arr[low] > arr[high]) {swap(arr, low, high);}if (arr[mid] > arr[high]) {swap(arr, mid, high);}// 将中位数与高位元素交换swap(arr, mid, high);return arr[high];}/*** 交换数组中的两个元素* @param arr 数组* @param i 索引i* @param j 索引j*/private static void swap(int[] arr, int i, int j) {int temp = arr[i];arr[i] = arr[j];arr[j] = temp;}public static void main(String[] args) {// 初始化数组int[] arr = {10, 7, 8, 9, 1, 5};int n = arr.length;// 调用优化后的快速排序方法quickSort(arr, 0, n - 1);// 输出排序后的数组System.out.println("排序后的数组:");for (int i = 0; i < n; i++){System.out.print(arr[i] + " ");}}
}

小数组优化

对于小规模数组,可以使用插入排序代替快速排序,以减少递归调用的开销。

图解小数组优化

数组: 10, 7, 8, 9, 1, 5
分割数组
小于阈值的子数组: 插入排序
大于阈值的子数组: 快速排序
插入排序过程
快速排序过程

Java实现小数组优化

public class HybridQuickSort {private static final int INSERTION_SORT_THRESHOLD = 10;/*** 实现混合快速排序算法* @param arr 待排序的数组* @param low 起始索引* @param high 结束索引*/public static void quickSort(int[] arr, int low, int high) {if (low < high) {if (high - low < INSERTION_SORT_THRESHOLD) {// 对小数组使用插入排序insertionSort(arr, low, high);} else {// 对大数组使用快速排序int pi = partition(arr, low, high);quickSort(arr, low, pi - 1);quickSort(arr, pi + 1, high);}}}/*** 分区方法* @param arr 待排序的数组* @param low 起始索引* @param high 结束索引* @return 分区索引*/public static int partition(int[] arr, int low, int high) {int pivot = arr[high];int i = (low - 1); // 最小元素索引for (int j = low; j < high; 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[high];arr[high] = temp;return i + 1;}/*** 插入排序方法* @param arr 待排序的数组* @param low 起始索引* @param high 结束索引*/public static void insertionSort(int[] arr, int low, int high) {for (int i = low + 1; i <= high; i++) {int key = arr[i];int j = i - 1;while (j >= low && arr[j] > key) {arr[j + 1] = arr[j];j--;}arr[j + 1] = key;}}public static void main(String[] args) {int[] arr = {10, 7, 8, 9, 1, 5};int n = arr.length;quickSort(arr, 0, n - 1);System.out.println("排序后的数组:");for (int i = 0; i < n; i++) {System.out.print(arr[i] + " ");}}
}

结论

通过上述讲解和实例代码,我们详细展示了如何在Java中实现快速排序算法,并结合图解说明了其工作原理。同时,我们探讨了快速排序的优化方法,包括三数取中法和小数组优化,以提高其性能。

希望这篇博客对您有所帮助!记得关注、点赞和收藏哦,以便随时查阅更多优质内容!


如果您觉得这篇文章对您有帮助,请关注我的CSDN博客,点赞并收藏这篇文章,您的支持是我持续创作的动力!


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

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

相关文章

员工聊天记录监控方法大全(五种方法你自己选择)

在现代企业中&#xff0c;为了保障业务安全、防止数据泄露和促进工作效率&#xff0c;很多公司会采用各种方法监控员工的聊天记录。虽然听起来有点“大哥哥在看着你”的感觉&#xff0c;但只要在合法和透明的前提下进行&#xff0c;这其实是为了构建一个更加健康、安全的工作环…

网络流问题-Min-cut

文章目录 1. 网络流问题基础1.1 概述1.2 常规算法1.3 总结 2. Ford-Fulkerson Algorithm2.1 概述2.2 Ford 算法2.3 Ford 算法小结 链接&#xff1a; B站学习视频 1. 网络流问题基础 1.1 概述 最大流问题主要是关于有向图问题。有向图中有m个边&#xff0c; n个节点,其中有一个…

怎么用PPT录制微课?详细步骤解析!

随着信息技术的不断发展&#xff0c;微课作为一种新型的教学形式&#xff0c;因其短小精悍、针对性强等特点&#xff0c;在教育领域得到了广泛的应用。而PPT作为一款常用的演示工具&#xff0c;不仅可以用来制作课件&#xff0c;还可以利用其内置的录屏功能或结合专业的录屏软件…

Dify中的经济索引模式实现过程

当索引模式为经济时&#xff0c;使用离线的向量引擎、关键词索引等方式&#xff0c;降低了准确度但无需花费 Token。 一.提取函数**_extract** 根据不同文档类型进行内容的提取&#xff1a; def _extract(self, index_processor: BaseIndexProcessor, dataset_document: Data…

FastAPI 学习之路(四十三)路径操作的高级配置

在实际开发中&#xff0c;可能我们有些接口不能在接口文档中与其他业务接口一样开放给前端或者其他对接人&#xff0c;那么我们肯定会想着在接口文档中对其进行屏蔽隐藏操作&#xff0c;那么可以实现吗&#xff1f; 接口文档中隐藏接口 当然&#xff0c;还很简单&#xff0c;…

Java泛型之协变与逆变

Java中的泛型有两个重要特性&#xff1a;不可变性&#xff08;invariance&#xff09;和类型擦除&#xff08;type erasure&#xff09;。这两个概念在理解和使用泛型时非常重要。以下是对这两个特性的详细解释&#xff1a; 不可变性&#xff08;Invariance&#xff09; 在Ja…

【CSS in Depth 2 精译】2.6 CSS 自定义属性(即 CSS 变量)+ 2.7 本章小结

文章目录 2.6 自定义属性&#xff08;即 CSS 变量&#xff09;2.6.1 动态变更自定义属性 2.7 本章小结 当前内容所在位置 第一章 层叠、优先级与继承第二章 相对单位 2.1 相对单位的威力2.2 em 与 rem2.3 告别像素思维2.4 视口的相对单位2.5 无单位的数值与行高2.6 自定义属性 …

SunnyUI中UIAvatar的使用

在SunnyUI控件库中&#xff0c;UIAvatar 控件是用来显示头像或图标的小部件&#xff0c;通常用于用户界面中代表用户或角色的图像。下面是如何在你的应用程序中使用 UIAvatar 的步骤&#xff1a; 1. 引入 SunnyUI 控件库 确保你的项目已经包含了 SunnyUI 控件库。如果是通过 …

PGCCC|【PostgreSQL】PCA+PCP+PCM等IT类认证申报个税退税指南

小编特将PostgreSQL证书申报个税退税流程&#xff0c;编辑成文&#xff0c;供大家申报参考哦~ 1.申报专项附加扣除 第一步&#xff1a;打开个人所得税APP&#xff0c;选择“专项附加扣除填报”&#xff1a; 第二步&#xff1a;“扣除年度”选择您要申报的年度&#xff0c;并…

Python input NameError: name ‘xxx‘ is not defined.

chiami.py name input("Come ti chiami?")type(name) print(name) $ python chimi.py Come ti chimi? xxx Traceback (most recent call last): File "chimi.py", line 1, in <module> name input("Come ti chiami?") …

script标签type属性

script标签中的type的使用 type MDN&#xff1a;该属性定义script标签元素包含或src应用的脚本语言&#xff0c;属性的值为MINE类型&#xff0c;也叫媒体类型。支持的为text/javascript,application/javascript,text/ecmascript,application/ecmascript,application/json,mod…

Windows 默认以管理员运行打开CMD

winr 默认以管理员打开运行CMD 需求&#xff1a;在运行页面输入cmd 希望是可以直接通过管理员方式打开的。 winr 打开运行 输入secpol.msc 打开本地安全策略&#xff08;注意家庭版是没有这个的&#xff09; 找到本地策略–安全选项–用户帐户控制: 以管理员批准模式运行所有管…

【网络编程】select函数

select的优点是跨平台的&#xff0c;缺点是因为是轮询查询的&#xff0c;相对效率不高 使用 select 同时监听多个文件描述符, 将监控的操作交给内核去处理&#xff0c;当有监控操作时返回。select可以完成一个进程对多个客户端的处理 #include <sys/select.h> #include…

基于Python thinker GUI界面的股票评论数据及投资者情绪分析设计与实现

1.绪论 1.1背景介绍 Python 的 Tkinter 库提供了创建用户界面的工具&#xff0c;可以用来构建股票评论数据及投资者情绪分析的图形用户界面&#xff08;GUI&#xff09;。通过该界面&#xff0c;用户可以输入股票评论数据&#xff0c;然后通过情感分析等技术对评论进行情绪分析…

前端数据加密方式

1、Base64加密 一、原生加解密 const btoa window.btoa(123) // 编码console.log(加密后,btoa)const atob window.atob(bota) // 解码console.log(解密后,atob) 二、base64插件 npm install --save js-base64 <script lang"ts"> import { defineCompon…

JavaScript 中 await 永远不会 resolve 的 Promise 会导致内存泄露吗?

前言 在 JavaScript 中&#xff0c;await 关键字用于等待一个 Promise 完成&#xff0c;它只能在异步函数&#xff08;async function&#xff09;内部使用。当 await 一个永远不会 resolve 的 Promise 时&#xff0c;它确实会阻塞异步函数的进一步执行&#xff0c;但不会直接…

Matlab中产生高斯白噪声信号的方法和其功率计算

Matlab中产生高斯白噪声信号的方法和其功率计算 matlab中计算信号能量&#xff1a; p o w e r ∑ n 1 N x 2 ( n ) power \sum_{n1}^Nx^2(n) powern1∑N​x2(n) ​ 功率为 P 1 N ∑ n 1 N x 2 ( n ) P \frac{1}{N}\sqrt{\sum_{n1}^Nx^2(n)} PN1​n1∑N​x2(n) ​ 对应ma…

C1W1.Assignment: Logistic Regression

理论课&#xff1a;C1W1.Sentiment Analysis with Logistic Regression 文章目录 前期准备导入包导入数据处理推文文本 Part 1: Logistic regressionPart 1.1: Sigmoid实现 sigmoid 函数Logistic regression: regression and a sigmoid Part 1.2 Cost function and GradientUp…

Python 使用proto 发送socket数据

import socket import binascii import struct from SensingMonitoring_pb2 import Command, CommandNamesif __name__ "__main__":client socket.socket(socket.AF_INET, socket.SOCK_STREAM)client.connect(("192.168.1.100", 22295))# 发送数据comman…

软件模块的初始化

什么是初始化&#xff1f; 软件的初始化&#xff08;Initialization&#xff09;是指软件启动或重新配置时执行的一系列步骤和过程&#xff0c;旨在准备软件运行环境、加载必要的配置信息、检查系统依赖项、分配资源&#xff08;如内存、文件句柄等&#xff09;&#xff0c;以及…