插入排序
插入排序
插入排序(Insertion Sort)算法通过对未排序的数据执行逐个插入至合适的位置而完成排序工作。
插入排序是一种从序列左端开始依次对数据进行排序的算法。在排序过程中,左侧的数据陆续归位,而右侧留下的就是还未被排序的数据。插入排序的思路就是从右侧的未排序区域内取出一个数据,然后将它插入到已排序区域内合适的位置上。
算法步骤
将第一待排序序列第一个元素看做一个有序序列,把第二个元素到最后一个元素当成是未排序序列。
从头到尾依次扫描未排序序列,将扫描到的每个元素插入有序序列的适当位置。(如果待插入的元素与有序序列中的某个元素相等,则将待插入元素插入到相等元素的后面。)
动图演示
插入排序的效率
N^2比较和平移的合计+N-1次移除+N-1次插入=N^2+2N-2步
大O只保留最高阶的N。
O(N^2+2N-2)还得进一步简化成O(N^2)。
在插入排序中,需要将取出的数据与其左边的数字进行比较。就跟前面讲的步骤一样,如果左边的数字更小,就不需要继续比较,本轮操作到此结束,自然也不需要交换数字的位置。
然而,如果取出的数字比左边已归位的数字都要小,就必须不停地比较大小,交换数字,直到它到达整个序列的最左边为止。具体来说,就是第k轮需要比较k-1次。因此,在最糟糕的情况下,第2轮需要操作1次,第3轮操作2次……第n轮操作n-1次,所以时间复杂度和冒泡排序的一样,都为O(n2)。
代码实现:java
static int[] insertSort(int[] arr) { // 对 arr 进行拷贝,不改变参数内容 int[] return_arr = Arrays.copyOf(arr, arr.length); int temp, j; for (int i = 1; i < arr.length; i++) { temp = arr[i];// 记录要插入的数据 j = i - 1; // 从已经排序的序列最右边的开始比较,找到比其小的数 while (j >= 0 && temp < arr[j]) { arr[j + 1] = arr[j]; arr[j] = temp; j--; } System.out.println("第" + i + "步:" + ArrayUtils.toString(arr)); } return return_arr; } public static void main(String[] args) { int[] ints = insertSort(new int[]{5, 4, 3, 2, 1}); System.out.println(ArrayUtils.toString(ints)); }
结果:
第1步:{4,5,3,2,1} 第2步:{3,4,5,2,1} 第3步:{2,3,4,5,1} 第4步:{1,2,3,4,5}
参考:
数据结构与算法图解.6
Java常用算法手册4.4
插入排序(https://www.runoob.com/w3cnote/insertion-sort.html)
我的第一本算法书 2-4 插入排序