【演算法拾遺(java描述)】--- 插入排序(直接插入排序、希爾排序)
插入排序基本思想
每次將一個待排序的記錄按其關鍵字大小插入到前面已經拍好序的子檔案的適當位置,直到全部記錄插入完成為止。
直接插入排序基本思想
直接插入排序的基本操作是將一個記錄插入到已排好序的有序表中,從而得到一個新的有序表。即假設待排序的記錄存放在數組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] + ","); }}}
效能分析時間複雜度
直接插入排序屬於就地排序,是一種穩定的排序方法。希爾排序基本思想
先取一個小於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 應該盡量避免序列中的值(尤其是相鄰的值)互為倍數的情況。
希爾排序的時間效能要由於直接插入排序,原因如下:
當檔案初態基本有序時直接插入排序所需的比較和移動次數均較少。 在希爾排序開始時增量較大,分組較多,每組的記錄數目少,故各組內直接插入較快,後來增量di逐漸縮小,分組數逐漸減少,而各組的記錄數目逐漸增多,但由於已經按di-1作為距離排過序,使檔案較接近於有序狀態,所以新的一趟排序過程也較快。因此,希爾排序在效率上較直接插入排序有較大的改進。
希爾排序是一種不穩定的排序方法
參考資料:《資料結構與演算法分析——java語言描述》、《大話資料結構》