快速排序 Java 针对重复元素

与归并排序一样,快速排序也是采用分治策略。但是归并排序的计算量主要集中在有序子序列的合并上,而子序列的划分几乎不花费时间。快速排序恰恰相反,可以在o(1)的时间内完成子序列的合并,对于将原问题划分上需要花费O(n)的时间。对于子序列的划分上,可能的划分是极不平等的,因此该算法不能保证最坏情况下的O(nlogn)的时间复杂度。一般来说,快排是首选的算法。

因此:版本一

package Basic.QuickSort;
import java.util.Random;
/**
 * 该方法对于出现大量的重复元素的时候,轴点位置总是接近与lo,子序列的划分极不均匀,二分递归退化为线性递归,递归深度接近于O(n),运行时间接近于O(n2)
 * 在移动lo和hi时,同时比较相邻元素的:lo与hi会交替移动,二者移动的距离大致相等。见于第二版本,而对于重复元素不多的时候,法二反而会增加计算量。
 */
public class QuickSort_v1 {

    public static void main(String[] args) {
        int[] array = {9, 10, 5, 84, 2, 45, 1, 4, 56, 1};
        quickSort(array, 0, array.length - 1);
        for (int i = 0; i < array.length; i++) {
            System.out.println(array[i]);
        }
    }

    public static void quickSort(int[] array, int lo, int hi) {
        if (lo >= hi) return;
        int mid = partition(array, lo, hi);
        quickSort(array, lo, mid - 1);
        quickSort(array, mid + 1, hi);
    }

    private static int partition(int[] array, int lo, int hi) {
        swap(array, lo, hi);
        int key = array[lo];
        while (lo < hi) {
            while (lo < hi && array[hi] >= key) hi--;
            array[lo] = array[hi];
            while (lo < hi && array[lo] <= key) lo++;
            array[hi] = array[lo];
        }
        array[hi] = key;
        return hi;
    }

    private static void swap(int[] array, int lo, int hi) {
        int temp = 0;
        Random r = new Random();
        int k = r.nextInt(10) % (hi - lo + 1) + lo;
        temp = array[lo];
        array[lo] = array[k];
        array[k] = temp;

    }
}

版本二:
该方法对于出现大量的重复元素的时候,轴点位置总是接近与lo,子序列的划分极不均匀,二分递归退化为线性递归,递归深度接近于O(n),运行时间接近于O(n2)在移动lo和hi时,同时比较相邻元素的:lo与hi会交替移动,二者移动的距离大致相等。见于第二版本,而对于重复元素不多的时候,法二反而会增加计算量。

package Basic.QuickSort;


import java.util.Random;

import static Basic.QuickSort.QuickSort_v1.quickSort;

/**
 * 
 */
public class QuickSort_v2 {
    public static void main(String[] args) {
        int[] array = {9, 10, 5, 84,56 ,96,2, 45, 1, 4, 56,1,10000};
        quickSort2(array, 0, array.length - 1);
        for (int i = 0; i < array.length; i++) {
            System.out.println(array[i]);
        }
    }

    public static void quickSort2(int[] array, int lo, int hi) {
        if (lo >= hi) return;
        int mid = partition(array, lo, hi);
        quickSort(array, lo, mid - 1);
        quickSort(array, mid + 1, hi);
    }

    private static int partition(int[] array, int lo, int hi) {
        swap(array, lo, hi);
        int key = array[lo];
        while (lo < hi) {
            while (lo < hi) {
                if (key < array[hi]) hi--;
                else {
                    array[lo++] = array[hi];
                    break;
                }
            }
            while (lo < hi) {
                if (array[lo] < key) lo++;
                else {
                    array[hi--] = array[lo];
                    break;
                }
            }
        }
        array[lo] = key;
        return lo;
    }
    private static void swap(int[] array, int lo, int hi) {
        int temp = 0;
        Random r = new Random();
        int k = r.nextInt(10) % (hi - lo + 1) + lo;
        temp = array[lo];
        array[lo] = array[k];
        array[k] = temp;

    }
}
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值