排序算法—高級篇

距離上次的排序算法文章已通過了蠻久了,今天終於有時間來寫寫高級的排序,若有不當請多指教!java

  • 歸併排序
  • 快速排序

歸併排序

定義

  • 要將一個數組排序,能夠先(遞歸地)將它分紅兩半分別排序,而後將結果歸併起來

特性

  • 歸併排序的時間複雜度是O(N*lgN)
  • 歸併排序是穩定的

clipboard.png

代碼實現

public class MergeSort {

    private static int[] temp;//臨時數組
    
    public static void sort(int[] a) {    
        temp=new int[a.length];//避免在遞歸中頻繁新建數組
        sort(a,0,a.length-1);    
  }
    
    private static void sort(int[] a,int low,int hig) {
        
        if (hig<=low)  return;
        int mid=low+(hig-low)/2;
        sort(a, low, mid);//左邊排序
        sort(a, mid+1, hig);//右邊排序
        merge(a,low,mid,hig);//將兩個有序子數組歸併
    }
    //合併子數組
    public static void merge(int[] a,int low,int mid,int hig) {
        //i爲左序列索引、j爲右序列索引
        int i=low,j=mid+1;
        //將a[low..hig]複製到temp[low..hig]
        for (int k = low; k <= hig; k++) {
            temp[k]=a[k];
        }
        
        for (int k = low; k <= hig; k++) {
            if (i>mid)                  a[k]=temp[j++];   //左邊用盡則取右邊元素
            else if (j>hig)             a[k]=temp[i++];   //右邊用盡則取左邊元素
            else if (temp[i]<temp[j])   a[k]=temp[i++];   //比較左右取小值
            else                        a[k]=temp[j++];            
        }
    }
}

快速排序

簡單快速排序

快速排序(Quick Sort)使用分治法策略。 它的基本思想是:選擇一個基準數,經過一趟排序將要排序的數據分割成獨立的兩部分;其中一部分的全部數據都比另一部分的全部數據都 要小。而後,再按此方法對這兩部分數據分別進行快速排序,整個排序過程能夠遞歸進行,以此達到整個數據變成有序序列。算法

步驟

  1. 首先取a[low]做爲切分元素。
  2. 而後從數組左端開始向右掃描找到一個大於等於它的元素,再從數組右端開始向左掃描找到一個小於等於它的元素,而後交換兩個元素位置。
  3. 當兩個指針相遇時,將切分元素a[low]和左子數組最右側元素交換。

快速排序和歸併排序正好相反:數組

  • 歸併排序:遞歸調用發生在處理數組前。
  • 快速排序:遞歸調用發生在處理數組後。

在這裏插入圖片描述
在這裏插入圖片描述
在這裏插入圖片描述
![在這裏插入圖片描述](https://img-blog.csdnimg.cn/20190621094100719.png?x-oss-process=image/watermark,type_ZmFuZ3poZW5naGVpdGk,shadow_10,text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L2N6eTE0Mjg1MjgxNDY=,size_16,color_FFFFFF,t_70

時間&空間複雜度

平均 最好 最壞 空間 穩定性
O(nlogn) O(nlogn) O(n^2) O(logn) 不穩定

代碼實現

public class QuickSort {

    public static void sort(int[] a){    
        shuffle(a);//虛擬方法,打亂數組以加快排序
        sort(a,0,a.length-1);
    }
    private static void sort(int[] a,int low,int hig) {
        
        if (hig<=low)  return;
        int j=partition(a,low,hig);
        sort(a, low, j-1);
        sort(a, j+1, hig);
 }
    private static int partition(int[] a, int low, int hig) {
         
        int i=low,j=hig+1;
        int v=a[low];//切分元素
        while(true){
            while(a[++i]<v) if(i==hig) break;//從左側開始尋找比v大的元素
            while(v<a[--j]) if(j==low) break;//從右側開始尋找比v小的元素
            if(i>=j)   break; //指針相遇,退出主循環
            //交換i、j的值
            swap(a,i, j);            
        }
        //交換切分元素v和a[j]            
        swap(a, low, j);
        return j;
    }
    private static void swap(int[] a,int i,int j){
        int t;
        t=a[i];
        a[i]=a[j];
        a[j]=t;
    }    
}

優化

  • 對於小數組,快速排序比插入排序慢,所以在排序小數組時應該切換到插入排序

將sort()中的語句優化

if (hig <= low) return;

替換成ui

if (hig <= low + M){ InsertSort.sort(a,low,hig); return; }

對於含有大量重複元素的數組,使用三向切分快速排序進行改進spa

三向切分的快速排序

從左到右遍歷數組一次,維護一個指針 lt 使得 a[ low…lt-1 ] 中的元素小於v,一個指針 gt 使得 a[ gt+1…hig ] 中的元素都大於v,一個指針 i 使 a[ lt…i-1 ] 中的元素都等於v,a[ i…gt ] 中的元素都還未肯定3d

在這裏插入圖片描述

咱們對a[i]進行三向比較來處理如下狀況:指針

  • a [ i ] 小於 v,將a [ lt ] 和 a [ i ] 交換,將 lt 和 i 加一;
  • a [ i ] 大於 v,將a [ gt ] 和 a [ i ] 交換,將 gt 減一;
  • a [ i ] 等於 v,將 i 加一;

代碼實現

public class QuickSort3Way {

    public static void sort(int[] a) {
        sort(a, 0, a.length - 1);
    }

    private static void sort(int[] a, int low, int hig) {
    
        if (hig <= low) return;
        //a[ low..lt-1 ] 中的元素小於v
        //a[ gt+1..hig ] 中的元素都大於v
        //a[ lt..i-1 ] 中的元素都等於v
        int lt = low, i = low + 1, gt = hig;
        int v = a[low];
        
        while (i <= gt) {
            if (a[i] < v) swap(a, lt++, i++);
            else if (a[i] > v) swap(a, i, gt--);
            else i++;
        }
        sort(a, low, lt - 1);
        sort(a, gt + 1, hig);
    }
    //交換數組元素
    private static void swap(int[] a, int i, int j) {
        int temp = a[i];
        a[i] = a[j];
        a[j] = temp;
    }    
}

參考

《算法4》第四版code

相關文章
相關標籤/搜索