快速排序思想

快速排序尤其适用于对大数据的排序,它的高速和高效无愧于“快速”两个字。

1、快速排序的基本思想:

快速排序所采用的思想是分治的思想。所谓分治,就是指以一个数为基准,将序列中的其他数往它两边“扔”。以从小到大排序为例,比它小的都“扔”到它的左边,比它大的都“扔”到它的右边,然后左右两边再分别重复这个操作,不停地分,直至分到每一个分区的基准数的左边或者右边都只剩一个数为止。这时排序也就完成了。

2、快速排序的三个步骤:

(1)选择基准:在待排序列中,按照某种方式挑出一个元素,作为 "基准"(pivot)

(2)分割操作:以该基准在序列中的实际位置,把序列分成两个子序列。此时,在基准左边的元素都比该基准小,在基准右边的元素都比基准大

(3)递归地对两个序列进行快速排序,直到序列为空或者只有一个元素。

案例图:

方法其实很简单:分别从初始序列“6 1 2 7 9 3 4 5 10 8”两端开始“探测”。先从找一个小于6的数,再从找一个大于6的数,然后交换他们。这里可以用两个变量i和j,分别指向序列最左边和最右边。我们为这两个变量起个好听的名字“哨兵i”和“哨兵j”。刚开始的时候让哨兵i指向序列的最左边(即i=1),指向数字6。让哨兵j指向序列的最右边(即=10),指向数字。

1574685745(1).jpg

首先哨兵j开始出动。因为此处设置的基准数是最左边的数,所以需要让哨兵j先出动,这一点非常重要(请自己想一想为什么)。哨兵j一步一步地向左挪动(即j–),直到找到一个小于6的数停下来。接下来哨兵i再一步一步向右挪动(即i++),直到找到一个数大于6的数停下来。最后哨兵j停在了数字5面前,哨兵i停在了数字7面前。

image.png

现在交换哨兵i和哨兵j所指向的元素的值。交换之后的序列如下:

6 1 2 5 9 3 4 7 10 8

image.png

到此,第一次交换结束。接下来开始哨兵j继续向左挪动(再友情提醒,每次必须是哨兵j先出发)。他发现了4(比基准数6要小,满足要求)之后停了下来。哨兵i也继续向右挪动的,他发现了9(比基准数6要大,满足要求)之后停了下来。此时再次进行交换,交换之后的序列如下:

6 1 2 5 4 3 9 7 10 8

第二次交换结束,“探测”继续。哨兵j继续向左挪动,他发现了3(比基准数6要小,满足要求)之后又停了下来。哨兵i继续向右移动,糟啦!此时哨兵i和哨兵j相遇了,哨兵i和哨兵j都走到3面前。说明此时“探测”结束。我们将基准数6和3进行交换。交换之后的序列如下:

3 1 2 5 4 6 9 7 10 8

image.png

到此第一轮“探测”真正结束。此时以基准数6为分界点,6左边的数都小于等于6,6右边的数都大于等于6。回顾一下刚才的过程,其实哨兵j的使命就是要找小于基准数的数,而哨兵i的使命就是要找大于基准数的数,直到i和j碰头为止。

案例图:

image.png

快速排序的性能高度依赖于你选择的基准值

代码实现:


package com.ac;

/**

* 小鹅通接口测试

*/

public class Test {

public static void main(String[] a){

int [] b = {1,6,8,7,3,5,16,4,8,36,13,44};

quickSort(b);

for (int i:b) {

System.out.print(i +" ");

}

}

/**

    * 快速排序

    * @param array

    */

    public static void quickSort(int[] array) {

int len;

if(array ==null

                || (len = array.length) ==0

                || len ==1) {

return ;

}

sort(array,0, len -1);

}

/**

    * 快排核心算法,递归实现

    * @param array

    * @param left

    * @param right

    */

    public static void sort(int[] array,int left,int right) {

if(left > right) {

return;

}

// base中存放基准数

        int base = array[left];

int i = left, j = right;

while(i != j) {

// 顺序很重要,先从右边开始往左找,直到找到比base值小的数

            while(array[j] >= base && i < j) {

j--;

}

// 再从左往右边找,直到找到比base值大的数

            while(array[i] <= base && i < j) {

i++;

}

// 上面的循环结束表示找到了位置或者(i>=j)了,交换两个数在数组中的位置

            if(i < j) {

int tmp = array[i];

array[i] = array[j];

array[j] = tmp;

}

}

// 将基准数放到中间的位置(基准数归位)

        array[left] = array[i];

array[i] = base;

// 递归,继续向基准的左右两边执行和上面同样的操作

        // i的索引处为上面已确定好的基准值的位置,无需再处理

        sort(array, left, i -1);

sort(array, i +1, right);

}

}

部分内容参考文章:https://blog.csdn.net/shujuelin/article/details/82423852

©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • 简单来说,时间复杂度指的是语句执行次数,空间复杂度指的是算法所占的存储空间 时间复杂度计算时间复杂度的方法: 用常...
    Teci阅读 4,770评论 0 1
  • 高快省的排序算法 有没有既不浪费空间又可以快一点的排序算法呢?那就是“快速排序”啦!光听这个名字是不是就觉得很高端...
    博弈史密斯阅读 3,017评论 0 0
  • 上一节的冒泡排序可以说是我们学习的第一个真正的排序算法,并且解决了桶排序浪费空间的问题,但在算法的执行效率上却牺牲...
    青葱烈马阅读 3,875评论 0 1
  • 排序也就是使集合中的元素有序化,他是常见的计算机操作之一,主要介绍几种经典的排序方法:冒泡排序,插入排序,快速排序...
    螺丝钉25阅读 2,472评论 0 0
  • 假设我们现在对“6 1 2 7 9 3 4 5 10 8”这个10个数进行排序。首先在这个序列中随便...
    小陈阿飞阅读 4,369评论 0 1