快速排序
快速排序
快速排序算法首先会在序列中随机选择一个基准值(pivot),然后将除了基准值以外的数分为“比基准值小的数”和“比基准值大的数”这两个类别,再将其排列成以下形式。
[比基准值小的数] 基准值 [比基准值大的数]
接着,对两个“[ ]”中的数据进行排序之后,整体的排序便完成了。对“[]”里面的数据进行排序时同样也会使用快速排序。
基本思路
快速排序是一种“分治法”。它将原本的问题分成两个子问题(比基准值小的数和比基准值大的数),然后再分别解决这两个问题。子问题,也就是子序列完成排序后,再像一开始说明的那样,把他们合并成一个序列,那么对原始序列的排序也就完成了。
不过,解决子问题的时候会再次使用快速排序,甚至在这个快速排序里仍然要使用快速排序。只有在子问题里只剩一个数字的时候,排序才算完成。
快速排序效率
分割子序列时需要选择基准值,如果每次选择的基准值都能使得两个子序列的长度为原本的一半,那么快速排序的运行时间和归并排序的一样,都为O(nlogn)。和归并排序类似,将序列对半分割log2n次之后,子序列里便只剩下一个数据,这时子序列的排序也就完成了。因此,如果像下图这样一行行地展现根据基准值分割序列的过程,那么总共会有log2n行。
每行中每个数字都需要和基准值比较大小,因此每行所需的运行时间为O(n)。由此可知,整体的时间复杂度为O(nlogn)。
如果运气不好,每次都选择最小值作为基准值,那么每次都需要把其他数据移到基准值的右边,递归执行n行,运行时间也就成了O(n2)。这就相当于每次都选出最小值并把它移到了最左边,这个操作也就和选择排序一样了。此外,如果数据中的每个数字被选为基准值的概率都相等,那么需要的平均运行时间为O(nlogn)。
代码示例
示例1:
private static List<Integer> quicksort(List<Integer> list) { if (list.size() < 2) { // 基线条件:为空或只包含一个元素的数组是“有序”的 // base case, arrays with 0 or 1 element are already "sorted" return list; } else { // recursive case // 递归条件 Integer pivot = list.get(0); // sub-array of all the elements less than the pivot // 由所有小于基准值的元素组成的子数组 List<Integer> less = list.stream().skip(1).filter(el -> el <= pivot).collect(Collectors.toList()); // sub-array of all the elements greater than the pivot // 由所有大于基准值的元素组成的子数组 List<Integer> greater = list.stream().skip(1).filter(el -> el > pivot).collect(Collectors.toList()); return Stream.of(quicksort(less).stream(), Stream.of(pivot), quicksort(greater).stream()) .flatMap(Function.identity()).collect(Collectors.toList()); } } public static void main(String[] args) { System.out.println(quicksort(Arrays.asList(10, 5, 2, 3))); // [2, 3, 5, 10] }
示例2:
static void quickSort(int[] arr, int left, int right) { int temp, ltemp = left, rtemp = right; int f = arr[(left + right) / 2];//分界值 while (ltemp < rtemp) { while (arr[ltemp] < f) {//找出左边 大于分界值的 index ++ltemp; } while (arr[rtemp] > f) {//找出右边 大于分界值的 index --rtemp; } if (ltemp <= rtemp) { //ltemp和rtemp互换 temp = arr[ltemp]; arr[ltemp] = arr[rtemp]; arr[rtemp] = temp; ++ltemp; --rtemp; } } if (ltemp == rtemp) { ltemp++; } if (left < rtemp) { quickSort(arr, left, ltemp - 1); } if (ltemp < right) { quickSort(arr, rtemp + 1, right); } System.out.println(ArrayUtils.toString(arr)); } public static void main(String[] args) { quickSort(new int[]{5, 4, 3, 2, 1}, 0, 4); }
参考:
百度百科-快速排序
Java常用算法手册-4.6
我的第一本算法书 2-7 快速排序
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律