數據結構與算法之排序算法(二):交換排序

交換排序能夠分爲:冒泡排序和快速排序。其中快速排序是對冒泡排序的改進
1.冒泡排序

原理:比較臨近的兩個數字,按照從小到大的順序進行交換,這樣一趟過去後,最大(最小)的數字被交換到了最後一位,而後再從頭開始進行兩兩比較交換,直到倒數第i位時結束。算法

代碼實現:
for(int i=0;i<a.length-1;i++){
    for(int j=i + 1; j<a.length;j++){
        if(a[j] < a[j-1]){
            a[j] = a[j] ^ a[j-1];
            a[j-1] = a[j] ^ a[j-1];
            a[j] = a[j] ^ a[j-1];
        }
    }
}

分析:穩定,空間複雜度O(1),時間複雜度【最佳、最差、平均都是O(n*n)】。緩存

改進:若是當前順序已經正確,就沒有必要再冒泡了。能夠定義一個標誌變量來標誌是否當前順序已正確。
代碼實現:
for(int i=0;i<a.length-1;i++){
    bool swap = false; //定義一個標誌變量swap
    for(int j=1;j<a.length-i;j++){
        if(a[j] < a[j-1]){
            a[j] = a[j] ^ a[j-1];
            a[j-1] = a[j] ^ a[j-1];
            a[j] = a[j] ^ a[j-1];
            swap = true;
        }
    }
    if(!swap){return;}
}

分析:穩定,空間複雜度O(1),時間複雜度[最佳爲O(n)、最差、平均都是O(n*n)]。ui

 
2.快速排序(冒泡排序的改進)

原理:經過一趟排序將要排序的數據分割成獨立的兩部分,其中一部分的全部數據都比另外一部分的數據小。而後再按此方法對這兩部分數據分別進行快速排序,整個排序過程能夠遞歸進行。spa

實現思路:指針

  1. 以第一個關鍵字k1爲控制字(樞軸),將[k1,k2,....kn]分紅兩個子區。使左區全部關鍵字都小於等於控制字,右區全部關鍵字都大於等於控制字,最後控制字居兩個子區中間適當的位置。
  2. 將左區和右區分別進行遞歸處理。

代碼實現:code

public static void main(String[] args) {
        int[] arr = new int[]{50,10,90,20,40,60,80,70};
        quickSort(arr,0,arr.length-1);
        print(arr);
    }
private static void print(int[] arr) {
        for (int i : arr){
            System.out.println(i + " ");
        }
    }
private static void quickSort(int[] arr, int left, int right) {
        //定義關鍵字pivot
        int pivot = 0;
        if (left < right){
           //將序列分紅兩個子區,算出關鍵字值
            pivot = partition(arr,left,right);
            //遞歸左子區
            quickSort(arr,left,pivot - 1);
            //遞歸右子區
            quickSort(arr,pivot + 1,right);
        }
}
private static int partition(int[] arr, int left, int right) {
       //將序列第一個元素做爲關鍵字,緩存起來
        int pivotKey = arr[left];
        //循環條件,兩個指針left,right,分別指向序列的兩端,直到兩個指針重合
        while(left < right){
        //將序列最右端的值與關鍵字比較,若是大於,則應放在關鍵字右邊,right減1(向左移動一個),直到不知足條件爲止
            while(left < right && arr[right] >= pivotKey){
                right--;
            }
            //當right遇到第一個小於關鍵字或者兩個指針重合時,將該值賦給左指針指向的位置,left向右移動。right中止移動
            arr[left++] = arr[right];
            //此時移動left
            while(left < right && arr[left] <= pivotKey){
                left++;
            }
            //當left遇到第一個大於關鍵字或者兩個指針重合時,將該值賦給右指針指向的位置,lright向左移動。left中止移動
            arr[right--] = arr[left];
        }
        arr[left] = pivotKey;//將關鍵字賦值給left
        return left;//返回關鍵字所在位置
    }
}
分析:算法不穩定,空間代價【最壞O(n)、最好和平均O(logn)】,時間代價【最壞O(n*n)、最好和平均O(nlogn)】.
相關文章
相關標籤/搜索