一、排序思路
將原有的數組看為兩塊,一塊是已經排好序的(我們叫有序區),一塊是待排序的(我們叫無序區),不斷地從無序區中取出其第一個元素,搜尋該元素應該放在有序區的哪個位置,並將該元素放入該位置,完成這個步驟后,有序區長度+1,無序區長度-1,直至無序區長度為0,即無序區中不再有元素,排序就完成啦。
二、有序區和無序區的選取
把輸入的數組的第一個元素定義為有序區(只有一個元素,怎么放都有序),其余的元素都定義在無序區中。
三、搜尋合適位置
不難發現,排好序的數組除頭尾之外,某個元素的后一個元素一定大於或者等於該元素,該元素的前一個元素一定小於等於該元素。從這個想法中可以提煉出來搜尋合適位置存放插入元素的方法,我們可以從有序區的最后一個元素,即已排序的最大元素,開始與插入元素比較,若插入元素比該元素小,那么插入元素的插入位置一定在最后一個元素之前,緊接着再將插入元素與有序區的倒數第二個元素比較,若插入元素比倒數第二個元素小,那么插入元素插入的位置將在倒數第二個元素之前......依次類推,當插入元素比與之比較的元素小的時候,停止比較,插入元素的位置則在此元素之后。
四、插入元素
找到合適的位置之后,我們將有序區內該位置及該位置之后的元素都往右移一位,這樣就將該位置空出來了,再將插入元素插入其中。
五、圖形說明
文字表述較為抽象,我們用圖形來說明一下直接插入排序的過程,下面將對數組{8,3,2,7,4,5}進行排序:
首先確定有序區和無序區,由於一個元素無論如何排放都可以看做有序的,那么我們將第一個元素作為有序區,其余的作為無序區
接着,我們開始進行插入操作,每次插入都是選用無序區的第一個元素,如上圖,確定好有序區和無序區后,即可確定即將插入的元素,即是原有數組的第二個元素,現將插入元素放入有序區,再搜尋合適位置
可以發現插入的元素“3”比有序區中最后一個元素“8”小,故元素“3”放在元素“8”之前,比較結束之后,元素“3”之前再無元素,可以看做元素“3”之前的元素比其小,結束比較,將元素“8”往右移一位,並將元素“3”插入搜尋到的位置,第一輪插入結束,是不是感覺很簡單?我們繼續往下看
再取出無序區中第一個元素“2”,將其放去有序區中與有序區的各個元素進行比較,下圖中線的左邊代表有序區,右邊代表無序區,由於上圖中給出了,以下的圖就不明確說明啦!!
這里值得注意的是,插入排序中插入元素搜尋合適位置並不是遇到一個比插入元素小的元素就進行交換,而是記錄該位置,並在接下來的比較中更新記錄
顯而易見,元素“2”比元素“8”小,所以插入位置會暫時停留在元素“3”與元素"8"之間,並記錄下來,元素“2”再往下繼續比較,元素“2”比元素“3”小,且元素“3”之前不再有元素,所以元素“2”插入位置最終定在元素“3”之前,將元素“3”和元素“8”都往右移一位,將元素“2”插入搜尋到的位置,第二輪插入結束。
接下來的幾步插入類似就不一一列出來了,下面讓我們一起來看看Java代碼是如何實現的。
六、代碼實現
1 /** 2 * 直接插入排序的方法 3 * @param a 需要排序的數組 4 */ 5 public void insertSort(int[] a) { 6 //遍歷除了第一個元素外的所有元素,即將初始無序區內的元素一一插入有序區 7 for (int i = 1; i < a.length; i++) { 8 //存放插入元素 9 int temp = a[i]; 10 //定義j變量,並初始化,j變量用於插入位置的定位 11 int j = 0; 12 //搜尋插入位置 13 for (j = i - 1; j >= 0; j--) { 14 //從有序區最后一個元素開始比較,若比較的元素比插入的元素大則比較的元素往右移一位 15 if (temp < a[j]) { 16 a[j + 1] = a[j]; 17 } 18 //若比較的元素比插入元素小,結束比較 19 if(temp > a[j]) { 20 break; 21 } 22 } 23 //將插入元素插入到搜尋到的合適位置 24 a[j + 1] = temp; 25 //查看每一步插入的情況 26 System.out.println(Arrays.toString(a)); 27 } 28 }
對數組{8, 3, 2, 7, 4, 5}進行排序,每一步插入的過程如下:
最后一行即排完序的最終結果。
本文為原創,轉載請注明!