经典排序算法——插入排序
插入排序原理
插入的排序的原理是每趟将一个数按照大小插入到它前面已经排好序的子序列中。依次重复,直到插入全部数字。
图解插入排序原理(升序为例)
以数组[3,4,1,2]为例,升序排列数组。
第一趟从第2个数据开始(第1个数字自己已经有序),跟前面一个数字比较,如果小于前面数字就将前面数字后移,并继续向前比较,直到下标小于0为止。如下图所示
第二个数字4,插入到它前面的有序子序列(3)中,由于4>3所以直接插在3后面即无需移动。第一趟结束。指针i向后移,如下图所示
第三个数字1,插入到它前面的有序子序列(3,4)中,由于1<4所以将4后移一位(数字1会先保存起来,不必担心被覆盖),然后再让1与3比较,1<3,所以3后移一位。子序列遍历完后,将数字1放入插入位置。接着i指针后移,如下图所示
经过3趟比较后,数组中的数字已经排好顺序。下面看下具体代码
1 public static void sort(int[] array){ 2 for (int i = 1; i <array.length ; i++) { 3 int insertValue = array[i]; 4 int insertIndex = i -1 ; 5 while (insertIndex >= 0 && insertValue < array[insertIndex]){ 6 //待插入数字小于前面下标对应的数 7 array[insertIndex+1] = array[insertIndex]; 8 insertIndex --; 9 } 10 //位置找到 为insertIndex + 1 11 array[insertIndex + 1] = insertValue; 12 } 13 }
代码分析
1)第一个for循环用于确定比较趟数,i从1开始(前面有1个数,1个数的子序列肯定有序)到数组最后一个数字
2)记录当前要插入到前面子序列的值(防止子序列数字后移覆盖)
3)while依次序循环子序列,当子序列中数字大于要插入的数字时继续向前遍历,直到找到比当前数字更小或子序列遍历完,插入对应位置
时间复杂度
从代码可知,插入排序有两层循环,所以其时间复杂度为T(n)=O(n^2)
测试算法执行效率
与前面的排序算法相同,我们依然生成10万个随机数的数组,使用插入排序方法进行排序,看其执行时间。测试代码如下
1 public static void main(String []args){ 2 int[] array = new int[100000]; 3 for (int i=0; i<100000; i++){ 4 array[i] = (int)(Math.random()*800000); 5 } 6 long begin = System.currentTimeMillis(); 7 sort(array); 8 System.out.println("总耗时="+(System.currentTimeMillis() - begin)); 9 }
测试结果
可以看到插入排序算法比选择排序更快,10万个数据的数组排序大概需要1秒多时间。下篇我们将介绍基于插入算法的优化算法 --希尔排序算法,排序效率是否会更高呢?一起期待!
总结
插入排序算法的思路是从数组的第二个数开始,插入到它前面的有序子序列。依次遍历数组,直到遍历完所有数据后,数组即变为有序。