经典排序算法之:快速排序

  快速排序可能是应用最广泛的排序算法。快速排序流行的原因是它实现简单、适用于各种不同的输入数据且在一般应用中比其他排序算法都要快很多。此次,我们来学习一下快速排序算法。


一、快速排序算法含义

  快速排序是一种分治的排序算法。它会在数组中选择一个基准元素,讲数组分为两部分,使得第一部分中的所有元素都小于或等于基准元素,而第二部分中的所有元素都大于基准元素。对第一部分和第二部分递归的应用快速排序算法。

二、快速排序算法过程

例如:
  对数组 [5 2 9 3 8 4 0 1 6 7 ]进行快速排序

  基准元素的选择会影响算法的性能。在理想情况下,应该选择能平均划分两部分的基准元素。为了简单起见,假定将数组的第一个元素选为基准元素。

如下图:
在这里插入图片描述

根据基准元素,将数组分为左边和右边的数组,并选择第一个为基准元素。
在这里插入图片描述

对左边< 5的数组进行快速排序

在这里插入图片描述

基准元素4又将数组划分为一个数组(0 2 1 3),然后对其进行快速排序
在这里插入图片描述

基准元素2又将数组仅分为(2 1 3),然后对其快速排序
在这里插入图片描述
然后,左边 <5 的数组已经快速排序完成。对右边 >5的数组递归的运用快速排序。

如上图流程可更能了解快速排序的原理过程。但是要实现这个过程就要有实际的切分方法。

三、快速排序算法的过程方法实现

  要实现快速排序的过程,关键在于切分。

  切分过程使得数组满足下面三个条件。

  • 对于某个pivotIndex,a[pivotIndex]已经排定;
  • a[first]到a[pivotIndex-1]中的所有元素都不大于a[pivotIndex];
  • a[pivotIndex+1]到a[last]所有元素都不小于a[pivotIndex];

要完成这个切分,就要实现切分的方法。一般是去a[first]为切分元素(pivot)。然后我们从数组左端开始向右扫描直到找到一个大于等于它的元素,在从右边扫描直到找到一个小于等于它的元素。然后交它们的位置。如此继续。我们就可以保证左边的不小于切分元素,右边的不大于切分元素。
当两个指针相遇时,我们只需要将切分元素a[first]和左子数组最右侧元素a[high]交换返回[high]即可。

切分过程所示:
在这里插入图片描述

对于随机数组一次递归的动态过程如下请添加图片描述

四、快速排序算法的实现

public class QuickSort {

    public static void quickSort(int[] list, int first, int last) {
        if (last > first){
            int pivotIndex = partiton(list,first,last);
            quickSort(list,first,pivotIndex-1);
            quickSort(list,pivotIndex+1,last);
        }
    }

    public static int partiton(int[] list, int first, int last) {
        int pivot = list[first];
        int low = first +1;
        int high = last;

        while (high > low){
            while (low <= high &&  list[low] <= pivot) low++;

            while (low <= high && list[high] > pivot) high--;

            if (high > low && list[high] > list[low]){
                int temp = list[high];
                list[high] = list[low];
                list[low] = temp;
            }
        }
        while (high > first && list[high] >= pivot) high--;

        if(pivot > list[high]){
            list[first] = list[high];
            list[high] = pivot;
            return high;
        }
        else {
            return first;
        }
    }

    ///另一种方式写快速排序
    public static int[] qsortA(int arr[],int first,int last) {
        int pivot = arr[first];
        int low = first +1;
        int high = last;
        while (high > low) {
            while ((low <= high)&&(arr[low] <= pivot)) {
                low++;
            }
            while ((low <= high)&&(arr[high]>= pivot)) {
                high--;
            }
            if (high > low){
                int temp = arr[low];
                arr[low] = arr[high];
                arr[high] = temp;
            }
        }

        while (high > first && arr[high] >= pivot){
            high--;
        }

        if (pivot >arr[high]){ //此时基准元素大于下标元素,将其对换,满足左边的都小于基准元素,右边的都大于基准元素(数组的拆分)
            arr[first] = arr[high];
            arr[high] = pivot;
        }

        if (low -1 > first){
            arr = qsortA(arr,first,low-1);
        }
        if (high +1 < last){
            arr =qsortA(arr,high+1,last);
        }
        return (arr);
    }

    public static void main(String[] args) {
        
        int[] a ={5,2,6,9,6,1,2,0,3,6,8,11,68,75};
        qsortA(a,0,a.length-1);
        for (int i = 0; i < a.length; i++) {
            System.out.print(a[i]+ "  ");
        }
    }
 }

运行结果:
0 1 2 2 3 5 6 6 6 8 9 11 68 75

  • 16
    点赞
  • 79
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

风儿吹吹吹

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值