快速排序-三路快排

快速排序可能是应用最广泛的排序算法了,它的实现简单,只需要一个很小的辅助栈,将长度为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左右时候,我们可以改为插入排序,效率会有所改进


猜你喜欢

转载自blog.csdn.net/m0_37752084/article/details/80147989