手写算法:插入排序

Posted 骞牧学编程

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了手写算法:插入排序相关的知识,希望对你有一定的参考价值。



什么是插入排序

上一篇讲解冒泡排序的文章我们曾以玩扑克举例,实际上,玩扑克时的排序是典型的插入排序。你可以回忆一下你抓牌时的场景,开始游戏时,轮流抓牌,轮到你抓牌时,你右手抓牌,然后放到左手中。当抓第一张牌时,自然没有什么好说的,直接放到左手中即可。当你抓第二张牌时,就会比较你左手中的牌,找到一个合适的位置,使右边的牌比它小,左边的牌比它大,然后将抓到的牌插入到这个合适的位置。这个过程持续到桌面上的牌抓完为止。这就是典型的插入排序了。

简单理解插入排序

如果有一个整数数列,和上次一样,是:96,35,4,26,79,16,请把它当做是桌面上要抓取的牌,当然,比较特殊的是此时只有你一个玩家。重新申请一个等长的空白整数数列,当你抓到第一个数字96时,没有什么特别的,直接把它塞到空白数列中即可。当你抓到第二个数字35时,因为35<96,需要将96往左移一个位置,将35查到96的右边。这样依次插入,知道插入最后一个数字16,新数列就变成有序的了。这就是插入排序了,是不是非常简单。

原地插入排序

插入排序不是一个高效的排序,就是说时间复 杂度很高,上面那个算法虽然容易理解,但是还需要开辟新的内存空间,又增加了空间复杂度,一般我们不会这么设计算法,对于插入排序,我们一般在原数列上直接排序,叫做“原地插入排序”

手写算法:插入排序


手写算法:插入排序


那么,怎样实现原地插入排序呢?现在看我们的图,可以把原数列划分成两个数列,左边是有序数列,右边是待排序数列,因为只有一个元素是,是天然有序的,那么我们可以认为第一个数字96是一个有序数列,而右边的35,4,26,79,16是待排序数列,我们要做的事就是把右边的数字逐个插入到左边的有序数列中。右边的待排序数列就像桌面上的牌,而左边的有序数列就像是你手上的牌。

  • 从第一个数字35开始比较,35<96,所以96要后移,给35腾出位置,96往后移会覆盖原来的35,所以35要提前保存好,插入到96原来的位置,此时有序数列变成35,96,待排序数列变成4,26,79,16。

  • 现在要把4插入到有序数列35,96中,和(1)类似,从后往前比较,先提前将4保存到临时变量,因为如果发生后移会覆盖4,4<96,96后移,4<35,35后移,最后将4插入到第一个空位中。此时有序数列变成4,35,96,待排序数列变成26,79,16。

  • 类似的,把26插入到有序数列中,有序数列变成4,26,35,96,待排序数列变成79,16

  • 类似的,插入79,有序数列变成4,26,35,79,96,待排序数列变成16

  • 最后将数字16插入到有序数列,变成有序数列4,16,26,35,79,96

图中,用竖线区分有序数列和待排序数列,为了表示位置的移动,标出的横线,数字用括号括起来了。

程序实现

最后直接上程序:

int a[6] = { 96,35,4,26,79,16 };
   int tmp = 0;
   int i, j = 0;

   for (i = 1; i < 6; i++)
  {
       tmp = a[i];
       for ( j = i-1; j >=0; j--)
      {
           if (tmp < a[j])
          {
               a[j+1] = a[j];
          }
           else
          {
               break;
          }
      }
       a[j + 1] = tmp;
  }

   std::cout << "after sort:\n";
   for (int i = 0; i < 6; i++)
  {
       std::cout << a[i] << "\t";
  }
   std::cout << "\n";









以上是关于手写算法:插入排序的主要内容,如果未能解决你的问题,请参考以下文章

手写算法:插入排序

算法(插入排序----手写5种方法)

请用Python手写实现插入排序

面试官:手写一个希尔排序,并对其改进

面试必备用Python手写十大经典排序算法

面试官:手写一个插入排序,并对其改进