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

java算法:快速排序

快速排序是一种常用的排序算法,它利用分治的思想将一个数组分成两个子数组,然后递归地对子数组进行排序,最终将整个数组排序完成。

快速排序的基本思想如下:

  1. 选择一个基准元素(pivot),通常选择数组的第一个或最后一个元素。
  2. 将数组分成两个部分,使得左边的元素都小于等于基准元素,右边的元素都大于基准元素。这个过程称为分区(partition)。
  3. 对左右两个部分分别递归地进行快速排序。
  4. 合并左右两个部分,得到最终的排序结果。

以下是用Java实现快速排序的示例代码:

public class QuickSort {public static void quickSort(int[] arr) {quickSort(arr, 0, arr.length - 1);}private 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[high];// 比基准元素小的元素的最终位置int i = low - 1;for (int j = low; j < high; j++) {// 如果当前元素小于等于基准元素,则将其放到小元素区域的末尾if (arr[j] <= pivot) {i++;swap(arr, i, j);}}// 将基准元素放到最终位置swap(arr, i + 1, 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;}public static void main(String[] args) {int[] arr = {4, 2, 6, 8, 3, 1, 5, 7};quickSort(arr);System.out.println("Sorted array:");for (int num : arr) {System.out.print(num + " ");}}
}

在上述代码中,quickSort()方法是快速排序的入口方法,它调用了私有的辅助方法quickSort()和partition()。quickSort()方法通过递归调用对子数组进行排序,而partition()方法用于将数组分区并返回基准元素的最终位置。

可以看到,快速排序算法成功地对数组进行了排序。快速排序的平均时间复杂度为O(nlogn),其中n是数组的长度。

快速排序的优点:

  • 高效:快速排序的平均时间复杂度为O(nlogn),其中n是数组的长度,是一种较快的排序算法。
  • 原地排序:快速排序使用了原地排序,不需要额外的空间来存储临时数据,只需要对数组进行原地交换操作。 快速排序的缺点:

快速排序的缺点:

  • 不稳定性:在分区过程中,相同元素的相对顺序可能会改变,因此快速排序是一种不稳定的排序算法。
  • 对于特定的输入情况,快速排序的性能可能会下降。当输入数组已经有序或近乎有序时,快速排序的时间复杂度会退化到O(n^2),其中n是数组的长度。为了避免这种情况,可以采用一些优化技巧,如随机选择基准元素或使用三数取中法来选择基准元素。

随机选择基准元素

  • 在每次分区之前,随机选择数组中的一个元素作为基准元素。
  • 这样可以降低出现最坏情况的概率,使得快速排序的期望时间复杂度更接近O(nlogn)。
private static void quickSort(int[] arr, int low, int high) {if (low < high) {// 随机选择基准元素int randomIndex = low + new Random().nextInt(high - low + 1);swap(arr, randomIndex, high);// 分区操作,返回基准元素的最终位置int pivotIndex = partition(arr, low, high);// 递归排序基准元素左边的子数组quickSort(arr, low, pivotIndex - 1);// 递归排序基准元素右边的子数组quickSort(arr, pivotIndex + 1, high);}
}

三数取中法选择基准元素

  • 从待排序数组的起始、中间和末尾位置各选取一个元素。
  • 对这三个元素进行排序,并选择其中位于中间位置的元素作为基准元素。
  • 这样可以尽量选择一个接近中间值的元素作为基准元素,减少最坏情况的概率。
private static void quickSort(int[] arr, int low, int high) {if (low < high) {// 三数取中法选择基准元素int mid = low + (high - low) / 2;if (arr[low] > arr[mid]) {swap(arr, low, mid);}if (arr[mid] > arr[high]) {swap(arr, mid, high);if (arr[low] > arr[mid]) {swap(arr, low, mid);}}// 分区操作,返回基准元素的最终位置int pivotIndex = partition(arr, low, high);// 递归排序基准元素左边的子数组quickSort(arr, low, pivotIndex - 1);// 递归排序基准元素右边的子数组quickSort(arr, pivotIndex + 1, high);}
}

总结:快速排序通过分区和递归的方式实现了高效的排序,是一种常用的排序算法。尽管它有一些缺点,但在大多数情况下,快速排序仍然是一种高效的排序算法。

相关文章:

  • 北京网站建设多少钱?
  • 辽宁网页制作哪家好_网站建设
  • 高端品牌网站建设_汉中网站制作
  • 车载网络安全指南 概述(一)
  • PHP实名认证接口开发示例、银行卡实名认证API
  • C语言| 编程获取数组的长度
  • Ubuntu Server 20.04挂载磁盘
  • STM32的FreeRtos的学习
  • Spring Web MVC之过滤器Filter和拦截器HandlerInterceptor的区别和用法
  • Python第二语言(十、Python面向对象(上))
  • Java 类加载器与加载机制
  • 详解 Flink Table API 和 Flink SQL 之函数
  • 计算机网络(3) 字节顺序:网络字节序与IPv4
  • Stack详解(含动画演示)
  • Hutool有哪些常用方法
  • 服务架构的设计原则
  • DS1338/PT7C4338串行实时时钟-国产兼容RS4C1338
  • 如何免费用 Qwen2 辅助你翻译与数据分析?
  • [分享]iOS开发 - 实现UITableView Plain SectionView和table不停留一起滑动
  • C++回声服务器_9-epoll边缘触发模式版本服务器
  • docker-consul
  • Golang-长连接-状态推送
  • gulp 教程
  • iOS帅气加载动画、通知视图、红包助手、引导页、导航栏、朋友圈、小游戏等效果源码...
  • JAVA_NIO系列——Channel和Buffer详解
  • Javascripit类型转换比较那点事儿,双等号(==)
  • Nginx 通过 Lua + Redis 实现动态封禁 IP
  • text-decoration与color属性
  • 第十八天-企业应用架构模式-基本模式
  • 动手做个聊天室,前端工程师百无聊赖的人生
  • 翻译:Hystrix - How To Use
  • 基于Android乐音识别(2)
  • 解决iview多表头动态更改列元素发生的错误
  • 每天10道Java面试题,跟我走,offer有!
  • 如何利用MongoDB打造TOP榜小程序
  • 设计模式(12)迭代器模式(讲解+应用)
  • 机器人开始自主学习,是人类福祉,还是定时炸弹? ...
  • 完善智慧办公建设,小熊U租获京东数千万元A+轮融资 ...
  • ​14:00面试,14:06就出来了,问的问题有点变态。。。
  • ​secrets --- 生成管理密码的安全随机数​
  • #C++ 智能指针 std::unique_ptr 、std::shared_ptr 和 std::weak_ptr
  • (vue)el-cascader级联选择器按勾选的顺序传值,摆脱层级约束
  • (第27天)Oracle 数据泵转换分区表
  • (定时器/计数器)中断系统(详解与使用)
  • (二刷)代码随想录第15天|层序遍历 226.翻转二叉树 101.对称二叉树2
  • (机器学习-深度学习快速入门)第三章机器学习-第二节:机器学习模型之线性回归
  • (十一)c52学习之旅-动态数码管
  • (四)opengl函数加载和错误处理
  • (太强大了) - Linux 性能监控、测试、优化工具
  • (未解决)jmeter报错之“请在微信客户端打开链接”
  • (转) 深度模型优化性能 调参
  • (转)自己动手搭建Nginx+memcache+xdebug+php运行环境绿色版 For windows版
  • ... fatal error LINK1120:1个无法解析的外部命令 的解决办法
  • .NET “底层”异步编程模式——异步编程模型(Asynchronous Programming Model,APM)...
  • .net 调用php,php 调用.net com组件 --
  • .sys文件乱码_python vscode输出乱码
  • @LoadBalanced 和 @RefreshScope 同时使用,负载均衡失效分析
  • @Transactional 竟也能解决分布式事务?