一文搞定插入排序算法
文章目錄
- 三、插入排序
- 1、插入排序原理
- 2、圖解插入排序
- 3、插入排序思路
- 4、代碼實現插入排序
- 5、時間復雜度分析
- 6、小技巧:常用時間復雜度
- (1) O(1)
- (2) O(n)
- (3) O(n^2)
- (4) O(n^3)
- (5) O(lg n)
- (6) O(n lg n)
- (7) O(2^n)
- 7、附:常用的排序算法的時間復雜度和空間復雜度
三、插入排序
1、插入排序原理
每次處理就是將無序數列的第一個元素與有序數列的元素從后往前逐個進行比較,找出插入位置,將該元素插入到有序數列的合適位置中。
插入排序,顧名思義其基本操作就是插入,不斷把一個個元素插入到一個序列中,最終得到排序序列。
插入排序就像打牌一樣,當你摸到比較小的牌時,通常往后放,遇到比較大的牌時,通常往前方。當然了,還要看自己個人習慣。
在打牌時,我們通常每次從桌子摸一張牌,然后把這張牌再放到一個正確的位置。
為了找到這張牌放置的正確位置,我們從左到右(或者從右到左)進行比較。
2、圖解插入排序
第一輪:
i=2
第二個數與前面的數做比較,發現2比5小則把小的往前方,把大的往后放
第二輪:
i+1=3
第二輪時,從第三個數與前面的作比較,發現比5小,把2大,則把5往后移動
第三輪:
i+1=4
第三輪時,因為是i+1,所以這次是第4個數與前面的數作比較,發現自己就是最大的,則不調整位置
第四輪:
i+1=5
第四輪從第5個數開始比較,發現比2小,則放在2的前面,2和后面的都向后移動調整位置。
第五輪:
i+1=6
從第6個數依次向前比較,找到2號(按照數組的索引:0,1,2)位置,則插入此位置,并把后面的依次往后移動。
完成:
3、插入排序思路
如上圖所示,此排序需要維護一個數組中的兩個列表,可以把插入排序的數組分成已排序和未排序的數組。
排序的過程中只需要維護已排序的部分即可。
每次拿未排序列表的首個數與已排序的列表的數據依次作比較。
找到合適的位置后,移動這些的位置然后插入進來即可完成插入的操作。
步驟:
4、代碼實現插入排序
從小到大:
package 排序算法.插入排序;import java.util.Arrays;/*** @Auther: truedei* @Date: 2020 /20-6-6 22:59* @Description:*/ public class InsertionSort {public static int[] INSERTION_SORT(int[] ints){//所有參與排序的數組的索引范圍,為什么從1開始呢,因為可以把0號位置的數據當成已經排序好的for (int i = 1; i < ints.length; i++) {//一直到排到的第i個位置結束,進行倒著比較for (int j = i; j >0 ; j--) {//比較,如果符合要求則交換位置if(ints[j] < ints[j-1]){int temp = ints[j];ints[j]=ints[j-1];ints[j-1]=temp;}else {//遇到不符合要求的數據則停止,代表前面都是最小或者最大的了break;}}}return ints;}public static void main(String[] args) {System.out.println(Arrays.toString(INSERTION_SORT(new int[]{2,5,4,7,6,1,3})));}}結果:
[1, 2, 3, 5, 4, 6, 7]從大到小:
package 排序算法.插入排序;import java.util.Arrays;/*** @Auther: truedei* @Date: 2020 /20-6-6 22:59* @Description:*/ public class InsertionSort {public static int[] INSERTION_SORT(int[] ints){//所有參與排序的數組的索引范圍,為什么從1開始呢,因為可以把0號位置的數據當成已經排序好的for (int i = 1; i < ints.length; i++) {//一直到排到的第i個位置結束,進行倒著比較for (int j = i; j >0 ; j--) {//比較,如果符合要求則交換位置if(ints[j] > ints[j-1]){int temp = ints[j];ints[j]=ints[j-1];ints[j-1]=temp;}else {//遇到不符合要求的數據則停止,代表前面都是最小或者最大的了break;}}}return ints;}public static void main(String[] args) {System.out.println(Arrays.toString(INSERTION_SORT(new int[]{2,5,4,7,6,1,3})));}}結果:
[7, 6, 5, 4, 3, 2, 1][7, 6, 5, 4, 3, 2, 1]
5、時間復雜度分析
插入排序使用了雙層for循環,其中內層循環體是真正完成排序的代碼,所以我們分析插入排序的時間復雜度時忽略其他的,主要分析一下內層循環體的時間復雜度即可;
可以注意到該算法就兩個操作是有用的:
- 一個是比較數據
- 一個是交換數據
最壞的情況:
比較數據次數:
最壞的情況就是從頭到尾進行比較
(N?1)+(N?2)+(N?3)+...+2+1=((N?1)+1)×N?12=N22?N2(N-1)+(N-2)+(N-3)+...+2+1=((N-1)+1)×\frac {N-1}{2}=\frac{N^{2}}{2}-\frac{N}{2} (N?1)+(N?2)+(N?3)+...+2+1=((N?1)+1)×2N?1?=2N2??2N?
交換數據次數:
最壞的情況就是從頭到尾進行交換
(N?1)+(N?2)+(N?3)+...+2+1=((N?1)+1)×N?12=N22?N2(N-1)+(N-2)+(N-3)+...+2+1=((N-1)+1)×\frac {N-1}{2}=\frac{N^{2}}{2}-\frac{N}{2} (N?1)+(N?2)+(N?3)+...+2+1=((N?1)+1)×2N?1?=2N2??2N?
時間復雜度就是:
(N22?N2)+(N22?N2)=N2?N(\frac{N^{2}}{2}-\frac{N}{2})+(\frac{N^{2}}{2}-\frac{N}{2})=N^{2}-N (2N2??2N?)+(2N2??2N?)=N2?N
根據大O推導法則,保留最高階項: 去掉常數項還剩下:
N2N^{2} N2
所以最終得出時間復雜度為:
O(N2)O(N^{2}) O(N2)
6、小技巧:常用時間復雜度
(1) O(1)
(1)O(1) 這個針對的是常數;對于一個N,不管這個N是如何增長,這個時間是不變的。
例如下面這些代碼的時間復雜度都是O(1):
/*** @Auther: truedei* @Date: 2020 /20-6-2 22:01* @Description:*/ public class Test {public static void main(String[] args) {System.out.println("你好,我叫鄭暉");System.out.println("你好,我叫鄭暉");System.out.println("你好,我叫鄭暉");System.out.println("你好,我叫鄭暉");}}還有這種:
我有一個數組,我知道了我需要的這個數據所在的索引,然后去拿這個值,咋這種也是O(1)
/*** @Auther: truedei* @Date: 2020 /20-6-2 22:01* @Description:*/ public class Test {public static void main(String[] args) {String[] names = {"小明","小紅","鄭暉"};System.out.println("你好,我叫"+names[2]);}}(2) O(n)
O(n)是一個線性增長的。
經常用在for()循環當中
例如下面這種代碼:
/*** @Auther: truedei* @Date: 2020 /20-6-2 22:01* @Description:*/ public class Test {public static void main(String[] args) {String[] names = {"小明","小紅","鄭暉"};for (int i = 0; i < names.length; i++) {System.out.println("你好,我叫"+names[i]);}}}(3) O(n^2)
是一個平方級的的增長。經常出現在兩層for循環。
例如本文所寫的:
public static int[] sort(int A[]){for (int i = 0; i < A.length; i++) {for (int j = 0; j < A.length -i - 1 ; j++) {.....}}return A; }(4) O(n^3)
是一個立方級的增長。經常出現在遍歷一個三層的for循環中
for (...) {for (...) {for (...) {.....}}}(5) O(lg n)
是一個對數級。
在二分查找法里就是O(lg n)。
每次執行N是以一個倍數的形式是遞減的:
比如第1次:1/2
比如第2次:1/4
比如第3次:1/8
比如第4次:1/16
…
快速的讓N的規模變小。
(6) O(n lg n)
在排序中經常見到的
(7) O(2^n)
指數級的
7、附:常用的排序算法的時間復雜度和空間復雜度
| 冒泡排序 | O(n^2) | O(n^2) | 穩定 | O(1) |
| 快速排序 | O(n^2) | O(n*log2n) | 不穩定 | O(log2n)~O(n) |
| 選擇排序 | O(n^2) | O(n^2) | 不穩定 | O(1) |
| 二叉樹排序 | O(n^2) | O(n*log2n) | 不一頂 | O(n) |
| 插入排序 | O(n^2) | O(n^2) | 穩定 | O(1) |
| 堆排序 | O(n*log2n) | O(n*log2n) | 不穩定 | O(1) |
| 希爾排序 | O | O | 不穩定 | O(1) |
如果對你有幫助,可以分享給你身邊的朋友。或者給俺點個大大的贊和大大的評論,點贊和評論就是給我最大的支持,感謝。
水平有限,難免會有疏漏或者書寫不合理的地方,歡迎交流討論。
作者:TrueDei
作者唯一博客CSDN:https://truedei.blog.csdn.net/
轉載說明:如需轉載請注明原地址和作者名。
如果喜歡我的文章,還沒看夠可以關注我,我會用心寫好每一篇文章。
歡迎大佬們加入在下的小社區:
總結
以上是生活随笔為你收集整理的一文搞定插入排序算法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【调剂】燕山大学电气工程学院付荣荣老师接
- 下一篇: Labview优化技巧