欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

快速排序-三路快排

程序员文章站 2022-03-12 17:09:34
...

快速排序可能是应用最广泛的排序算法了,它的实现简单,只需要一个很小的辅助栈,将长度为N的数组排序所需时间和NlogN成正比,在本篇文章讲述一下改进的快速排序-三路快排

三路快排

所谓三路快排,一言以蔽之,就是同时排序小于选定值,等于选定值和大于选定值三种情况

在这里我们随机选取一个值v作为分界点,分别排序小于v,等于v和大于v的,这里之所以随机选取是考虑到如果我们选取数组第一个值,那么在一个完全有序的数组里,我们的快速排序就会退化为log(n^2)

先来看代码:

package vip.lanco;
import java.util.*;

public class QuickSort3 {

    // 我们的算法类不允许产生任何实例
    private QuickSort3(){}

    // 递归使用快速排序,对arr[left...right]的范围进行排序
    private static void sort(Comparable[] arr, int left, int right){

        // 对于小规模数组, 使用插入排序会更加快速
        if( right <left ){
            //自己实现插入排序
        }

        /* 随机在arr[l...r]的范围中, 选择一个数值作为标定点pivot*/
        swap( arr, left, (int)(Math.random()*(right-left+1)) + left );

         Comparable v = arr[left];

         //设置边界值
        int lt = left;     // arr[left+1...lt] < v
        int gt = right + 1; // arr[gt...right] > v
        int i = left+1;    // arr[lt+1...i) == v
        while( i < gt ){
            if( arr[i].compareTo(v) < 0 ){
                swap( arr, i, lt+1);
                i ++;
                lt ++;
            }
            else if( arr[i].compareTo(v) > 0 ){
                swap( arr, i, gt-1);
                gt --;
            }
            else{ // arr[i] == v
                i ++;
            }
        }

        swap( arr, left, lt );

        sort(arr, left, lt-1);
        sort(arr, gt, right);
    }

    public static void sort(Comparable[] arr){

        int n = arr.length;
        sort(arr, 0, n-1);
    }

    //两值交换
    private static void swap(Object[] arr, int i, int j) {
        Object t = arr[i];
        arr[i] = arr[j];
        arr[j] = t;
    }
    
    //输出显示
    private static void show(Comparable[] a) {
        for (int i = 0; i < a.length; i++) {
           System.out.print(a[i]+"--");
        }
    }

    // 测试 QuickSort3
    public static void main(String[] args) {

    	Comparable[] arr = new Comparable[] {23,45,1,21,67,78,89,55,12,34,22,11,5,6,9};
    	sort(arr);
    	 show(arr);
        return;
    }
}


快速排序-三路快排

如上,我们以数组[23,45,1,21,67,78,89,55,12,34,22,11,5,6,9]为例

一开始设置的边界值lt=0,gt=15,i=1,假设随机选取pivot标志后为5;

则arr[1]=45 > v=5  所以交换45和9的位置,同时gt-1,此时arr[1]=9;

接着继续判断arr[1]=9 > v=5 ,所以这时候交换6和9的位置 ,此时arr[1]=6

如此下去直到最后只剩下:

v(left) <v(lt) ==v(gt,i) >v(right)

再去交换left和lt的值。

小改进,在right-left<=15左右时候,我们可以改为插入排序,效率会有所改进