Java 快速排序的实现(通俗解释 + 详细代码)

快速排序的基本概念:

快速排序的核心就是选择一个基准值,然后将数组分成两部分:

  • 左边:比基准值小的元素。
  • 右边:比基准值大的元素。 然后递归地对左右两部分继续进行这个过程,直到每部分都排好序。

来,我们用现实生活中的例子来理解!🌟

假设你在整理一堆数字卡片📇,你想把这些卡片按从小到大的顺序排列。快速排序就像是你站在桌子旁边,对这些卡片进行一次大分拣📦,然后不断地把小卡片和大卡片分成左右两边,直到它们都排好位置。

举个具体的例子👇:

你有这样一堆数字:
[8, 3, 5, 1, 9, 6]

第一步:选一个基准值(pivot)

我们从中间选一个数字作为基准值,比如选择 6 作为基准。

第二步:分拣

  • 比6小的数字放到左边,即:[3, 5, 1]
  • 比6大的数字放到右边,即:[8, 9]
  • 基准值6就放在中间。

现在我们有了这样的分拣结果: 左边:[3, 5, 1], 中间:6, 右边:[8, 9]


第三步:递归处理左边和右边

  1. 对左边的数组 [3, 5, 1] 再次进行快速排序

    • 选择基准值:3
    • 左边:[1] (比3小)
    • 右边:[5] (比3大)

    现在左边排好了:[1, 3, 5]

  2. 右边的数组 [8, 9]

    • 这个部分已经排好了,因为8比9小。

第四步:组合结果

现在我们把所有部分组合起来:

  • 左边:[1, 3, 5]
  • 基准值:6
  • 右边:[8, 9]

最终得到的排序结果就是:
[1, 3, 5, 6, 8, 9]


简单总结快速排序的步骤👇:

  1. 选择基准值:选一个数字作为基准值,通常选择数组中的某个元素。
  2. 分拣:把比基准值小的放左边,比基准值大的放右边。
  3. 递归:对左边和右边的部分继续进行相同的操作。
  4. 组合结果:最终把排好序的部分拼在一起。

用生活中的例子来理解🔍:

Imagine 你要整理一个大抽屉里的袜子🧦。你先挑出一只作为“基准袜”,比如中等长度的,然后开始整理:

  • 比基准袜短的放一边(左边)。
  • 比基准袜长的放另一边(右边)。

接着你再分别整理两边的袜子,按照同样的方式继续分拣,直到所有的袜子都按长短排好顺序!


快速排序的优势

快速排序的效率很高,因为它每次都将问题规模减半。通过把问题分解成小问题,它能快速解决排序问题。平均时间复杂度是 O(n log n),在大多数情况下比冒泡排序(时间复杂度 O(n²))要快得多。

快速排序的完整Java代码:

public class QuickSortExample {

    // 快速排序的主方法,传入数组、最小索引和最大索引
    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);
        }
    }

    // 分区方法:选择一个基准值,把小于基准的元素放在左边,大于基准的放在右边
    private static int partition(int[] arr, int low, int high) {
        // 选择最右边的元素作为基准
        int pivot = arr[high];
        
        // i是用来追踪小于基准值的元素的位置
        int i = low - 1; 

        // 遍历数组,找到所有小于基准值的元素
        for (int j = low; j < high; j++) {
            // 如果当前元素小于或等于基准值
            if (arr[j] <= pivot) {
                i++; // 增加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 main(String[] args) {
        // 定义一个需要排序的数组
        int[] arr = {8, 3, 5, 1, 9, 6};

        // 打印排序前的数组
        System.out.println("排序前的数组:");
        printArray(arr);

        // 调用快速排序方法,排序整个数组
        quickSort(arr, 0, arr.length - 1);

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

    // 辅助方法:打印数组中的所有元素
    private static void printArray(int[] arr) {
        for (int num : arr) {
            System.out.print(num + " ");
        }
        System.out.println();
    }
}

代码详解:

  1. quickSort 方法:
    这是快速排序的主方法。它接收一个数组、最小索引(low)和最大索引(high)。如果当前子数组的大小大于1(low < high),它会找到基准值的正确位置,然后递归地排序左右两部分。
  2. partition 方法:
    这个方法的作用是将数组分成两部分
    • 左边是比基准值小或相等的元素。
    • 右边是比基准值大的元素。
      它返回的是基准值最终所在的位置,这样我们知道从哪里把数组一分为二。
  3. printArray 方法:
    这个方法是一个辅助方法,用来打印数组内容,方便我们查看排序前后的效果。

解释这个例子的通俗版本🌟:

  1. 选基准值
    比如我们从数组 [8, 3, 5, 1, 9, 6] 中选了 6 作为基准值。这个基准值就像是一条“分界线”,我们要把小于 6 的元素放到左边,把大于 6 的元素放到右边。
  2. 分左右
    遍历数组,依次将小于 6 的元素放在数组的前面,大于 6 的元素放到数组的后面。比如 3, 5, 和 1 会被移到前面,8, 9 会放到后面,6 作为基准值就在中间。
  3. 递归处理
    然后我们对左边部分 [3, 5, 1] 和右边部分 [8, 9] 继续做相同的分拣,直到每个部分都只有一个元素为止。
  4. 排序完成
    最后,所有的元素就按照从小到大的顺序排好了,结果是 [1, 3, 5, 6, 8, 9]
排序前的数组:
8 3 5 1 9 6 
排序后的数组:
1 3 5 6 8 9 

小结:

  • 快速排序通过挑选一个基准值,然后将数组分为两部分:左边比基准小,右边比基准大。
  • 然后对左右两部分继续递归进行快速排序,直到数组排序完毕。
  • 整个过程其实就是不停地“分拣”元素,类似于你把大小不同的物品进行快速分拣,最后得到排序结果。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值