网站首页 > 精选教程 正文
快速排序(Quick Sort)是一种常用的排序算法,它的时间复杂度为O(nlogn),是在平均情况下具有良好性能的排序算法之一。
一、原理
快速排序算法采用了分治的思想,将一个大问题分解成若干个小问题来解决。其基本思路是选取一个基准元素,将数组分成两个子序列,其中一个子序列的所有元素都小于基准元素,另一个子序列的所有元素都大于或等于基准元素。然后再对这两个子序列进行递归操作,直到所有序列长度为1时排序完成。
快速排序的平均时间复杂度为O(nlogn),最坏情况下的时间复杂度为O(n^2),其中n为待排序的元素个数。快速排序对于大规模数据的排序效率比较高,是常用排序算法之一。
二、快速排序算法实现过程
快速排序的实现需要完成以下几步:
- 选择序列中的一个元素作为基准值(pivot),通常选择首个元素或末尾元素作为基准值;
- 将低于基准元素的放到左边,高于或等于基准元素的放到右边。
- 对基准值左右两侧的子序列分别重复上述步骤,直到所有元素均被排完序为止。
2.1 选择基准元素
选择基准元素是快速排序的第一步,其目的是将待排序数组分成两个子序列。最常用的方法是选取第一个元素作为基准元素。但是,如果待排序数组已经有序或近乎有序,那么选取第一个元素就会导致快速排序的时间复杂度变为O(n^2)。为了解决这个问题,可以采用随机化的方法来选择基准元素。
以下是选取第一个元素作为基准元素的代码实现:
public static int partition(int[] arr, int low, int high) {
int pivot = arr[low]; //基准元素
while (low < high) {
while (low < high && arr[high] >= pivot) {
high--;
}
arr[low] = arr[high]; //将比基准元素小的移到低端
while (low < high && arr[low] <= pivot) {
low++;
}
arr[high] = arr[low]; //将比基准元素大的移到高端
}
arr[low] = pivot; //把基准元素放到最终位置
return low;
}
以下是采用随机化方法选择基准元素的代码实现:
public static int partition(int[] arr, int low, int high) {
int randomIndex = (int) (Math.random() * (high - low + 1)) + low; //随机选取一个位置
swap(arr, randomIndex, high); //交换基准元素和随机元素
int pivot = arr[high]; //基准元素
while (low < high) {
while (low < high && arr[low] <= pivot) {
low++;
}
arr[high] = arr[low]; //将比基准元素大的移到高端
while (low < high && arr[high] >= pivot) {
high--;
}
arr[low] = arr[high]; //将比基准元素小的移到低端
}
arr[high] = pivot; //把基准元素放到最终位置
return high;
}
private static void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
2.2 将低于基准元素的放到左边,高于或等于基准元素的放到右边
这一步是快速排序的关键步骤,其代码实现如下:
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); //递归排序右半部分
}
}
2.3 对基准值左右两侧的子序列分别重复上述步骤,直到所有元素均被排完序为止。
这一步是快速排序的递归过程,其代码实现如上文所示。
三、示例代码
下面是使用Java语言实现快速排序的示例代码:
import java.util.Arrays;
public class QuickSort {
public static void main(String[] args) {
int[] arr = {32, 6, 17, 28, 10, 22, 43, 13, 48, 35};
System.out.println("Before sorting: " + Arrays.toString(arr));
quickSort(arr, 0, arr.length - 1);
System.out.println("After sorting: " + Arrays.toString(arr));
}
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); //递归排序右半部分
}
}
public static int partition(int[] arr, int low, int high) {
int randomIndex = (int) (Math.random() * (high - low + 1)) + low; //随机选取一个位置
swap(arr, randomIndex, high); //交换基准元素和随机元素
int pivot = arr[high]; //基准元素
while (low < high) {
while (low < high && arr[low] <= pivot) {
low++;
}
arr[high] = arr[low]; //将比基准元素大的移到高端
while (low < high && arr[high] >= pivot) {
high--;
}
arr[low] = arr[high]; //将比基准元素小的移到低端
}
arr[high] = pivot; //把基准元素放到最终位置
return high;
}
private static void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
四、动图效果演示
上面的动图效果的步骤,首先基准值取第一个元素32,然后逐一比较,把小于基准值的移到左侧,大于基准值的移到右侧。整个数组拆分成了P1、P2两个数组
接着对左侧的P1数组进行快速排序,基准值取第一个元素13,那么P1数组又被拆分成更小的左右两个数组P3、P4。
继续对上面拆分出来的P3数组快速排序,基准值取第一个元素10
左侧数组的长度已经是1,排序已经完成,开始对13的右边P4数组快速排序,基准值取第一个元素28,P4中没有比基准值28大的数字,所以只有左侧的P5数组
接着是28的左侧P5数组快速排序,基准值取第一个元素22,
结果数组长度已经是1,结束。
接着对32的右侧部分P2数组快速排序,基准值取第一个元素43
到这里,所有最小单位的数组都已经拆成了长度为1的数组,无法继续拆分,快速排序结束得到了最终的结果。
- 上一篇: 排序算法详解(java代码实现)
- 下一篇: 十大经典排序算法之选择排序
猜你喜欢
- 2024-12-17 深圳尚学堂Java培训:可视化排序实践之选择排序
- 2024-12-17 深圳尚学堂Java培训:排序方法小结-选择排序
- 2024-12-17 下一个排列(算法思路清晰)Java
- 2024-12-17 Redis实现排行榜设计
- 2024-12-17 「数据结构与算法」 合并排序
- 2024-12-17 极客算法训练笔记(十),十大经典排序之计数排序、基数排序
- 2024-12-17 太厉害了!腾讯T4大牛把《数据结构与算法》讲透了,带源码笔记
- 2024-12-17 希尔排序(java)
- 2024-12-17 看动画学算法之:排序-选择排序
- 2024-12-17 navicat如何进行排序?附安装包
你 发表评论:
欢迎- 最近发表
- 标签列表
-
- nginx反向代理 (57)
- nginx日志 (56)
- nginx限制ip访问 (62)
- mac安装nginx (55)
- java和mysql (59)
- java中final (62)
- win10安装java (72)
- java启动参数 (64)
- java链表反转 (64)
- 字符串反转java (72)
- java逻辑运算符 (59)
- java 请求url (65)
- java信号量 (57)
- java定义枚举 (59)
- java字符串压缩 (56)
- java中的反射 (59)
- java 三维数组 (55)
- java插入排序 (68)
- java线程的状态 (62)
- java异步调用 (55)
- java中的异常处理 (62)
- java锁机制 (54)
- java静态内部类 (55)
- java怎么添加图片 (60)
- java 权限框架 (55)
本文暂时没有评论,来添加一个吧(●'◡'●)