每日一个小算法(二)-插入排序

来源:互联网 发布:cad迷你看图 mac 编辑:程序博客网 时间:2024/05/01 10:07

插入排序

1.通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应的位置并插入。

image

插入排序非常类似于整扑克牌。

在开始摸牌时,左手是空的,牌面朝下放在桌上。接着,一次从桌上摸起一张牌,并将它插入到左手一把牌中的正确位置上。为了找到这张牌的正确位置,要将它与手中已有的牌从右到左地进行比较。无论什么时候,左手中的牌都是排好序的。

如果输入数组已经是排好序的话,插入排序出现最佳情况,其运行时间是输入规模的一个线性函数。如果输入数组是逆序排列的,将出现最坏情况。平均情况与最坏情况一样,其时间代价是Θ(n2)。

也许你没有意识到,但其实你的思考过程是这样的:现在抓到一张7,把它和手里的牌从右到左依次比较,7比10小,应该再往左插,7比5大,好,就插这里。为什么比较了10和5就可以确定7的位置?为什么不用再比较左边的4和2呢?因为这里有一个重要的前提:手里的牌已经是排好序的。现在我插了7之后,手里的牌仍然是排好序的,下次再抓到的牌还可以用这个方法插入。编程对一个数组进行插入排序也是同样道理,但和插入扑克牌有一点不同,不可能在两个相邻的存储单元之间再插入一个单元,因此要将插入点之后的数据依次往后移动一个单元。

2.插入排序说白了,就是一种反着排序的思想。默认第一个数据已经排好,那么拿第二个数据和他去做对比,如果比第一个数小交换位置。本次循环结束。再拿第三个数据和第二个对比,如果比第二个小,交换位置。再与第一个比,小就交换位置,否则循环结束。以此类推。代码如下,注释详细说。自己懒得敲了。注释说详细点吧。

3.示例代码

public static void InsertSort(int[] arr){    int i, j;     int n = arr.Length; // 数组长度    int target;  //暂存量,暂时记住拿到数值大小     //假定第一个元素被放到了正确的位置上    //这样,仅需遍历1 - n-1    for (i = 1; i < n; i++)  //循环拿到数组中的数的下标    {        j = i; //记录拿到的的数的下标        target = arr[i]; //记录拿到的数的值         while (j > 0 && target < arr[j - 1])//如果拿到的数值比前面的值小。        {            arr[j] = arr[j - 1]; //将前面的,大的数往后移一位。            j--;  //此数值的下标减一,下次再走while循环时与前面的值比较。        }         arr[j] = target; //循环结束说明此时 j 的下标值所对应的数找到了正确位置。比前面的小。比后面的大。    }}

4.稳定
空间复杂度O(1)
时间复杂度O(n2)
最差情况:反序,需要移动n*(n-1)/2个元素
最好情况:正序,不需要移动元素

数组在已排序或者是“近似排序”时,插入排序效率的最好情况运行时间为O(n)

插入排序最坏情况运行时间和平均情况运行时间都为O(n2)

通常,插入排序呈现出二次排序算法中的最佳性能。

对于具有较少元素(如n<=15)的列表来说,二次算法十分有效。

在列表已被排序时,插入排序是线性算法O(n)。

在列表“近似排序”时,插入排序仍然是线性算法。

在列表的许多元素已位于正确的位置上时,就会出现“近似排序”的条件。

通过使用O(nlog2n)效率的算法(如快速排序)对数组进行部分排序,

然后再进行选择排序,某些高级的排序算法就是这样实现的。


参考微博:http://www.cnblogs.com/fanyong/archive/2012/03/23/2413553.html




0 0
原创粉丝点击