《算法图解》读书笔记 - 快速排序

《算法图解》- 快速排序

快速排序------一种常用的优雅的排序算法,快速排序使用分而治之的策略。

1. 分而治之

D&C(dvide and conquer)算法是递归的。
使用D&C解决问题的过程包括两个步骤:
(1)找出基线条件,这种条件必须尽可能简单。
(2)不断将问题分解(或者说缩小规模),直到符合基线条件。

D&C并非可用于解决问题的算法,而是一种解决问题的思路。

2. 快速排序

快速排序是一种常用的排序算法,比选择排序快得多。
例如,C语言标准库中的函数qsort实现的就是快速排序。
下面来使用快速排序对数组进行排序。对排序算法来说,最简单的数组什么样呢?就是根本不需要排序的数组。

在这里插入图片描述
因此,基线条件为数组为空或只包含一个元素。在这种情况下,只需原样返回数组——根本就不用排序。

我们来看看更长的数组。对包含两个元素的数组进行排序也很容易。
在这里插入图片描述

包含三个元素的数组呢?
在这里插入图片描述

别忘了,你要使用D&C,因此需要将数组分解,直到满足基线条件。下面介绍快速排序的工作原理。
首先,从数组中选择一个元素,这个元素被称为基准值(pivot)。
在这里插入图片描述
稍后再介绍如何选择合适的基准值。我们暂时将数组的第一个元素用作基准值。
接下来,找出比基准值小的元素以及比基准值大的元素。
在这里插入图片描述

这被称为分区(partitioning)。现在你有:
 一个由所有小于基准值的数字组成的子数组;
 基准值;
 一个由所有大于基准值的数组组成的子数组。

这里只是进行了分区,得到的两个子数组是无序的。但如果这两个数组是有序的,对整个数组进行排序将非常容易。
在这里插入图片描述

如果子数组是有序的,就可以像下面这样合并得到一个有序的数组:左边的数组 + 基准值 + 右边的数组。
在这里,就是[10, 15] + [33] + [],结果为有序数组[10, 15, 33]。
如何对子数组进行排序呢?对于包含两个元素的数组(左边的子数组)以及空数组(右边的子数组),快速排序知道如何将它们排序,
因此只要对这两个子数组进行快速排序,再合并结果,就能得到一个有序数组!
quicksort([15, 10]) + [33] + quicksort([])

[10, 15, 33]
不管将哪个元素用作基准值,这都管用。假设你将15用作基准值。
在这里插入图片描述

这个子数组都只有一个元素,而你知道如何对这些数组进行排序。现在你就知道如何对包含
三个元素的数组进行排序了,步骤如下。
(1) 选择基准值。
(2) 将数组分成两个子数组:小于基准值的元素和大于基准值的元素。
(3) 对这两个子数组进行快速排序。

快速排序Java代码:

public class QuickSort {
    public static void main(String[] args) {
        int[] a = {1, 4, 3, 2, 5, 4};
        quicksort(a, 0, a.length - 1);
        System.out.println(Arrays.toString(a));
    }

    private static void quicksort(int[] a, int left, int right) {
        if (left > right) {
            return;
        } else {
            int base = a[left];
            int i = left;
            int j = right;
            while (i < j) {
                while (a[j] > base && i < j) { //从右向左找出第一个小于base的数
                    j--;
                }
                while (a[i] <= base && i < j) { //从左向右找出第一个大于base的数
                    i++;
                }
                if (i < j) { // 交换
                    int temp = a[j];
                    a[j] = a[i];
                    a[i] = temp;
                }
            }
            //交换基准数
            int temp = a[i];
            a[i] = a[left];
            a[left] = temp;
            quicksort(a, left, i - 1);
            quicksort(a, i + 1, right);
            return;
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值