排序-快速排序的优化(三分取中法实现)

优化一:当待排列序列的长度分割到一定大小时,使用插入排序
原因:对于很小和部分有序的数组,快排不如插入排序好。当待排序序列的长度分割到一定大小后,继续使用分割的效率比插入排序要差; 但是三分取中+插入排序还不能处理重复数组;
优化二:聚集相同基准法;处理重复的数组元素
原因:在一次分割结束后,可以把与par相等的元素聚集在一起。下次分割时,不用在对和par相等元素进行分割
举例:

待排序序列 1 4 6 7 6 6 7 6 8 6

三数取中选取枢轴:下标为4的数6

转换后,待分割序列:6 4 6 7 1 6 7 6 8 6
枢轴par:6

本次划分后,未对与par元素相等处理的结果:1 4 6 6 7 6 7 6 8 6

下次的两个子序列为:1 4 6 和 7 6 7 6 8 6

本次划分后,对与key元素相等处理的结果:1 4 6 6 6 6 6 7 8 7

下次的两个子序列为:1 4 和 7 8 7

经过对比,我们可以看出,在一次划分后,把与par相等的元素聚在一起,能减少迭代次数,效率会提高不少

具体过程:在处理过程中,会有两个步骤

划分结束后,把与par相等的元素移到par周围

举例:

待排序序列 1 4 6 7 6 6 7 6 8 6

三数取中选取枢轴:下标为4的数6

转换后,待分割序列:6 4 6 7 1 6 7 6 8 6
枢轴par:6

划分结束后,把与par相等的元素移到枢轴周围

结果为:1 4 66(枢轴) 6 6 6 7 8 7

此时,与6相等的元素全移到枢轴周围了,之后在对14和787两个子序列进行快排

之后,在1 4 和 7 8 7两个子序列进行快排

/**
 * @Author 《BoYou》
 * @Description   快排的优化
 *   当数据小于100的时候,用直接插入
 *   海量数据时,每次取到par时,左右各循环
 *   将与par相同的值都移动到par附近,则下次排序
 *   就会从不相同的临界值开始
 * @Date 2019/1/10 -- 下午 8:51
 */
public class FastSort05 {
    public static void main(String[] args) {
        Random ran=new Random();
        int[] array=new int[120];
        for (int i = 0; i <120 ; i++) {
            array[i] = ran.nextInt(99)+1;
        }
        quicksort(array);
        System.out.println(Arrays.toString(array));

    }
    public static void quicksort(int[] array){
        quick(array,0,array.length-1);
    }

    public static int[] foucsParNum(int[] array,int par,int low,int high){
     //聚集相同元素
        int left=par-1;
        int right=par+1;
        int[] brray=new int[2];
        for (int i = par-1; i >low ; i--) {
            if (array[i]==array[par]){
                if (left!=i){
                    swap(array,left,i);
                }
                left--;
            }
        }
        for (int j = par+1; j <high ; j++) {
            if (array[j]==array[par]){
                if (right!=j){
                    swap(array,right,j);
                }
                right++;
            }
        }
        brray[0]=left;
        brray[1]=right;
        return brray;
    }

    public static void quick(int[] array, int low,int high){
        if (high-low+1<100){
            insertsort(array,low,high);
            return;
        }
        midThree(array,low,high);
        int par=parvion(array,low,high);
        int[] brray=foucsParNum(array,par,low,high);
        int left=brray[0];
        int right=brray[1];
        if (left>low){
            quick(array,low,left);
        }
        if (right<high){
            quick(array,right,high);
        }
    }
    public static void insertsort(int[] array,int low,int high){
        int tmp=0;
        int j=0;
        for (int i = 1; i <= high; i++) {
            tmp=array[i];
            for ( j = i-1; j >=low ; j--) {
                if (array[j]>tmp){
                    array[j+1]=array[j];
                }else {
                    break;
                }
            }
            array[j+1]=tmp;
        }
    }
    
   
    //三分取中法实现原理:
       //array[mid]<=array[low]<=array[high]; 
    public static void midThree(int[] array,int low,int high){
        int mid=(low+high)/2;
        if (array[mid]>array[low]){
            swap(array,low,mid);
        }
        if (array[mid]>array[high]){
            swap(array,mid,high);
        }
        if (array[low]>array[high]){
            swap(array,low,high);
        }
    }
    public static void swap(int[] array ,int low,int rand){
        int tmp=array[low];
        array[low]=array[rand];
        array[rand]=tmp;
    }
    public static int parvion(int[] array,int low,int high){
        int tmp=array[low];

        while (low<high){
            while (low<high&&tmp<array[high]){
                high--;
            }
            if (low<high){
                array[low]=array[high];
                low++;
            }else break;
            while (low<high&&tmp>array[low]){
                low++;
            }
            if (low<high){
                array[high]=array[low];
                high--;
            }else break;
        }

        array[low]=tmp;
        return low;
    }
}

猜你喜欢

转载自blog.csdn.net/qq_39602004/article/details/87902162
今日推荐