手写算法:插入排序
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";
以上是关于手写算法:插入排序的主要内容,如果未能解决你的问题,请参考以下文章