简单改进的快排算法——含代码


/**
 * 
 * @Description:快排算法
 * 快排算法基于划分操作,所谓划分操作即把大于一个临界值的全部放在一边,把小于临界值的全部放在另一边,对于临界值的选择会影响快排的效率
 * 为了方便,一般快排中会将需要排序的数组的最右端值作为临界值,在划分操作结束后,把最右端的这个值放到划分的临界点上,这样就形成了一个相对有序的序列
 * 但是直接使用最右端的值作为临界值,在面对特殊情况,如逆序排列的数组时,会导致效率降低,因此使用改进的方法,即在需要排序的数组中间、最左端、最右端的三个数中进行选择,挑选三个数中中等大小的数值作为临界值
 * 在实际实现中,把三个数中最小的数放在最左端,最大的数放在最右端,中等的数,也就是临界值,放在最右端的左边一位
 * 在划分操作时,直接在最右端的右边一位到最左端的左边两位进行,如图:[最小值,…需要划分…,中间值(临界值),最大值]
 * 这么做的目的是可以减少若干操作,临界值放在两类数的边界上,即意味着,临界值到达了他在最终排序序列中的位置,因为临界值的左边都小于他,右边都大于他,这样就可以在接下来的递归调用中不再考虑这个临界值
 * 同时最大值,最小值放在以前以后,可以在划分操作的时候不用考虑这两个数,因为他们已经在应该在的那边了,但是在后续递归的快排中,这里的最大值和最小值还是要参与的
 * 划分操作结束后,把中间值换到临界值的位置上,然后对两边分别进行快排操作,如图:[最小值,…需要快排…,中间值,…需要快排…,最大值]
 * 因为使用了三选一选临界值的方法,所以当需要递归快排的数组大小小于3的时候,只能直接排序,就是几个简单的判断语句,这是可以再优化的
 * @author:Gii
 * @time:2017年4月3日 下午5:21:18
 */
public class QuickSort {

    private static int[] arr = new int[] { 1, 2, 5, 3, 5, 7, 2, 4, 7, 1, 3, 42, 7, 233, 234, 67, 4, 3 };

    public static void main(String[] args) {
        // partition(0,7,4);
        recSort(0, arr.length - 1);
        for (int i : arr) {
            System.out.print(i + " ");
        }
    }

    public static void recSort(int begin, int end) {
        if (end - begin < 3) {
            smallSort(begin, end);
            return;
        }
        int base = getBaseAndSort(begin, end);
        int mid = partition(begin, end, base);
        recSort(mid + 1, end);
        recSort(begin, mid - 1);
    }

    private static void smallSort(int begin, int end) {
        if (begin == end) {
            return;
        }
        int mid = (begin + end) / 2;
        if (arr[begin] > arr[end]) {
            swap(begin, end);
        }
        if (arr[begin] > arr[mid]) {
            swap(begin, mid);
        }
        if (arr[mid] > arr[end]) {
            swap(mid, end);
        }
    }

    private static int partition(int begin, int end, int base) {
        int leftPoint = begin;
        int rightPoint = end - 1;
        // 1 8 1 4 5 2 6 4 8
        // 1 4 1 4 2 8 6 8 5
        while (true) {
            while (arr[++leftPoint] < base);
            while (arr[--rightPoint] > base);
            if (leftPoint >= rightPoint) {
                break;
            } else {
                swap(leftPoint, rightPoint);
            }
        }
        swap(end - 1, leftPoint);
        return leftPoint;
    }

    private static int getBaseAndSort(int begin, int end) {
        int midPos = (begin + end) / 2;
        if (arr[begin] > arr[midPos]) {
            swap(begin, midPos);
        }
        if (arr[begin] > arr[end]) {
            swap(begin, end);
        }
        if (arr[midPos] > arr[end]) {
            swap(midPos, end);
        }
        swap(midPos, end - 1);
        return arr[end - 1];
    }

    private static void swap(int a, int b) {
        int tmp;
        tmp = arr[a];
        arr[a] = arr[b];
        arr[b] = tmp;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值