1. 程式人生 > >【算法拾遺(java描寫敘述)】--- 插入排序(直接插入排序、希爾排序)

【算法拾遺(java描寫敘述)】--- 插入排序(直接插入排序、希爾排序)

ecan itblog insert med image java程序 can rip title

插入排序基本思想

每次將一個待排序的記錄按其keyword大小插入到前面已經拍好序的子文件的適當位置,直到全部記錄插入完畢為止。

直接插入排序

基本思想

直接插入排序的基本操作是將一個記錄插入到已排好序的有序表中。從而得到一個新的有序表。即如果待排序的記錄存放在數組R[1······n]中,排序過程中,R被分成兩個子區間R[1······i]和R[i+1······n],當中。R[1······i]是已經排好序的有序區;R[i+1······n]是當前未排序的部分。

將當前無序區的第一個記錄R[i+1]插入到有序區R[1······i]的適當位置,使R[1······i+1]變為新的有序區,每次插入一個數據,直到全部的數據有序為止。

技術分享

java程序

/*************************
* 
* 直接插入排序
*
*************************/
public class InsertSort {

private void insertSort(int[] datas) {
    if (datas == null || datas.length < 2)
        return;
    int i, j, insertData;
    for (i = 1; i < datas.length; i++) {
        insertData = datas[i];// 要插入的變量
        for (j = i - 1; j >= 0 && insertData < datas[j]; j--)
            datas[j + 1] = datas[j];
        datas[j + 1] = insertData;// 將要插入的數據放置到正確的位置
    }
}

public static void main(String[] args) {
    int[] datas = new int[] { 6, 5, 3, 1, 8, 7, 2, 4 };
    System.out.println("********排序前********");
    for (int i = 0; i < datas.length; i++) {
        System.out.print(datas[i] + ",");
    }
    InsertSort insertSort = new InsertSort();
    insertSort.insertSort(datas);
    System.out.println("\n********排序後********");
    for (int i = 0; i < datas.length; i++) {
        System.out.print(datas[i] + ",");
    }
}

}

性能分析

  1. 時間復雜度

技術分享

  1. 直接插入排序屬於就地排序,是一種穩定的排序方法。

希爾排序

基本思想

先取一個小於n的整數d1作為第一個增量,把文件的全部記錄分成d1個組,全部距離為d1的倍數的記錄放在同一個組中,在各組內進行插入排序;然後。取第二個增量d2 < d1,反復上述的分組和排序,直至所取得增量dt = 1(dt < dt-1 < ······ < d2 < d1),即全部記錄放在同一個組中進行直接插入排序為止。

技術分享

java程序

/*************************
* 
* 希爾排序
*
*************************/
public class ShellSort {

private void shellSort(int[] datas) {
    if (datas == null || datas.length < 2)
        return;
    int temp;// 暫存變量
    int dataLength;// 步長
    int pointer;// 進行處理的位置
    dataLength = datas.length / 2;// 初始化步長
    while (dataLength != 0) {
        for (int j = dataLength; j < datas.length; j++) {
            temp = datas[j];
            pointer = j - dataLength;
            while (pointer >= 0 && temp < datas[pointer]) {
                datas[pointer + dataLength] = datas[pointer];
                pointer = pointer - dataLength;
            }
            datas[pointer + dataLength] = temp;
        }
        dataLength = dataLength / 2;
    }
}

public static void main(String[] args) {
    int[] datas = new int[] { 6, 5, 3, 1, 8, 7, 2, 4 };
    System.out.println("********排序前********");
    for (int i = 0; i < datas.length; i++) {
        System.out.print(datas[i] + ",");
    }
    ShellSort shellSort = new ShellSort();
    shellSort.shellSort(datas);
    System.out.println("\n********排序後********");
    for (int i = 0; i < datas.length; i++) {
        System.out.print(datas[i] + ",");
    }
}

}

性能分析

希爾排序的運行時間依賴於增量序列(步長)的選取。好的增量序列有例如以下特點:

  1. 最後一個增量必須為1
  2. 應該盡量避免序列中的值(尤其是相鄰的值)互為倍數的情況。

希爾排序的時間性能要因為直接插入排序,原因例如以下:

  • 當文件初態基本有序時直接插入排序所需的比較和移動次數均較少。
  • 在希爾排序開始時增量較大,分組較多,每組的記錄數目少,故各組內直接插入較快,後來增量di逐漸縮小,分組數逐漸降低。而各組的記錄數目逐漸增多,但因為已經按di-1作為距離排過序,使文件較接近於有序狀態。所以新的一趟排序過程也較快。

    因此,希爾排序在效率上較直接插入排序有較大的改進。

希爾排序是一種不穩定的排序方法

參考資料:《數據結構與算法分析——java語言描寫敘述》、《大話數據結構》

【算法拾遺(java描寫敘述)】--- 插入排序(直接插入排序、希爾排序)