快速排序算法

定义
快速排序(Quicksort)是对冒泡排序的一种改进。
快速排序由C. A. R. Hoare在1962年提出。它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。
简单点~

算法描述
快速排序使用分治法来把一个序列(list)分为两个子序列(sub-lists)。具体算法描述如下:
我们可以把快速排序看着三个步骤:
1.选择轴点:在待排序列中,按照某种方式挑出一个元素,作为轴点。
2.分区操作:以该基准值在序列中的实际位置,把序列分成两个子序列,一边是比它大的值,另外一边是比它小的值(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;
3.递归(recursive):对两个子序列进行递归的快排,直到序列为空或者只有一个元素。

轴点:左/右侧的元素,均不比它更大/小
在这里插入图片描述
以轴点为界,原序列的划分自然实现:[low, high)=[low, mid)+[mid] + (mid, high)

在原始序列中轴点未必存在,但是通过适当交换,可使任一元素转换为轴点。
在有序序列中所有元素皆为轴点,反之亦然。
快速排序:就是将所有元素逐个转换为轴点的过程
主算法: 快速找到轴点,借助二分式的递归,就可以快速写出快速排序算法。

  public static void quickSort(int[] A, int low, int high) {
        if (high - low < 2) {//单元素区间自然有序,比如[3,4)
            return;
        }
        //先构造轴点mid
        int mid = partition(A, low, high - 1);//注意patition函数使用两端封闭区间

        quickSort(A, low, mid);//前缀排序
        quickSort(A, mid + 1, high);//后缀排序
    }

通过构造轴点的方法有两种,即partition()方法的实现有两种方式。

方法1:

  1. 首先选择轴点候选作为培养对象,取做首元素。整个序列分为候选轴点、L(前缀,L<= pivot)、U(大小未知)、G(后缀,pivot<=G)四部分。
    初始U为原始序列,L、G为空。
    low和high交替向内侧移动,使他们彼此靠近。low每向后移动一次,U中的元素加入到L中,L向右扩展一单元。high每向前移动一次,U中的元素加入到G中,G向左扩展一单元。low与high指向同一个位置时,将选定的轴点候选者放入这个位置。候选者就成了名副其实的轴点。
    在这里插入图片描述
    下面图理解构造轴点的过程。
    在这里插入图片描述
    在这里插入图片描述
 public static int partition (int[] A, int low, int high) {
        int pivot = A[low] ;
        while (low < high) {
        //从U的尾元素开始迭代
            while (low < high && pivot <= A[high]) {
                high--;
            }
            if (low < high) {
                A[low] = A[high];
            }

            while (low < high && A[low] <= pivot) {
                low++;
            }
            if (low < high) {
                A[high] = A[low];
            }
        }
        //候选轴点归位(从而名副其实)
        A[low] = pivot;
        return low;
    }

方法2:
轴点归位变种:
首先选择轴点候选作为培养对象,取做首元素。整个序列分为候选轴点、L(前缀,L<= pivot)、G(后缀,pivot<=G)、U(大小未知)四部分。L边界[low,mid],G[mid+1,k-1],U[k,hi]决定。
初始U为原始序列,L、G为空。
low和high交替向内侧移动,使他们彼此靠近。low每向后移动一次,U中的元素加入到L中,L向右扩展一单元。high每向前移动一次,U中的元素加入到G中,G向左扩展一单元。low与high指向同一个位置时,将选定的轴点候选者放入这个位置。候选者就成了名副其实的轴点。
在这里插入图片描述
//从U的首元素开始迭代,根据x元素的大小,将其归位到L或者G子序列中。
在这里插入图片描述
最后一步 候选轴点归位(从而名副其实):根据L小G大的特性,候选轴点安插在L和G的交接处,G不变,L的末元素被替换为候选轴点,也就是L的末元素和候选轴点交换

public static int partition(int[] A, int low, int high) {
        //此方法轴点元素可随机的选取
        int pivot = A[low];//选取第一个元素作为轴点
        int mid = low;
        //从U的首元素开始迭代
        for (int k = low + 1; k <= high; k++) {//k指向U,自左向右考察每个[k]
            if (A[k] < pivot) {//若[k]小于轴点,将其归入L,做法:则将其与[mid+1](也就是G的第一个元素)交换,L向右扩展到mid+1
                ++mid;
                int temp = A[k];
                A[k] = A[mid];
                A[mid] = temp;
            }//隐藏的else,在这种情况下简明的令k递增一个单位。因为if也需要k递增,所以统一放在for循环的更新环节
        }
        //候选轴点归位(从而名副其实),根据L小G大的特性,候选轴点安插在L和G的交接处,G不变,L的末元素被替换为候选轴点,也就是L的末元素和候选轴点交换
        A[low] = A[mid];
        A[mid] = pivot;
        return mid;//返回轴点的位置
    }

测试方法:返回 0,1,1,2,3,3,4,7,8,9,12,22,65

 public static void main(String args[]) {
        int[] A = {7, 1, 2, 0, 9, 3, 12, 1, 8, 3, 4, 65, 22};
        quickSort(A, 0, A.length);
        for (int i : A) {
            System.out.print(i + ",");
        }
    }

算法分析
最佳情况:T(n) = O(nlogn) 最差情况:T(n) = O(n2) 平均情况:T(n) = O(nlogn)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值