面试必备:经典算法动画解析之插入排序

哈喽,我是程序员大鹏java

前面咱们介绍了冒泡排序和选择排序,今天咱们来看一下简单排序中的插入排序。程序员

打过扑克的都知道,在抓牌的时候,咱们不会等抓完全部的牌再用冒泡或者选择排序再理牌。通常是拿到一张牌就放到手里,抓到第二张牌的时候,再跟手里面已经有的牌进行比较,插到合适的位置,而后抓第三张牌,再与手里面的两张牌进行比较,而后再把牌插到合适的位置。这种一边抓牌,一边理牌的方式,咱们就称之为直接插入排序算法

插入排序思想

插入排序是一种从序列左端开始依次对数据进行排序的算法。在排序过程当中,索引左侧的数据陆续归位,而右侧留下的就是尚未被排序的数据。数组

插入排序的思路就是从右侧的未排序区域内取出一个数据作为待排序数据,而后将它插入到已排序区域内合适的位置上。一直到未排序清空。动画

排序原理

  1. 将待排序的值临时移除并保存在一个临时变量中。
  2. 将空隙左侧的每个值一次与临时变量比较,若是左边的数大于临时变量的值,则该值右移一格,若是左边的数字更小,就不须要继续比较,本轮操做到此结束。最终左侧会有一个位置的空隙。
  3. 将临时移走的数据插入到当前空隙。
  4. 重复前面三步,直到全部元素均排序完毕。

插入排序动画

插入排序代码

public static void insertSort(int[] arr) {
//    默认第一个元素是有序的,因此索引不是从0开始,从1开始
    for (int i = 1; i < arr.length; i++) {
      int temp = arr[i];//待排序元素赋值给临时变量
      int position = i;//记录当前比较的索引
      while (position > 0 && arr[position - 1] > temp) {
        arr[position] = arr[position - 1];
        position--;
      }
      arr[position] = temp;//插入到正确的位置
    }
  }

让咱们来一行一行地分析一下代码:code

for (int i = 1; i < arr.length; i++) {

在上面代码是外层循环,在i的左侧是已排序数据,起始的i等于1,是默认第0个数据已是排序数据。blog

int temp = arr[i];//待排序元素赋值给临时变量
int position = i;//记录当前比较的索引

每一轮开始的时候,position是待排序数据的索引,temp的值就是本轮待排序的数据,第一轮的待排序索引为1,第二轮是2,第三轮是3,依次类推,一直到最后一轮。排序

while (position > 0 && arr[position - 1] > temp) {

开始内层的循环,若是知足position大于0,而且当前位置的数据与temp比较,若是大于temp数据,则进入到循环里面。索引

arr[position] = arr[position - 1];
        position--;

数据平移一个位置,将position作为空隙。it

arr[position] = temp;

将待排序的数据temp插入到空隙的位置。

排序步骤分析

下面咱们应用插入排序对数组[4,2,3,5,1]进行排序,来看每一步的操做。

第0轮

这一轮实际上是没有的,咱们默认就是第一个位置的值是有序的。

第一轮

将索引值为1的值2暂时移除,保存在临时变量temp中,此时temp为2。

第1步:比较索引0的值4与temp中的

第2步:由于4大于2,因此将4右移。

空隙移到了数组最左端,没有其余值能够比较了。

第3步:将temp插回到数组中,结束第一轮。

第二轮

将索引为2的值3暂时移除,保存到临时变量temp中,此时temp为3。

第4步:比较4与temp

第5步:由于4比3大,因此将4右移

第6步:比较2与temp

第7步:由于2比3小,因此无须2平移,平移结束

第8步:将temp插回到数组的空隙中,结束第二轮。

第三轮

将索引为3的值5暂时移除,保存在临时变量temp中,此时temp的值为5.

第9步:比较4与temp

第10步:由于4比5小,,因此无须4平移,平移结束

第四轮

将索引为4的值1暂时移除,保存在临时变量temp中,此时temp的值为1.

第11步:比较5与temp

第12步:由于5比1大,因此将5右移

第13步:比较4与temp

第14步:由于4比1大,因此将4右移

第15步:比较3与temp

第16步:由于3比1大,因此将3右移

第17步:比较2与temp

第18步:由于2比1大,因此将2右移

空隙移到了数组最左端,没有其余值能够比较了。

第19步:将temp的值1插回到数组的空隙中。

到如今为止,整个数组已经排好序了。

选择排序复杂度分析

在插入排序中,须要将取出的数据与其左边的数字进行比较。就跟前面讲的步骤一 样,若是左边的数字更小,就不须要继续比较,本轮操做到此结束,天然也不须要交换 数字的位置。

然而,若是取出的数字比左边已归位的数字都要小,就必须不停地比较大小,交换数字,直到它到达整个序列的最左边为止。具体来讲,就是第 k 轮须要比较k-1 次。因 此,在最糟糕的状况下,第2 轮须要操做1 次,第 3 轮操做2 次……第n 轮操做n-1 次,因此时间复杂度和冒泡排序的同样,都为 O(n^2)。

和前面讲的排序算法同样,输入数据按从大到小的顺序排列时就是最糟糕的状况。

相关文章
相关标签/搜索