前言
插入排序
就是每一步都将一个待排数据按照其大小插入到已排数据中合适位置,直至所有数据都排列完毕。我这里按照数据从小到大
顺序排列。因此可以将上面原理简化成每趟寻找array[i]这个元素的合适插入位置,将其放入其中
直到所有数据(i=n)排列完毕。
插入排序介绍
介绍原理
插入排序是一种稳定的排序,上面提到了每一趟当中寻找array[i]
的合适位置,如果此时它已经在合适位置就不需要进行移动了,可以省去一部分时间。内层循环进行的条件为array[j] < array[j-1]
。那么我们可以猜想如果array[j-1]< array[j]
此时元素在自己本该在的位置,就不需要进行一次循环。这种思想相对于选择排序不管元素是否在自己本应该在的位置上都需要进行寻找一遍,有了一定的优化。所以说插入排序在针对几乎是有序
的序列进行排序的时候,效率会提高很多,最优化效率可以提高到O(n)
.
代码实现
上面说了思想,下面就来看一看代码实现部分。
1 | /** |
- 写法一
简单直观,寻找array[i]这个元素的合适插入位置,内层循环中,当前位置元素和前一个位置进行比较,如果array[j]< array[j-1]
进行两个位置数据交换。调用swap()
方法.同时调用swap方法时候,是两个元素调换位置,三个变量之间的交换。
- 写法二
在前面提到了,需要进行交换的前提是,array[j]< array[j-1]
后一个元素比前一个小。这个从小到大排列违背。我们可以试想可以将这样一个判断条件放入for
循环当中比较,就有了第二种写法,但是仍然需要进行两个元素调换位置,三个变量之间交换。
- 写法三
可以不用变量,在循环当中将当前元素位置array[i]
保存起来,然后将array[j] 和 array[j-1]
交换位置,赋值。
运行结果
三种写法,第一种简单直观。下面就来看一看排序的测试用例。
1 | public static void main(String[] args) { |
在这里我调用封装的SortTestHelper
类中的generateRandomArray
方法生成一个指定长度n
区间在[rangeL,rangR]
(0,10000)内的数组,并且调用方法testSort()
方法对其进行排序,打印其排序50000个元素所花费时间。这里所耗费时间跟测试电脑性能有关。
1 | InsertionSort : 5823 ms |
综合测试
上一个例子说到了选择排序
算法篇——选择排序SelectionSort,现在我就来测试一下同一个随机数组使用两个排序算法所耗费时间。
在这里就用到了上面我封装的SortTestHelper方法
,代码如下
1 | package cc.ccoder.insertion_sort; |
随机生成指定长度、范围数组
Integer[] generateRandomArray(int n, int rangeL, int rangeR)
判断数组是否有序
static boolean isSorted(Comparable[] array)
我这里使用从小打到顺序反射调用排序算法,判断其排序是否成功,计算排序时间
void testSort(Class<?> clazz, Comparable[] array)
打印数组
void printArray(Object[] array)
针对少量数据可以调用,数据量上去了不要将数组打印出来。
好了,现在已经封装好了这个类,下面我们就来写一个Main
来跑一下这两个排序算法。
1 | /** |
跑起来,看一下结果,时间长短和测试机器性能有很大关系。
1 | InsertionSort : 6166 ms |
后记
时间复杂度和空间复杂度
插入排序的时间复杂度就是判断比较
array[j] 和 array[j-1]
的次数,那么比较的次数肯定跟原数据的初始顺序有关了,当待排数组有序时候,上述方法三
中for (; j > 0 && array[j - 1].compareTo(e) > 0; j--)
这个for循环的条件就不成立了,不用进入内层循环。此时时间复杂度为O(N)
。同理,当待排数组为逆序时候,比较次数最大,对于下标为i
的元素就需要进行i-1
次比较了,总的次数就为1+2+3+···+N-1
此时的时间复杂度为O(N²)
在上方法当中引入了临时变量,因此空间复杂度为
O(1)
学习了一下插入排序,根据插入排序
的这种思想,其实还有冒泡排序
、希尔排序
,它们的一些优化、时间复杂度又是怎样的呢?
有时间,再整理整理吧….
传送门
本次
插入排序
源码部分在github上,可以在下面联系
当中找到github地址,里面的algorithm_study
为所有算法篇源码
直接传送门
InsertionSort
联系
聪聪的独立博客 ,一个喜欢技术,喜欢钻研的95后。如果你看到这篇文章,千里之外,我在等你联系。