java-快速排序 1

Java中的快速排序

1. 快速排序的基本概念

快速排序(Quick Sort)是一种高效的排序算法,由Tony Hoare在1960年提出。它采用分治法(Divide and Conquer)策略来将一个数组分成较小的子数组,并分别对它们进行排序。快速排序通常被认为是最实用的排序算法之一,因为它在大多数情况下具有非常好的平均性能。

2. 快速排序的工作原理

快速排序的核心思想是通过一个称为"基准"(Pivot)的元素将数组分为两部分,使得基准左侧的元素都小于基准,右侧的元素都大于基准。然后,递归地对左右两部分进行同样的操作,直到整个数组有序。

2.1 分治法

快速排序使用分治法,将问题递归地分解成更小的子问题。具体步骤如下:

  1. **选择基准**:从数组中选择一个元素作为基准,通常选择第一个元素或最后一个元素。

  2. **划分数组**:重排数组,使得基准左侧的元素都小于基准,右侧的元素都大于基准。

  3. **递归排序**:递归地对基准左侧和右侧的子数组进行排序。

2.2 示例

假设有一个待排序的数组 `10, 7, 8, 9, 1, 5`,快速排序的过程如下:

  1. 选择基准元素,假设选择最后一个元素 `5`。

  2. 划分数组,将小于 `5` 的元素移到左侧,大于 `5` 的元素移到右侧,得到 `1, 7, 8, 9, 10, 5`。

  3. 基准 `5` 已经在正确的位置,现在对左侧 `1, 7, 8, 9, 10` 和右侧空数组进行递归排序。

  4. 重复上述步骤,直到数组有序。

3. 快速排序的实现

在Java中实现快速排序可以使用递归方法,下面是详细的实现步骤。

3.1 基本实现

```java

public class QuickSort {

// 快速排序主方法

public static void quickSort(int\[\] array, int low, int high) {

if (low < high) {

// 找到划分点

int pi = partition(array, low, high);

// 递归排序划分点左侧的数组

quickSort(array, low, pi - 1);

// 递归排序划分点右侧的数组

quickSort(array, pi + 1, high);

}

}

// 划分方法

private static int partition(int\[\] array, int low, int high) {

int pivot = arrayhigh; // 选择最后一个元素作为基准

int i = low - 1; // i指向小于基准的区域的最后一个元素

for (int j = low; j < high; j++) {

if (arrayj < pivot) {

i++;

// 交换元素

int temp = arrayi;

arrayi = arrayj;

arrayj = temp;

}

}

// 交换基准元素到正确的位置

int temp = arrayi + 1;

arrayi + 1 = arrayhigh;

arrayhigh = temp;

return i + 1;

}

public static void main(String\[\] args) {

int\[\] array = {10, 7, 8, 9, 1, 5};

quickSort(array, 0, array.length - 1);

System.out.println("Sorted array:");

for (int i : array) {

System.out.print(i + " ");

}

}

}

```

在这个实现中,`quickSort`方法是快速排序的主方法,它递归地对数组进行排序。`partition`方法是划分数组的方法,它选择一个基准元素,并将数组划分为两部分。

4. 快速排序的时间复杂度

快速排序的时间复杂度取决于选择基准的策略和输入数组的初始顺序:

  • **最好情况**:每次划分都能将数组均匀地分成两部分,时间复杂度为 O(n log n)。

  • **最坏情况**:每次划分只能减少一个元素,例如输入数组已经有序或逆序,时间复杂度为 O(n^2)。

  • **平均情况**:通过随机选择基准或三数取中法等策略,可以避免最坏情况,平均时间复杂度为 O(n log n)。

5. 快速排序的空间复杂度

快速排序的空间复杂度主要由递归调用栈的深度决定:

  • **最好情况**:递归调用栈的深度为 O(log n)。

  • **最坏情况**:递归调用栈的深度为 O(n)。

  • **平均情况**:递归调用栈的深度为 O(log n)。

6. 快速排序的优化

为了提高快速排序的性能,可以进行以下优化:

6.1 三数取中法

选择基准时,使用三数取中法可以避免选择最小或最大的元素作为基准,从而避免最坏情况。

```java

private static int medianOfThree(int\[\] array, int low, int high) {

int mid = (low + high) / 2;

if (arraylow > arraymid) swap(array, low, mid);

if (arraylow > arrayhigh) swap(array, low, high);

if (arraymid > arrayhigh) swap(array, mid, high);

return arraymid;

}

private static void swap(int\[\] array, int i, int j) {

int temp = arrayi;

arrayi = arrayj;

arrayj = temp;

}

private static int partition(int\[\] array, int low, int high) {

int pivot = medianOfThree(array, low, high);

int i = low - 1;

for (int j = low; j < high; j++) {

if (arrayj < pivot) {

i++;

swap(array, i, j);

}

}

swap(array, i + 1, high);

return i + 1;

}

```

6.2 随机选择基准

随机选择基准可以避免最坏情况的发生,保证平均时间复杂度为 O(n log n)。

```java

private static int partition(int\[\] array, int low, int high) {

int pivotIndex = low + (int)(Math.random() * (high - low + 1));

swap(array, pivotIndex, high);

int pivot = arrayhigh;

int i = low - 1;

for (int j = low; j < high; j++) {

if (arrayj < pivot) {

i++;

swap(array, i, j);

}

}

swap(array, i + 1, high);

return i + 1;

}

```

7. 快速排序的稳定性

快速排序不是一个稳定的排序算法,因为在划分过程中,相等元素的相对顺序可能会改变。然而,快速排序可以通过一些改进来实现稳定性,但这通常会增加算法的复杂性和开销。

相关推荐
dtq04242 小时前
数据结构 - 堆
数据结构
Cc.Y4 小时前
Java零基础入门:字符串深度掌握——从基础API到StringBuilder性能优化
java·开发语言·性能优化
nhdh8 小时前
B+树揭秘:MySQL索引核心原理全解析
数据结构·b树·mysql
shuoshuohaohao8 小时前
MyBatis 小知识点
java·spring·mybatis
海上小飞龙9 小时前
【KMP算法-下篇】同一道题:Java 库函数 2600 微秒,手写 KMP 16 微秒
java·开发语言·算法
青少儿编程课堂9 小时前
后缀自动机解析:本质不同子串与最长重复片段统计
c++·python·算法·bfs·信息学竞赛
朝朝辞暮i9 小时前
C++ 第 12 课:局部变量、作用域、变量生命周期
开发语言·c++·算法
谢亮_vipxieliang9 小时前
泛型擦除、通配符与 PECS 一次讲透
java·面试
八解毒剂10 小时前
【计组】中央处理器CPU
java·开发语言·计算机组成原理
乐迪信息10 小时前
港口船舶逆行怎么管?AI防爆摄像机搭载智能检测算法
大数据·人工智能·深度学习·算法·计算机视觉