java实现插入排序

1、基本思想

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

插入排序很是相似于整扑克牌。编程

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

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

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

2、算法描述

假定n是数组的长度,spa

首先假设第一个元素被放置在正确的位置上,这样仅需从1-n-1范围内对剩余元素进行排序。对于每次遍历,从0-i-1范围内的元素已经被排好序,code

每次遍历的任务是:经过扫描前面已排序的子列表,将位置i处的元素定位到从0到i的子列表以内的正确的位置上。blog

将arr[i]复制为一个名为target的临时元素。排序

向下扫描列表,比较这个目标值target与arr[i-1]、arr[i-2]的大小,依次类推。get

这个比较过程在小于或等于目标值的第一个元素(arr[j])处中止,或者在列表开始处中止(j=0)。

在arr[i]小于前面任何已排序元素时,后一个条件(j=0)为真,

所以,这个元素会占用新排序子列表的第一个位置。

在扫描期间,大于目标值target的每一个元素都会向右滑动一个位置(arr[j]=arr[j-1])。

一旦肯定了正确位置j,

目标值target(即原始的arr[i])就会被复制到这个位置。

与选择排序不一样的是,插入排序将数据向右滑动,而且不会执行交换。

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--;
        }
 
        arr[j] = target;
    }
}

 

4、效率分析

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

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

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

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

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

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

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

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

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

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

相关文章
相关标签/搜索