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

排序算法:详解快速排序

快速排序介绍

快速排序是一种高效的分治排序算法,由Tony Hoare在1960年提出。它的核心思想是"分而治之",通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,然后分别对这两部分记录继续进行排序,以达到整个序列有序。

快速排序实现

一、工作原理

原始数组: [10, 7, 8, 9, 1, 5]
步骤1: 选择基准元素(这里选择最后一个元素5)
步骤2: 分区操作,将小于5的放在左边,大于5的放在右边[1, 5, 8, 9, 10, 7]  // 5已经在正确位置
步骤3: 递归排序左半部分[1]和右半部分[8, 9, 10, 7]左半部分[1]已经有序右半部分选择基准7 → [7, 9, 10, 8] → 继续递归...

二、分区过程详解

分区是快速排序的核心操作,以最后一个元素为基准:

数组: [10, 80, 30, 90, 40, 50, 70]
基准: 70分区过程:
i = -1, j = 0: 10 < 70 → 交换arr[++i]和arr[j] → [10, 80, 30, 90, 40, 50, 70]
i = 0,  j = 1: 80 > 70 → 不交换
i = 0,  j = 2: 30 < 70 → 交换 → [10, 30, 80, 90, 40, 50, 70]
i = 1,  j = 3: 90 > 70 → 不交换
i = 1,  j = 4: 40 < 70 → 交换 → [10, 30, 40, 90, 80, 50, 70]
i = 2,  j = 5: 50 < 70 → 交换 → [10, 30, 40, 50, 80, 90, 70]
最后交换基准: 交换arr[i+1]和arr[high] → [10, 30, 40, 50, 70, 90, 80]
基准70已经在正确位置!

算法特点

代码实现

一、基础版(Lomuto分区方案)

public class QuickSortBasic {/*** 快速排序主方法*/public static void quickSort(int[] arr) {if (arr == null || arr.length <= 1) {return;}quickSort(arr, 0, arr.length - 1);}/*** 递归快速排序* @param arr 待排序数组* @param low 起始索引* @param high 结束索引*/private static void quickSort(int[] arr, int low, int high) {if (low < high) {// 分区操作,获取基准元素的正确位置int pivotIndex = partition(arr, low, high);System.out.println("基准元素 " + arr[pivotIndex] + " 已就位,数组状态: " + arrayToString(arr, low, high));// 递归排序左半部分quickSort(arr, low, pivotIndex - 1);// 递归排序右半部分quickSort(arr, pivotIndex + 1, high);}}/*** Lomuto分区方案* @return 基准元素的最终位置*/private static int partition(int[] arr, int low, int high) {// 选择最后一个元素作为基准int pivot = arr[high];System.out.println("分区: [" + low + "-" + high + "], 基准: " + pivot);// i指向小于基准的区域的边界int i = low - 1;for (int j = low; j < high; j++) {// 如果当前元素小于或等于基准if (arr[j] <= pivot) {i++;swap(arr, i, j);if (i != j) {System.out.println("  交换 " + arr[j] + " 和 " + arr[i] + " → " + arrayToString(arr, low, high));}}}// 将基准元素放到正确位置swap(arr, i + 1, high);System.out.println("  基准就位: " + arrayToString(arr, low, high));return i + 1;}/*** 交换数组中的两个元素*/private static void swap(int[] arr, int i, int j) {int temp = arr[i];arr[i] = arr[j];arr[j] = temp;}/*** 辅助方法:打印数组指定范围*/private static String arrayToString(int[] arr, int low, int high) {StringBuilder sb = new StringBuilder("[");for (int i = low; i <= high; i++) {sb.append(arr[i]);if (i < high) sb.append(", ");}sb.append("]");return sb.toString();}public static void main(String[] args) {int[] arr = {10, 7, 8, 9, 1, 5};System.out.println("原始数组: " + java.util.Arrays.toString(arr));System.out.println("开始快速排序:");quickSort(arr);System.out.println("排序结果: " + java.util.Arrays.toString(arr));}
}

二、优化版(Hoare分区方案+三数取中)

public class OptimizedQuickSort {/*** 优化版快速排序* 优化点1: 使用Hoare分区方案,减少交换次数* 优化点2: 三数取中法选择基准,避免最坏情况* 优化点3: 小数组使用插入排序*/public static void quickSortOptimized(int[] arr) {if (arr == null || arr.length <= 1) return;quickSortOptimized(arr, 0, arr.length - 1);}private static void quickSortOptimized(int[] arr, int low, int high) {// 小数组使用插入排序if (high - low + 1 <= 10) {insertionSort(arr, low, high);return;}if (low < high) {// 选择基准并分区int pivotIndex = hoarePartition(arr, low, high);// 递归排序quickSortOptimized(arr, low, pivotIndex);quickSortOptimized(arr, pivotIndex + 1, high);}}/*** Hoare分区方案 - 更高效的分区方法*/private static int hoarePartition(int[] arr, int low, int high) {// 三数取中法选择基准int pivot = medianOfThree(arr, low, high);int i = low - 1;int j = high + 1;while (true) {// 从左向右找到第一个大于等于基准的元素do {i++;} while (arr[i] < pivot);// 从右向左找到第一个小于等于基准的元素do {j--;} while (arr[j] > pivot);// 如果指针相遇,返回分区位置if (i >= j) {return j;}// 交换元素swap(arr, i, j);}}/*** 三数取中法:选择左、中、右三个数的中值作为基准*/private 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);// 将中值放在high-1位置,返回中值作为基准swap(arr, mid, high);return arr[high];}/*** 插入排序,用于小数组*/private 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;}}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 = {64, 34, 25, 12, 22, 11, 90, 5, 77, 30, 15, 42};System.out.println("原始数组: " + java.util.Arrays.toString(arr));quickSortOptimized(arr);System.out.println("排序结果: " + java.util.Arrays.toString(arr));}
}

使用建议

  • 推荐使用:大规模数据排序、通用排序需求
  • 避免使用:需要稳定排序的场景、对最坏性能要求严格的场景
  • 优化重点:合理的基准选择、处理小数组、避免最坏情况

快速排序以其优异的平均性能和缓存友好性,成为实际应用中最常用的排序算法之一!

架构设计之道在于在不同的场景采用合适的架构设计,架构设计没有完美,只有合适。
在代码的路上,我们一起砥砺前行。用代码改变世界!

  • 工作 3 年还在写 CRUD,无法突破技术瓶颈?
  • 想转技术管理但不会带团队?
  • 想跳槽没有面试的机会?
  • 不懂如何面试,迟迟拿不到 offer?
  • 面试屡屡碰壁,失败原因无人指导?
  • 在竞争激烈的大环境下,只有不断提升核心竞争力才能立于不败之地。

欢迎从事编程开发、技术招聘 HR 进群,欢迎大家分享自己公司的内推信息,相互帮助,一起进步!

—— 斩获心仪Offer,破解面试密码 ——

在这里插入图片描述

http://www.dtcms.com/a/499253.html

相关文章:

  • 安阳哪里做360网站科技感十足的网站
  • UV 紫外相机在半导体制造领域的应用
  • 突破亚微米光电子器件制造瓶颈!配体交换辅助打印技术实现全打印红外探测器
  • 可见光工业相机半导体制造领域中的应用
  • require和 import是两种不同的模块引入方式的区别
  • 半导体制造工艺基本认识 五 薄膜沉积
  • 矩阵及其应用
  • **发散创新:探索零信任网络下的安全编程实践**随着信息技术的飞速发展,网络安全问题日益凸显。传统的网络安全防护方式已难以
  • 网络营销方案毕业设计安卓手机性能优化软件
  • 建设企业网站价格建设银行北京市财满街分行网站
  • (Kotlin高级特性一)kotlin的扩展函数和属性在字节码层面是如何实现的
  • Spring Boot 3零基础教程,WEB 开发 静态资源默认配置 笔记27
  • 【论文精度-2】求解车辆路径问题的神经组合优化算法:综合展望(Yubin Xiao,2025)
  • 赣州哪里做网站域名注册备案
  • windows双系统下 ubutnu 20.04 启动项出问题无法进入ubuntu 20.04的解决方法
  • MQTT 协议全面学习笔记
  • 加权分位数直方图:提升机器学习效能的关键技术
  • 做分析图网站无锡seo优化
  • SQL CHECK约束详解
  • 【java接口实现】一个简单接口实现模板
  • 嵌入式Linux:线程同步(条件变量)
  • 从“小而美”到“大而强”:音视频直播SDK的技术进化逻辑
  • 2五、buildroot支持Qt5
  • 我做的网站怎么打开很慢电信网络运营商
  • 敦化网站开发淘宝网网页版登录平台
  • Umi-OCR制作双层PDF
  • TD 通达OAOAV12.9版本的密码重置
  • 【办公类-115-02】20251018信息员每周通讯上传之文字稿整理(PDF转docx没有成功)
  • MySQL表设计详解
  • AI 编程 Trae ,有重大更新!用 Trae 做了个图书借阅网站!