算法 第二章--快速排序

本文深入探讨了快速排序的基本思想与实现细节,包括标准的快速排序算法和优化后的三向切分快速排序。通过代码示例展示了如何通过递归将数组划分为更小的部分,并确保各部分有序。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

算法 第二章–快速排序

基本思想:
当两个子数组都有序时,(两个数组分界点则为 数组1< key, key, 数组2>key)整个数组也自然有序了。

public class Quick {

    //打印数组a的元素
        public static void print(Comparable[]a){
            for(Comparable j:a ){
                System.out.print(j+" ");
            }
            System.out.println("-----------------------");
        }

    //交换a[i] 和a[j]
    public static void exch(Comparable[] a,int i, int j){
        Comparable t =a[i]; a[i] = a[j]; a[j] = t;
    }

    public static boolean less(Comparable v, Comparable m ){
        return v.compareTo(m)<0;
    }

    private static int partition(Comparable[] a,int lo, int hi){
        Comparable x = a[lo];//标尺
        //指针  这样写为了  在程序执行之前  lo++; hi-- 到比较元素的开始地方
        int i = lo;//左
        int j = hi+1;//右
        while(true){
            if(lo >= hi) break;//首先去数组是否合法

            while(less(a[++i] ,x)) if(i==hi)break; //从数组的最左端起,只要 元素小于标尺时,则向左移动;直到元素大于或等于  标尺时,停止
            while(less(x,a[--j])) if(j==lo)break;  //同理得。再交换。

            if(i >= j) break;//检查是否j,i为同一个函数
            exch( a, i,j);  
        }
        exch( a, lo,j);//使a的 标尺  放在 的位置;
        return j;//跳出程序
    }

    public static void sort(Comparable[]a){
        StdRandom.shuffle(a);//消除对输入的依赖
        //sort(a, 0,a.length-1);
        sort2(a, 0,a.length-1);

    }
    private static void sort(Comparable[]a, int lo, int hi){
        if(hi<= lo)return;
        int k = partition(a,lo,hi);
        sort(a,lo,k-1);
        sort(a,k+1,hi);
    }


    //三向切分快速排序
    private static void sort2(Comparable[] a,int lo,int hi){
        if(hi<lo)return;

        int lt = lo;
        int i = lo+1;
        int gt = hi;

        Comparable v = a[lo];

        while(i<=gt){
            int cmp = a[i].compareTo(v);
            //比标尺小
            if(cmp < 0) exch(a,i++,lt++);
            else if(cmp > 0) exch(a,i,gt--);
            else i++;
        }
        sort(a,lo,lt-1);
        sort(a,lt+1,hi);
    }

    public static void main(String[] args) {
        Comparable[]a = {1,3,44,32,34,45,67,43,2,3,12,32,13,145};
        print(a);
        sort(a);
        print(a);
    }

}
  1. 基本算法
    以为sort()是递归,把数组分成左右两个部分,则它只需要数组两边有序即可。(两个数组分界点则为 数组1< key, key, 数组2>key)
private static int partition(Comparable[] a,int lo, int hi){
        Comparable x = a[lo];//标尺
        //指针  这样写为了  在程序执行之前  lo++; hi-- 到比较元素的开始地方
        int i = lo;//左
        int j = hi+1;//右
        while(true){
            if(lo >= hi) break;//首先去数组是否合法

            while(less(a[++i] ,x)) if(i==hi)break; //从数组的最左端起,只要 元素小于标尺时,则向左移动;直到元素大于或等于  标尺时,停止
            while(less(x,a[--j])) if(j==lo)break;  //同理得。

            if(i >= j) break;//检查是否j,i为同一个元素
            exch( a, i,j);  
        }
        exch( a, lo,j);//使a的 标尺  放在 的位置;
        return j;//跳出程序
    }

exch( a, lo,j)时,此数组以形成a[lo,…j-1] <= a[j] <=a[j+1,…hi]

  1. 三向切分
    见算法p299示意图。
    它其实就是把数组分为四个部分。
    a【[< key],[=key],[未知的元素],[>key]】
    然而一开始,全都是未知的即a【未知】,一步步进行排序,未知越来越少,从而达到了有序。
    a【[lo 小于key lt],[lt+1 等于key gt],[gt+1 大于key hi]】

    //三向切分快速排序
    private static void sort2(Comparable[] a,int lo,int hi){
        if(hi<lo)return;//(1)跳出递归的条件和防止非法的数组进行排序
    
        int lt = lo;//等于key的引索的其实点
        int i = lo+1;//未知的数组部分的开始引索
        int gt = hi;//gt为等于key的结束引索,即gt+1位大于key的引索
    
        Comparable v = a[lo];//key
    //i---gt之间为未知元素,i<=gt 为未知元素还没结束
        while(i<=gt){
            int cmp = a[i].compareTo(v);  //相当于a[i]-v
        //a[i] 小的时候, 即需要交换。因为它的原则,最左边都必须要比key小,交换后 ,第一个位置就确定了。同时++
            if(cmp < 0) exch(a,i++,lt++);
        //a[i] 大的时候, 即需要交换。因为它的原则,最右边都必须要比key大,交换后 ,最后的位置就确定了。注意:此时无法判断交换的a[gt]的大小,所以i不用++,它仍是一个未知数。
            else if(cmp > 0) exch(a,i,gt--);
            else i++; //当等于的时候,则其它的索引无需变动,只要i++即可
        }
        sort(a,lo,lt-1);
        sort(a,lt+1,hi);
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值