Java数据结构与算法(四)快速排序法

一、快速排序法分析

算法思想:
现将4(实际中是第一个元素)移动到它排好序之后的正确位置,那么左边的都是小于4的,右边的元素都是大于4的:
这里写图片描述
对小于4这部分元素的和大于4的这部分元素分别继续使用快速排序法,逐渐递归下去。
将第一个元素放到正确的位置:
这里写图片描述

二、快速排序法代码

public class KuaiSuPaiXu {
    //arr[l...r]部分进行快速排序
    private static void quickSort(int[] arr,int l,int r){
        if( l >= r )  return;
        int p = partition(arr,l,r);  //找到中间位置
        quickSort(arr,l,p-1);
        quickSort(arr,p+1,r);
    }
    //首先将第一个元素移动到排好序之后应该放的位置
    //使得p之前的元素都小一些,p之后的元素都大一些
    //返回p,使得arr[ l ... p-1 ] < arr[ p ]
    //arr[ p + 1 ... r] > arr[ p ]
    private static int partition(int[] arr,int l,int r){
        int v = arr[l];   //取出第一个元素
        int j = l;        //j表示小于第一个元素和大于第一个元素的分界点
        //当前访问的元素称为i
        for( int i = l + 1;i <= r;i++ ){
            //将所有小于第一个元素的值的元素全部都放到它的左边
            if( arr[i] < v ){     //如果当前元素小于v,则交换
                swap(arr,i,j+1);
                j++;
            }
        }
        swap(arr,l,j);  //将第一个元素和中间的元素进行交换
        return j;
    }
    public static void main(String[] args){
        int array[] = {1,2,4,3,9,7,8,6};
        quickSort(array,0,array.length-1);
        for( int i = 0 ; i < array.length ; i++ ){
            System.out.print(array[i]+" ");
        }
    }
    static void swap(int[] arr,int a,int b){
        int temp = 0;
        temp = arr[a];
        arr[a] = arr[b];
        arr[b] = temp;
    }
}

运行结果:
1 2 3 4 6 7 8 9

三、快速排序法的问题以及改进

当数据的量比较少的时候,直接用插入排序法效率高,所有加以优化:

private static void quickSort(int[] arr,int l,int r){
     if( l >= r )  return;
     if(r - l <= 15)
         ChaRuPaiXu.ChaRuPaiXuFa2(arr,l,r);
     int p = partition(arr,l,r);  //找到中间位置
     quickSort(arr,l,p-1);
     quickSort(arr,p+1,r);
 }

当数组近乎有序的时候,快速排序法的效率特别低。最差的时候为O(n^2)。所有继续优化。

四、随机化快速排序法

之前我们每次取的时候都是用的第一个元素,现在我们随机取出元素作为参考值,这样为O(n^2)的概率变得特别小,算法效率为O(nlogn):

private static int partition(int[] arr,int l,int r){
      /****************添加代码**********************/
      //随机取出一个元素,然后交换
      Random rm = new Random();
      int rm1 = rm.nextInt( r - l + 1);
      swap(arr,l,rm1 + l);
      /*********************************************/
      int v = arr[l];   //取出第一个元素
      int j = l;        //j表示小于第一个元素和大于第一个元素的分界点
      //当前访问的元素称为i
      for( int i = l + 1;i <= r;i++ ){
          //将所有小于第一个元素的值的元素全部都放到它的左边
          if( arr[i] < v ){     //如果当前元素小于v,则交换
              swap(arr,i,j+1);
              j++;
          }
      }
      swap(arr,l,j);  //将第一个元素和中间的元素进行交换
      return j;
}

五、双路快速排序法

如果数组中的元素有很多重复元素的话,快递排序效率很差。我们采用双路快速排序方法:

private static int partition2(int[] arr,int l,int r){
    //随机取出一个元素,然后交换
    Random rm = new Random();
    int rm1 = rm.nextInt( r - l + 1);
    swap(arr,l,rm1 + l);
    int v = arr[l];   //取出第一个元素
    int i = l + 1,j = r;
    while (true){
        while ( i <= r && arr[i] < v) i++;
        while ( j <= l + 1 && arr[j] > v) j--;
        if( i > j ) break;
        swap(arr,j,j);
        j++;
        j--;
    }
    swap(arr,j,l);
    return j;
}

转载请标明出处,原文地址:https://blog.csdn.net/weixin_41835916
总结整理不容易,如果觉得本文对您有帮助,请点击支持一下,您的支持是我写作最大的动力,谢谢。
这里写图片描述

猜你喜欢

转载自blog.csdn.net/weixin_41835916/article/details/81168265