快速排序的几种优化方式

快速排序的几种优化方式

1.对于基准选取方式的优化:

(1),随机选取基准的方法:

    /*进行第一趟快速排序
     * */
    public static int partion(int[] array,int low,int high){
        int tmp = array[low];
        while(low<high){
            while(low < high && array[high] >= tmp){
                --high;
            }
            if(low >= high){
                break;
            }else{
                array[low] = array[high];
            }
            while(low < high && array[low] <= tmp){
                ++low;
            }
            if(low >= high){
                break;
            }else{
                array[high] = array[low];
            }
        }
        array[low] = tmp;
        return low;
    }
/*交换函数
    */
    public static void swap(int[] array,int start,int end){
        int tmp = array[start];
        array[start] = array[end];
        array[end] = tmp;
    }

    public static void Quick(int[] array,int start,int end){
        /*让随机数位置的元素与start位置的元素进行交换
         * */
        swap(array,start,(int)(Math.random()%(end-start)+start));//产生start与end直接的随机数,并执行强制转换
        //然后进行第一次排序
        int par = partion(array,start,end);
        //对par左面的元素进行排序
        if(par > start+1){
            Quick(array, start, par-1);
        }//对par有面的元素进行排序
        if(par < end-1){
            Quick(array, par+1, end);
        }
    }

(2),三数取基准法

在快排的过程中,每一次我们要取一个元素作为枢纽值,以这个数字来将序列划分为两部分。在此我们采用三数取中法,也就是取左端、中间、右端三个数,然后进行排序,将中间数作为枢纽值。

 public static void dealPivot(int[] a, int left, int right) {
            int mid = (left + right) / 2;
            //把mid  left  right 三个位置中中间的元素放在left位置
         if(a[left]<a[right]){
             if(a[mid]>a[left]&&a[mid]<a[right]){
                 swap(a, left, mid);
             }
             if(a[mid]<a[left]){

             }
             if(a[right]<a[mid]){
                 swap(a, left, right);
             }

         }
         if(a[left]>a[right]){
             if(a[mid]<a[left]&&a[mid]>a[right]){
                 swap(a, left, mid);
             }
             if(a[mid]>a[left]){

             }
             if(a[right]>a[mid]){
                 swap(a, left, right);
             }

         }

        }


2.同元素聚合法
把所有与基准相同的元素放在中间,以减少不必要的找基准次数。

public static int[] focurNum(int[] array,int start,int end,int par){
    /*聚集与基准相同的元素
     * */
    int parLeft = par-1;//从基准左面相邻的位置开始
    int parRight = par+1;//从基准右面相邻的位置开始
    int tmp = 0;
    /*先在左面找相同的
     * */
    for(int i = par-1;i >= start;i--){
        if(array[i] == array[par]){
            if(i != parLeft){//找到与基准相同的值,进行交换
                tmp = array[parLeft];
                array[parLeft] = array[i];
                array[i] = tmp;
                parLeft--;//移动下标
            }else{
                parLeft--;
            }

        }
    }
    int left = parLeft;//左面离基准最近的一个与基准不同的元素的下标
    /*
     * 右边找
     */
    for(int j = par+1;j <= end;j++){
        if(array[j] == array[par]){
            if(j != parRight){
                tmp = array[parRight];
                array[parRight] = array[j];
                array[j] = tmp;
                parRight++;
            }else{
                parRight++;
            }
        }
    }
    int right = parRight;//右面离基准最近的一个与基准不同的元素的下标
    int[] brray = new int[2];//使用brray数组把俩个下标储存起来
    brray[0] = left;
    brray[1] = right;
    return brray;//返回brray数组
}

/*快速排序
*/
public static void Quick(int[] array,int start,int end){

    int par = partion(array,start,end);//先进行第一次找基准

    int[] brray = focurNum(array,start,end,par);
    int left = brray[0];//左面离基准最近的一个与基准不同的元素的下标赋给left
    int right = brray[1];//右面离基准最近的一个与基准不同的元素的下标赋给right
    if(par > start+1){//基准左面排序
        Quick(array, start, left);
    }

    if(par < end-1){//基准右面排序
        Quick(array, right, end);
    }
}

3,数据少的时候,用直接插入法

    public static void quick1(int []a,int start,int end){
        if((a.length)<10){//当数组的长度不足10的时候,使用直接插入排序
            for(int i=1;i<a.length;i++){
                    int temp = a[i];
                    int j=0;
                    for( j=i-1;j>=0;j--){
                         if(a[j]>temp){
                             a[j+1] = a[j];

                         }else{
                             break;
                         }
                    }
                    a[j+1] = temp;
                }
                return ;
            }

        int par=partion(a, start, end);//先确定第一个基准
        if(par>start+1){//如果基准左面有俩个或者俩个以上的元素
            quick1(a, start, par-1);//左面进行快速排序
        }
        if(par<end-1){//如果基准右面有俩个或者俩个以上的元素
            quick1(a, par+1, end);//右边进行快速排序
        }
    }

猜你喜欢

转载自blog.csdn.net/qq_37232304/article/details/80358922