排序算法——插入排序
基本思想:
通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应的位置并插入。

算法描述:
以n个数升序排序为例,从第2个元素开始遍历,到最后一个数结束,共遍历(n-1)轮,对与第i轮:
将元素设为target与第(i-1)个元素比较,若target小于元素(i-1),则将元素(i-1)后移一位,
将target与元素(i-2)比较,若target小于元素(i-2),则将元素(i-2)后移一位,
......
如此类推,直到target大于某个元素,则将target插入该元素后的空位中,
若已经遍历到队头也没有比target小的数,则把target插入队头。
可以看出,对于第i轮遍历,前(i-1)个元素是有序的。
另外为什么要强调从后向前比较,如果从前向后比较,找到正确位置后,需要将该位置后的所有元素(包括有序的和未排序的)后移一位,效率感人;
从已排序序列从后向前遍历,首先,抽起的target遗留了一个空位,利用这个空位,后边未排序的元素不必后移,移动的元素减少了,
其次,遍历的时候同时作比较和位移两个操作,而非先遍历一次找到位置,再遍历一次移动元素,效率自然就更高了。
Java代码实现:
 1 /**
 2  * 用插入排序算法对整型数组进行升序排序
 3  *
 4  * @param arr:待排序数组
 5  */
 6 private static void insertSort(int[] arr) {
 7     if (arr == null || arr.length <= 1)
 8         return;
 9     for (int i = 1; i < arr.length; i++) { //从第2个元素开始遍历
10         int target = arr[i];
11         int j = i;
12         while (j > 0 && target < arr[j - 1]) { //遍历直到队头或找到比target小的元素
13             arr[j] = arr[j - 1]; //将arr[j-1]后移一位
14             j--;
15         }
16         arr[j] = target; //将target插入到正确位置
17     }
18 }
特点:
1. 插入排序平均时间复杂度是O(N2),情况最好时(全部已排序)为O(N),情况最坏时(全部反序)为O(N2)。
2. 插入排序是稳定的排序算法。
优化:
二分插入排序,又叫折半插入排序,是对直接插入排序的一种优化。
二分插入排序插入时不再是从后往前遍历,而是对已有序的元素做二分查找操作,找到正确位置。
当元素比较多时,总比较次数比直接插入排序的最差情况好得多,但比最好情况要差。元素基本有序时,直接插入排序比二分插入排序比较次数少。
二分插入排序元素移动次数与直接插入排序相同。
二分插入排序的平均时间复杂度是O(N2),情况最好时是O(logN),情况最坏时是O(N2)。二分插入排序是稳定的排序算法。
1 /** 2 * 用二分插入排序算法对整型数组进行升序排序 3 * 4 * @param arr:待排序数组 5 */ 6 private static void binaryInsertSort(int[] arr) { 7 if (arr == null || arr.length <= 1) 8 return; 9 for (int i = 1; i < arr.length; i++) { 10 int target = arr[i]; 11 int insertIndex = findInsertIndex(arr, i - 1, target); 12 //如果待插入位置就是当前位置,则不必作后移操作,直接跳过 13 if (i == insertIndex) 14 continue; 15 //从有序元素的最后一个元素开始,作后移操作,到待插入位置的元素后移后结束 16 for (int j = i - 1; j >= insertIndex; j--) 17 arr[j + 1] = arr[j]; 18 //将待插入元素插入正确位置 19 arr[insertIndex] = target; 20 } 21 } 22 23 /** 24 * 用二分查找算法,找到二分插入排序算法中,待插入元素的正确位置 25 * 26 * @param arr:待排序数组 27 * @param maxIndex:已有序元素的最大下标 28 * @param target:待插入元素 29 * @return 待插入元素的正确位置 30 */ 31 private static int findInsertIndex(int[] arr, int maxIndex, int target) { 32 int low = 0; 33 int high = maxIndex; 34 while (low <= high) { 35 int mid = (low + high) / 2; 36 if (arr[mid] > target) 37 high = mid - 1; 38 else 39 low = mid + 1; 40 } 41 return low; 42 }
 
                    
                     
                    
                 
                    
                
 
                
            
         
         浙公网安备 33010602011771号
浙公网安备 33010602011771号