快速排序

快速排序

小弟初来咋到,面对算法一脸懵逼,希望各位大神能够给予指点,在此谢过。

普通快速排序

思路:升序排列时,数组被其中的一个key值切成两部分,保证左边的数据都比key小,右边的数据比key值大,当左右两边都有序时,整个数组也会有序
这里写图片描述

import java.util.Arrays;

/**
 * Created by Fearless on 2017/3/29.
 */
public class Quick {
    private static Comparable[] a={5,87,96,44,58,32,25,1,77,69,36,44};//测试数组
    /***
     * 测试算法
     * @param args
     */
    public static void main(String ... args){
        quickSort(a);
        System.out.println(Arrays.toString(a));
    }
    public static void quickSort(Comparable[] a) {
        sort(a, 0, a.length - 1);
    }

    /***
     * 排序
     * @param a 排序数组
     * @param i 起始索引
     * @param i1 结束索引
     */
    public static void sort(Comparable[] a, int i, int i1) {
        //如果起始索引大于等于结束索引,返回
        if (i >= i1) return;
        //对数组进行切割
        int j = partition(a, i, i1);
        //对切割后的数组分别再做切割
        sort(a,i,j);
        sort(a,j+1,i1);
    }

    /***
     * 对数组进行切割,返回切割位置的索引
     * @param a 数组
     * @param i 起始位置的索引
     * @param i1 结束位置的索引
     * @return 切割位置的索引
     */
    private static int partition(Comparable[] a, int i, int i1) {
        //初始化从左往右的索引
        int index1 = i;
        //初始化从右往左的索引
        int index2 = i1+1;
        //选取第一个值为key值
        Comparable key = a[i];
        //通过循环找在key左边比key大,在key右边比key小的值,并交换二者的位置
        //使用++index1 和--index2 可以保证最后得到的索引值就是最终索引
        //第一个位置是key值,所以index1从++index1开始
        while (true) {
           //从左往右找大于等于key的值
            while (less(a[++index1],key)) {
                if (index1 == i1) break;
            }
            //从右往左找小于等于key的值
            while (less(key,a[--index2])) {
                if (index2 == i) break;
            }
            //如果左索引位置大于右索引位置,跳出循环
            // 要保证在找到大小值的情况下大值在小值的左边
            if(index1>=index2) break;
            //交换大小值位置
            exch(a,index1,index2);
        }
        //把小值和切割数的位置做交换
        //如果没有找到比key小的值,index2会停在最前面
        /*如果有找到比key小的值,index2会停在小值处,此时index1找到合适数据时,可交换数据。
        如果没有找到合适的数据,说明index2之前的数据没有比key大的值了
         可以放心的把key的值放到index2处*/
        exch(a,index2,i);
        return index2;
    }

    //a是否小于b
    private static boolean less(Comparable a, Comparable b) {
        return a.compareTo(b) < 0;
    }

    /***
     * 交换索引 i j 处的数据
     * @param a
     * @param i
     * @param j
     */
    private static void exch(Comparable[] a,int i,int j){
        Comparable temp=a[i];
        a[i]=a[j];
        a[j]=temp;
    }
}
三向切分的快速排序

在普通快速排序时,当遇到相同数据的情况下,排序算法依旧会对其进行数据交换操作,这样大大降低了排序的效率,所以在有很多重复数据的情况下,我们可以使用改进后的三向切分的快速排序,

思路:将重复数据很多的数组取key值,并将该数组划分成小于key的区域,等于key的区域和大于key的区域,并通过递归对小于和大于key的区域分别做相同的排序操作。
这里写图片描述

import java.util.Arrays;

/**
 * Created by Fearless on 2017/3/29.
 */
public class Quick3way {
    private static Comparable[] a={19,18,20,20,21,21,19,20,19,21,18,19,18,18,20};//测试数组
    /***
     * 测试算法
     * @param args
     */
    public static void main(String ... args){
        System.out.println(Arrays.toString(a));
        quickSort(a);
        System.out.println(Arrays.toString(a));
    }


    public static void quickSort(Comparable[] a) {
        sort(a, 0, a.length - 1);
    }
    /***
     * 三向切分的快速排序
     * @param a 排序数组
     * @param i 起始索引
     * @param i1 结束索引
     */
    public static void sort(Comparable[] a, int i, int i1) {
        if(i>=i1) return;
        int li=i;
        int ri=i1;
        Comparable key=a[i++];
        while(i<=ri){
            //key 和a[i]做比较
            int j=key.compareTo(a[i]);
            //如果a[i]>key,交换索引i和ri处的数据,ri索引减1,把大的放到后面
            // 因为无法确定调换后的i处的数据的大小,所以i的索引保持不变,在轮进行比较
            if(j<0) exch(a,i,ri--);
            //如果a[i]==key,不做任何操作,i的索引后移
            else if(j==0) i++;
            //如果a[i]<key,交换索引i和ri处的数据,把小的放前面,两个索引都向后移
            else exch(a,i++,li++);
            System.out.println(Arrays.toString(a));
        }
        //对小于key的区域做排序
        sort(a,i,li-1);
        //对大于key的区域做排序
        sort(a,ri+1,i1);
    }

    /***
     * 交换索引 i j 处的数据
     * @param a
     * @param i
     * @param j
     */
    private static void exch(Comparable[] a,int i,int j){
        Comparable temp=a[i];
        a[i]=a[j];
        a[j]=temp;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值