插入排序就這麼簡單
從上面已經講解了冒泡和選擇排序了,本章主要講解的是插入排序,希望大家看完能夠理解並手寫出插入排序的程式碼,然後就通過面試了!如果我寫得有錯誤的地方也請大家在評論下指出。
插入排序介紹
來源百度百科:
插入排序的基本操作就是將一個資料插入到已經排好序的有序資料中,從而得到一個新的、個數加一的有序資料,演算法適用於少量資料的排序,時間複雜度為O(n^2)。是穩定的排序方法。
將一個資料插入到已經排好序的有序資料中
- 將要排序的是一個亂的陣列
int[] arrays = {3, 2, 1, 3, 3};
- 在未知道陣列元素的情況下,我們只能把陣列的第一個元素作為已經排好序的有序資料,也就是說,把
{3}
看成是已經排好序的有序資料
一、第一趟排序
用陣列的第二個數與第一個數(看成是已有序的資料)比較
- 如果比第一個數大,那就不管他
- 如果比第一個數小,將第一個數往後退一步,將第二個數插入第一個數去
int temp;
if (arrays[1] > arrays[0]) {
//如果第二個數比第一個數大,直接跟上
} else {
//如果第二個數比第一個數小,將第一個數後退一個位置(將第二個數插進去)
temp = arrays[1];
arrays[1] = arrays[0];
arrays[0] = temp;
}
System.out.println("公眾號Java3y" + arrays);
複製程式碼
二、第二趟排序
用陣列的第三個數與已是有序的資料{2,3}
(剛才在第一趟排的)比較
- 如果比2大,那就不管它
- 如果比2小,那就將2退一個位置,讓第三個數和1比較
- 如果第三個數比1大,那麼將第三個數插入到2的位置上
- 如果第三個數比1小,那麼將1後退一步,將第三個數插入到1的位置上
//第二趟排序--------------------
if (arrays[2] > arrays[1]) {
//如果第三個數比第二個數大,直接跟上
} else {
//如果第三個數比第二個數小,將第二個數往後退一個位置,讓第三個數跟第一個數比
temp = arrays[2];
arrays[2] = arrays[1];
//如果第三個數比第一個大,那就插入到第二個數中
if (temp > arrays[0]) {
arrays[1] = temp;
} else {
//如果第三個數比第一個小,將第三個數插入到第一個數前面
int swapTemp = arrays[0];
arrays[0] = temp;
arrays[1] = swapTemp;
}
}
System.out.println("公眾號Java3y" + arrays);
複製程式碼
....
三、簡化程式碼
從前兩趟排序我們可以摸出的規律:
- 首先將已排序的資料看成一個整體
- 一個陣列是需要
n-1
趟排序的,總是用後一位跟已排序的資料
比較(第一趟:第二位跟已排序的資料
比,第二趟:第三位跟已排序的資料
比) - 用第三位和
已排序的資料
比,實際上就是讓第三位數跟兩個數比較,只不過這兩個數是已經排好序的而已。而正是因為它排好序的,我們可以使用一個迴圈就可以將我們比較的資料插入進去
//臨時變數
int temp;
//外層迴圈控制需要排序的趟數(從1開始因為將第0位看成了有序資料)
for (int i = 1; i < arrays.length; i++) {
temp = arrays[i];
//如果前一位(已排序的資料)比當前資料要大,那麼就進入迴圈比較[參考第二趟排序]
while (arrays[i - 1] > temp) {
//往後退一個位置,讓當前資料與之前前位進行比較
arrays[i] = arrays[i - 1];
//不斷往前,直到退出迴圈
i--;
}
//退出了迴圈說明找到了合適的位置了,將當前資料插入合適的位置中
arrays[i] = temp;
}
複製程式碼
上面的程式碼還缺少了一個條件:如果當前比較的資料比已排序的資料
都要小,那麼while
中的arrays[i - 1]
會比0還要小,這會報錯的。
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: -1
at Main.main(Main.java:61)
複製程式碼
我們應該加上一個條件:i>=1
時才可以,如果i=1
了下次再進去的時候就退出迴圈,讓當前資料插入到[0]
的位置上
所以完整的程式碼是這樣的:
//臨時變數
int temp;
//外層迴圈控制需要排序的趟數(從1開始因為將第0位看成了有序資料)
for (int i = 1; i < arrays.length; i++) {
temp = arrays[i];
//如果前一位(已排序的資料)比當前資料要大,那麼就進入迴圈比較[參考第二趟排序]
while (i >= 1 && arrays[i - 1] > temp) {
//往後退一個位置,讓當前資料與之前前位進行比較
arrays[i] = arrays[i - 1];
//不斷往前,直到退出迴圈
i--;
}
//退出了迴圈說明找到了合適的位置了,將當前資料插入合適的位置中
arrays[i] = temp;
}
System.out.println("公眾號Java3y" + arrays);
複製程式碼
四、插入排序優化
二分查詢插入排序的原理:是直接插入排序的一個變種,區別是:在有序區中查詢新元素插入位置時,為了減少元素比較次數提高效率,採用二分查詢演算法進行插入位置的確定。
參考資料:www.cnblogs.com/heyuquan/p/…
五、擴充套件閱讀
C語言實現第一種方式:
void InsertSortArray ( int arr[], int n)
{
//int arr[]={2,99,3,1,22,88,7,77,54};
for (int i = 1; i < n; i++)// 迴圈從第二個陣列元素開始
{
int temp = arr[i];//temp標記為未排序的第一個元素
while (i >= 0 && arr[i - 1] > temp) //將temp與已排序元素從大到小比較,尋找temp應插入的元素
{
arr[i] = arr[i - 1];
i--;
}
arr[i] = temp;
}
}
複製程式碼
C語言實現第二種方式:
void insert ( int arr[], int n)
{
int key = arr[n];
int i = n;
while (arr[i - 1] > key) {
arr[i] = arr[i - 1];
i--;
if (i == 0)
break;
}
arr[i] = key;
}
void insertionSort ( int arr[], int n)
{
int i;
for (i = 1; i < n; i++) {
insert(arr, i);
}
}
複製程式碼
測試程式碼:
main()
{
int arr[] = {99, 2, 3, 1, 22, 88, 7, 77, 54};
int i;
insertionSort(arr, 9);
for (int i = 0; i < 9; i++)
cout << arr[i] << endl;
return 0;
}
複製程式碼
參考資料:
如果文章有錯的地方歡迎指正,大家互相交流。習慣在微信看技術文章,想要獲取更多的Java資源的同學,可以關注微信公眾號:Java3y