快速排序算法

简介

快速排序(Quick Sort)是一种高效的排序算法,由英国计算机科学家东尼·霍尔(Tony Hoare)在1960年提出。快速排序的基本思想是通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
快速排序的步骤如下:
1. 选择基准(Pivot):在数据集之中,选择一个元素作为"基准"(pivot)。
2. 分区(Partitioning):将数组进行分区,将小于基准的元素移到基准的左边,大于基准的元素移到基准的右边。分区完成后,基准元素所处的位置就是最终排序后它的位置。
3. 递归排序:递归地将小于基准的元素的子序列和大于基准的元素的子序列排序。
快速排序的算法特点:
时间复杂度:平均情况为O(n log n),最坏情况为O(n^2),但最坏情况并不常见,通常可以通过随机选择基准来避免。
空间复杂度:O(log n),因为它是递归的,需要使用栈空间来存储递归调用信息。
稳定性:快速排序不是一个稳定的排序算法,因为在排序过程中相等的元素可能会因为分区操作而改变它们的相对顺序。
内部排序:快速排序是在内存中进行的,不需要额外的存储空间。
快速排序因其效率高、实现简单而在实际应用中非常受欢迎,是处理大量数据时常用的排序算法之一。

实例

假设现在有一组数据如下:

首先第一步,以13为基准元素(通常用第一个元素),从小到大排序。

设两个指针,分别指向左边第一个元素和右边第一个元素。

从右边开始,比较两个指针的大小,只要指针r小于指针l,则交换二者的值,之后指针l开始右移,继续比较,一旦交换位置,则换另一边的指针移动,直至两个指针会合。

第一轮

9<13,交换位置,指针l右移。

24>13,交换位置,指针r左移。

10<13,交换位置,指针l右移。

35>13,交换位置,指针r左移。

27>13,保持原位,指针r继续左移。

15>13,保持原位,指针r继续左移。

42>13,保持原位,指针r继续左移。

86>13,保持原位,指针r继续左移。

67>13,保持原位,指针r继续左移。

此时指针l和指针r会合了,基准元素归位,左侧全是比它小的,右侧全是比它大的。

第二轮

左边以9为基准元素,右边以67为基准元素。

左边9<10,直接归位了,右边67>24,故交换位置,按照之前的方法,第二轮最终结果为:

67归位。

第三轮

10,24,86归位。

第四轮

15,42归位。

第五轮

27,35归位。

至此,排序完成。

代码实现

使用java编写一个经典的快速排序程序。

package sort;

import java.util.Scanner;

public class QuickSort {

    public static void main(String[] args) {
        // 创建一个扫描器对象,用于从控制台读取输入
        Scanner scanner = new Scanner(System.in);
        // 提示用户输入数组的元素个数
        System.out.print("请输入数组中的元素个数: ");
        int n = scanner.nextInt();

        // 根据用户输入的元素个数创建数组
        int[] arr = new int[n];
        // 提示用户输入数组元素
        System.out.println("请输入 " + n + " 个整数:");
        for (int i = 0; i < n; i++) {
            arr[i] = scanner.nextInt();
        }

        // 调用快速排序算法对数组进行排序
        quickSort(arr, 0, n - 1);

        // 输出排序后的数组
        System.out.println("排序后的数组:");
        printArray(arr);
    }

    // 快速排序算法
    public static void quickSort(int[] arr, int low, int high) {
        // 如果low小于high,说明还可以继续划分
        if (low < high) {
            // 获取分区点索引
            int pi = partition(arr, low, high);
            // 递归排序分区点左侧的子数组
            quickSort(arr, low, pi - 1);
            // 递归排序分区点右侧的子数组
            quickSort(arr, pi + 1, high);
        }
    }

    // 对数组进行分区操作
    public 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++; // 移动小于基准值的元素的索引
                // 交换arr[i]和arr[j]
                int temp = arr[i];
                arr[i] = arr[j];
                arr[j] = temp;
            }
        }
        // 将基准值放到正确的位置
        int temp = arr[i + 1];
        arr[i + 1] = arr[high];
        arr[high] = temp;
        // 返回基准值的索引
        return i + 1;
    }

    // 打印数组元素
    public static void printArray(int[] arr) {
        for (int i = 0; i < arr.length; i++) {
            System.out.print(arr[i] + " ");
        }
        System.out.println();
    }
}

运行验证一下

总结

关于快速排序,还有很多变式,这里只是简单介绍一下,谢谢大家。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值