快速排序原理及java实现

快速排序

1.

思想:
以数据中的一个数为基准P,把数据分成大于这个基准的一份和小于这个基准的一份(分区)。在再分区的数据中重复这个过程,直到分区只剩一个数据就完成了排序。
具体排序过程:
1.1 默认数据中的第一个为基准数据P, 左指针PL指向第一个数据,右指针PR指向最后一个元素
1.2 PL和PR分别和P进行比较,如果RL <= P即左边的数据小于P,将LR右移一位,如果大于P则看RP,如果RP < LP, 则将LR 和RP位置的数据互换。
1.3 PR 和 P进行比较,如果 PR > P 则将PR左移一位,否则不变。如果RP < P < LP , 则将LR 和RP位置的数据互换,类似上一步。
1.4 LP 和 RP 相遇,则将P插入LR和RP中,第一次分区完成。
1.5 重复上面的过程,直到分区只有一个数据。

e.g:

outOfSoted: 4, 10, 9 ,3, 5, 8 , 2, 9, 11, 6

P: 4

PL: 4

PR: 6

outOfSoted: pl:4, 10, 9 ,3, 5, 8 , 2, 9, 11, pr:6


PL <= P, PL右移, PL = 10

PR > P, PR左移, PR = 11

result: 4 l:10 9 3 5 8 2 9 r:11 6


PL > P, PL位置不变, PL = 10

PR > P, PR左移, PR =9

result: 4 l:10 9 3 5 8 2 r:9 11 6


PL > P, PL位置不变, PL = 10

PR > P, PR左移, PR = 2

result: 4 l:10 9 3 5 8 r:2 9 11 6


PL > P, PL位置不变, PL = 10

PR <= P, PR位置不变, PR = 2

PL > P && PR < PL, 互换PL和PR的值,PL = 2, PR = 10

result: 4 l:2 9 3 5 8 r:10 9 11 6


PL <= P, PL右移, PL = 9

PR > P, PR左移, PR = 8

result:4 2 l:9 3 5 r:8 10 9 11 6


PL > P, PL不变, PL = 9

PR > P, PR左移, PR = 5

result:4 2 l:9 3 r:5 8 10 9 11 6


PL > P, PL不变, PL = 9

PR > P, PR左移, PR = 3

result:4 2 l:9 r:3 5 8 10 9 11 6


PL > P, PL不变, PL = 9

PR <= P, PR不变, PR = 3

PL > P && PR < PL, 互换PL和PR的值,PL = 3, PR = 9

result:4 2 l:3 r:9 5 8 10 9 11 6


PL < P, PL 右移, PL = 9

PL = PR,比较PR和P的大小,PR > P, 位置不变,将P插入PR前(PR前的数据都<=p,故将PR-1和P互换位置即可)。


至此,第一次分区完成,3 2 4 9 5 8 10 9 11 6 ,P前面的数据都比P小,后面分区的数据都比P大,对分区重复上面的过程,直到所有分区的数据只剩一个就完成了排序。

2. 优点

对冒泡排序中天然有序的部分数据进行了优化,会直接跳过,所以更快,称为快排

3. java代码实现

import cn.jiayeli.sorts;

import java.util.Arrays;
import java.util.Random;

public class FastSort {

    int realPr = 0;

    @Test
    public void fastOrder() {

        Integer[] outOfOrder = new Integer[10];
        System.out.println("OutOfOrder");

        for (int i = 0; i < outOfOrder.length; i++) {
            Random random = new Random();
            outOfOrder[i] = random.nextInt(20);
            System.out.print(outOfOrder[i] + "\t,");
        }

/*
测试数据
        outOfOrder[0] = 7;
        outOfOrder[1] = 12;
        outOfOrder[2] = 18;
        outOfOrder[3] = 19;
        outOfOrder[4] = 1;
        outOfOrder[5] = 15;
        outOfOrder[6] = 5;
        outOfOrder[7] = 6;
        outOfOrder[8] = 18;
        outOfOrder[9] = 15;
        */

        System.out.println(Arrays.asList(outOfOrder) + "\n");
        // 第一次初始化时以第一个为基准,其等于它自己,直接右移一位
        partitionSort(outOfOrder, 1, outOfOrder.length-1);

    }

    public void partitionSort(Integer[] outOfOrder, int pl, int pr) {
        int p = pl;
        int temp = 0;
        //第二个分区偏移量
        realPr = pl == 0 && realPr != 0 ? 0 : realPr;

         
        if (outOfOrder.length > 1) {
         //分区只有一个元素时结束该分区的排序
            while (pr - pl > 0 ) {
                if (outOfOrder[pl] > outOfOrder[p] && outOfOrder[pr] < outOfOrder[pl]) {
                    temp = outOfOrder[pl];
                    outOfOrder[pl] = outOfOrder[pr];
                    outOfOrder[pr] =temp;
                }
                pl = outOfOrder[pl] <= outOfOrder[p] ? ++pl : pl ;
                pr = outOfOrder[pr] > outOfOrder[p] ? --pr : pr;
                //右边的数小于基准且左边的数大于基准,交换两个指针位置的数据
                if (pl >= pr) {
                    if (outOfOrder[pr] > outOfOrder[p]) {
                        temp = outOfOrder[pr-1];
                        outOfOrder[pr-1] = outOfOrder[p];
                        outOfOrder[p] = temp;
                    } else {
                        temp = outOfOrder[pr];
                        outOfOrder[pr] = outOfOrder[p];
                        outOfOrder[p] = temp;
                    }
                   // 保证第二个分区计算时偏移量不被覆盖
                    realPr = realPr == 0 ? pr : realPr;
                    System.out.println("p:\t" + p + "\tpr:\t" + pr);
                    System.out.println("p:\t" + outOfOrder[p] + "\tpr:\t" + outOfOrder[pr]);
                    System.out.println(Arrays.asList(outOfOrder));
                    //对第二个分区进行计算
                    partitionSort(outOfOrder, pr+1, outOfOrder.length-1);
                    //对第一个分区进行计算
                    partitionSort(outOfOrder, 0, realPr-1);
                } 
            }
        }
        
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值