Java實現幾種常見排序方法


  日常操作中常見的排序方法有:冒泡排序、快速排序、選擇排序、插入排序、希爾排序,甚至還有基數排序、雞尾酒排序、桶排序、鴿巢排序、歸並排序等。

以下常見算法的定義

  • 1. 插入排序:插入排序基本操作就是將一個數據插入到已經排好序的有序數據中,從而得到一個新的、個數加一的有序數據,算法適用於少量數據的排序,時間復雜度為O(n^2)。是穩定的排序方法。插入排序的基本思想是:每步將一個待排序的紀錄,按其關鍵碼值的大小插入前面已經排序的文件中適當位置上,直到全部插入完為止。
  • 2. 選擇排序:選擇排序(Selection sort)是一種簡單直觀的排序算法。它的工作原理是每一次從待排序的數據元素中選出最小(或最大)的一個元素,存放在序列的起始位置,直到全部待排序的數據元素排完。 選擇排序是不穩定的排序方法。
  • 3. 冒泡排序:冒泡排序(Bubble Sort),是一種計算機科學領域的較簡單的排序算法。它重復地走訪過要排序的數列,一次比較兩個元素,如果他們的順序錯誤就把他們交換過來。走訪數列的工作是重復地進行直到沒有再需要交換,也就是說該數列已經排序完成。這個算法的名字由來是因為越大的元素會經由交換慢慢“浮”到數列的頂端。
  • 4. 快速排序:快速排序(Quicksort)是對冒泡排序的一種改進。它的基本思想是:通過一趟排序將要排序的數據分割成獨立的兩部分,其中一部分的所有數據都比另外一部分的所有數據都要小,然后再按此方法對這兩部分數據分別進行快速排序,整個排序過程可以遞歸進行,以此達到整個數據變成有序序列。
  • 5. 歸並排序:歸並排序是建立在歸並操作上的一種有效的排序算法,該算法是采用分治法(Divide and Conquer)的一個非常典型的應用。將已有序的子序列合並,得到完全有序的序列;即先使每個子序列有序,再使子序列段間有序。若將兩個有序表合並成一個有序表,稱為二路歸並。
  • 6. 希爾排序:希爾排序(Shell Sort)是插入排序的一種。也稱縮小增量排序,是直接插入排序算法的一種更高效的改進版本。希爾排序是非穩定排序算法。希爾排序是把記錄按下標的一定增量分組,對每組使用直接插入排序算法排序;隨着增量逐漸減少,每組包含的關鍵詞越來越多,當增量減至1時,整個文件恰被分成一組,算法便終止。

一、冒泡排序

  冒泡排序是一種簡單的排序算法。它重復地走訪過要排序的數列,一次比較兩個元素,如果他們的順序錯誤就把他們交換過來。走訪數列的工作是重復地進行直到沒有再需要交換,也就是說該數列已經排序完成。這個算法的名字由來是因為越小的元素會經由交換慢慢“浮”到數列的頂端。

/**  
 *  冒泡法排序   
 *  比較相鄰的元素。如果第一個比第二個小,就交換他們兩個。 
 *  對每一對相鄰元素作同樣的工作,從開始第一對到結尾的最后一對。在這一點,最后的元素應該會是最小的數。   
 *  針對所有的元素重復以上的步驟,除了最后一個。  
 *  持續每次對越來越少的元素重復上面的步驟,直到沒有任何一對數字需要比較。 

 *   
 * @param numbers  
 *            需要排序的整型數組  
 */  
public static void bubbleSort01(int[] numbers) {   
    int temp; // 記錄臨時中間值   
    int size = numbers.length; // 數組大小   
    for (int i = 0; i < size - 1; i++) {   
        for (int j = i + 1; j < size; j++) {   
            if (numbers[i] < numbers[j]) { // 交換兩數的位置   
temp = numbers[i]; numbers[i] = numbers[j]; numbers[j] = temp; } } } }

注意:以上不知是什么排序,將基准位置的元素和后面的元素進行比較,如果基准位置值比后面元素小,則交換位置,交換后的元素為新的基准元素。以下才是真正的冒泡排序。

public static void bubbleSort(int[] a) {
    int temp;
    int size = a.length;
    for(int i=1; i<size; i++) {
        for(int j=0; j<size-i; j++) {
            if(a[j] < a[j+1]) {
                temp = a[j];
                a[j]=a[j+1];
                a[j+1]=temp;
            }
        }
        for(int aa : a)
            System.out.print(aa+",");
        System.out.println();
    }
}

二、快速排序

  快速排序使用分治法策略來把一個序列分為兩個子序列。

/**  
 * 快速排序 
 *    
 *  從數列中挑出一個元素,稱為“基准”  
 *  重新排序數列,所有元素比基准值小的擺放在基准前面,所有元素比基准值大的擺在基准的后面(相同的數可以到任一邊)。在這個分割之后,  
 *  該基准是它的最后位置。這個稱為分割(partition)操作。  
 *  遞歸地把小於基准值元素的子數列和大於基准值元素的子數列排序。  
 *  
 * @param numbers  
 * @param start  
 * @param end  
 */  
public static void quickSort(int[] numbers, int start, int end) {   
    if (start < end) {   
        int base = numbers[start]; // 選定的基准值(第一個數值作為基准值)   
        int temp; // 記錄臨時中間值   
        int i = start, j = end;   
        do {   
            while ((numbers[i] < base) && (i < end))   
                i++;   
            while ((numbers[j] > base) && (j > start))   
                j--;   
            if (i <= j) {   
                temp = numbers[i];   
                numbers[i] = numbers[j];   
                numbers[j] = temp;   
                i++;   
                j--;   
            }   
        } while (i <= j);   
        if (start < j)   
            quickSort(numbers, start, j);   
        if (end > i)   
            quickSort(numbers, i, end);   
    }   
}  

 如下為完全符合快速排序定義的算法:

public static void quickSort01(int[] a, int start, int end) {
    if(start >= end)
        return;
    int i = start;
    int j = end;
    int base = a[start];
    while(i != j) {
        while(a[j] >= base && j > i)
            j--;
        while(a[i] <= base && i < j)
            i++;
        if(i < j) {
            int temp = a[i];
            a[i] = a[j];
            a[j] = temp;
        }
    }
    a[start] = a[i];
    a[i] = base;
    te(a, start, i - 1);
    te(a, i + 1, end);
}

三、選擇排序

  選擇排序是一種簡單直觀的排序方法,每次尋找序列中的最小值,然后放在最末尾的位置。

/**  
 * 選擇排序
 * 在未排序序列中找到最小元素,存放到排序序列的起始位置  
 * 再從剩余未排序元素中繼續尋找最小元素,然后放到排序序列起始位置。  
 * 以此類推,直到所有元素均排序完畢。  
 *   
 * @param numbers  
 */  
public static void selectSort(int[] numbers) {   
    int size = numbers.length;
   int temp;   
    for (int i = 0; i < size; i++) {   
        int k = i;   
        for (int j = size - 1; j >i; j--)  {   
            if (numbers[j] < numbers[k]) {
         k = j;   
       }
        }   
        temp = numbers[i];   
        numbers[i] = numbers[k];   
        numbers[k] = temp;   
    }   
} 

四、插入排序

  插入排序的工作原理是通過構建有序序列,對於未排序數據,在已排序序列中從后向前掃描,找到相應位置並插入。其具體步驟參見代碼及注釋。

/**  
 * 插入排序   
 *   
 *  從第一個元素開始,該元素可以認為已經被排序 
 *  取出下一個元素,在已經排序的元素序列中從后向前掃描  
 *  如果該元素(已排序)大於新元素,將該元素移到下一位置   
 *  重復步驟3,直到找到已排序的元素小於或者等於新元素的位置   
 *  將新元素插入到該位置中   
 *  重復步驟2    
 * @param numbers  
 */  
public static void insertSort(int[] numbers) {   
    int size = numbers.length, temp, j;   
    for(int i=1; i<size; i++) {   
        temp = numbers[i];   
        for(j = i; j > 0 && temp < numbers[j-1]; j--)   
            numbers[j] = numbers[j-1];   
        numbers[j] = temp;   
    }   
}  

五、歸並排序

  歸並排序是建立在歸並操作上的一種有效的排序算法,歸並是指將兩個已經排序的序列合並成一個序列的操作。

/**  
 * 歸並排序   
 *   
 *  申請空間,使其大小為兩個已經排序序列之和,該空間用來存放合並后的序列 
 *  設定兩個指針,最初位置分別為兩個已經排序序列的起始位置   
 *  比較兩個指針所指向的元素,選擇相對小的元素放入到合並空間,並移動指針到下一位置 
 *  重復步驟3直到某一指針達到序列尾   
 *  將另一序列剩下的所有元素直接復制到合並序列尾  
 *   
 * @param numbers  
 */  
public static void mergeSort(int[] numbers, int left, int right) {   
    int t = 1;// 每組元素個數   
    int size = right - left + 1;   
    while (t < size) {   
        int s = t;// 本次循環每組元素個數   
        t = 2 * s;   
        int i = left;   
        while (i + (t - 1) < size) {   
            merge(numbers, i, i + (s - 1), i + (t - 1));   
            i += t;   
        }   
        if (i + (s - 1) < right)   
            merge(numbers, i, i + (s - 1), right);   
    }   
}  

 

/**  
 * 歸並算法實現  
 *   
 * @param data  
 * @param p  
 * @param q  
 * @param r  
 */  
private static void merge(int[] data, int p, int q, int r) {   
    int[] B = new int[data.length];   
    int s = p;   
    int t = q + 1;   
    int k = p;   
    while (s <= q && t <= r) {   
        if (data[s] <= data[t]) {   
            B[k] = data[s];   
            s++;   
        } else {   
            B[k] = data[t];   
            t++;   
        }   
        k++;   
    }   
    if (s == q + 1)   
        B[k++] = data[t++];   
    else  
        B[k++] = data[s++];   
    for (int i = p; i <= r; i++)   
        data[i] = B[i];   
}  

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM