1. 程式人生 > >資料結構-排序-快速排序之固定位置選取基準法(遞迴/非遞迴)

資料結構-排序-快速排序之固定位置選取基準法(遞迴/非遞迴)

快速排序: 資料量小的時候,使用插入排序;聚焦相同基準元素法

  • 固定位置選取排序:資料越有序,複雜度越高
  • 隨機選取基準排序
  • 三分取中法

思想:均勻的分割待排序序列 :選取一個基準par,定義兩個指標 low high 一般基準選取low下標的值;如果high下標的值比par大,high–;反之將high的值放到low 下標; low的操作和high 一樣 ;當high和low 相遇時,將par放到low角標,此時,左邊全是比par小的,右邊全是比par 大的;

快速排序:遞迴實現 ,一趟排序結束後如果基準左右兩邊的元素數量大於等於2,那麼說明左右還沒有有序,那麼在確定新的low 和high的值 繼續呼叫此方法;

public static int partion(int []array ,int low,int high){    //一趟快速排序;
          int tmp=array[low];
          while(low<high){
                   while(low<high&& array[high]>tmp){  //如果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;
        }
         /**
     * 時間複雜度:O(nlog2n)
     * 空間複雜度:O(log2n)
     * 穩定性:不穩定
     * @param array
     * @param low
     * @param high
     */
      public static  void  quick(int [] array ,int low,int high ){
            int par=partion(array,low,high); 返回下一趟排序的基準;
            if(par>low+1){  //新的基準與邊界之間的元素大於等於兩個就可以確定新的par
            quick(array,low,par-1); //log 2 N;   基準左邊遞迴
            }
            if(par<high-1){
               quick(array ,par+1,high); //右邊遞迴。
            }
     }
     public static void  quickSort(int array){
          quick(array,0,array.length-1);
     }
       public static void main(String[] args) {
        int[] array = new int[10000];//n   log2n
        Random random = new Random();
        for (int i = 0; i < array.length; i++) {
            array[i] = random.nextInt(10000)+1;
        }
        System.out.println(System.currentTimeMillis());
        quickSort(array);
        System.out.println(System.currentTimeMillis());
        System.out.println(Arrays.toString(array));
    }

快速排序: 非遞迴解法 :思想和遞迴解法差不多,只不過左右兩邊沒有序,將新的low和high壓入模擬棧中;在呼叫確定基準並排序的方法;只要棧不為空,那麼就需要進行排序

public class TestQuickSort {
    //一趟快速排序函式
    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 quickSort(int [] array){
            int high=array.length-1;
            int low=0;
            int par=partion(array,low,high);
            int size=(int)(Math.log(double)array.length/Math.log2d+1);  //這裡如果閒麻煩可以直接將長度確定為array 的長度;
            int []  stack=new int [size*3]  //log2n
            //按理應該是*2  但是溢位,所以*3 。 可以直接放array的長度;
            int  top=0;
            if(par>low+1){   //先壓第一次迴圈後符合條件的,在進迴圈
                  stack[top++]=low; 先入後出
                  stack[top++]=par-1;
            }
            if(par<high-1){
                 stack[top++]=par+1;
                 stack[top++]=high;
            }
            while(top>0){  //每次出一對low high 排序
                  high=stack[--top]; //後進先出
                  low=stack[--top];
                  par=partion(array,low,high);//呼叫一次快排確定新的基準
                   if(par>low+1){   
                  stack[top++]=low; 先入後出
                  stack[top++]=par-1;
                 }
                if(par<high-1){
                 stack[top++]=par+1;
                 stack[top++]=high;
                }
            }
    }
     public static void main(String[] args) {
        int[] array = new int[10000];//n   log2n
        Random random = new Random();
        for (int i = 0; i < array.length; i++) {
            array[i] = random.nextInt(10000)+1;
        }
        System.out.println(System.currentTimeMillis());
        quickSort(array);
        System.out.println(System.currentTimeMillis());
        System.out.println(Arrays.toString(array));
    }
}