[闭目洞察算法系列之二]插入排序三种实现

直接插入排序的思想是:将一个待排序的数字按照指定的排序规则,插入到一个前面已经排好序的的子序列中, 从而形成一个新的子序列,等待下一个数字的插入, 直至所有数字排序结束。



假设有数组a[0 … n – 1], 排序流程为:

  1. a[0]位第一个有序子序列, a[1 … n -1]为无序序列,令i = 1。
  2. 将a[i]插入到指定位置, 插入后形成a[0 … i] 有序子序列。
  3. i++, 重复步骤2, 直至整个数组有序, 即i == n -1

根据上述思路, 下面写出代码(从小到大排序),

void InsertSortA(int *array, int len)
{
    if (array == nullptr || len < 0)
    {
        return;
    }
    
    int curr,before,k;
    
    for (int curr = 1; curr < len; ++curr) //遍历比较 array[1]到 array[len -1]
    {
        for (before = curr - 1; before >=0; before--) //遍历比较待插数据与有序子序列中的元素,寻找比array[curr]小的元素(左面比右面小即停止)
        {
            if (array[before] < array[curr])
            {
                break; 
            }
        }
        
        if (before != curr -1)
        {
            //遍历之后发现before未变化,说明array[curr]比子序列最后一个元素都大,那么当前curr位置就是该插入的位置,比较下一个元素array[curr+1]即可
            //如果发现变化了,就说明中间有一个合适的位置,此时就需要将那个位置至子序列末尾的元素全部后移一位,从而将array[curr]插到该位置。
            int tmp = array[curr];
            for (k = curr - 1; k > before; k--)
            {
                array[k +1] = array[k];
            }
            array[k +1] = tmp;
        }
    }
}

上述代码有些囉嗦, 可以将搜索目标位置与数据后移两部分合并,即每次先比较array[i]和array[i -1], 若array[i] >= array[i -1], 说明当前元素大于或等于前面子序列中任意元素,则直接跳过,比较下一个元素即可。反之,则进入后移流程: j=i – 1, tmp = array[i], 然后一边向后移动数据,一边向前搜索位置,直至array[j] < tmp, array[j+1] = tmp

void InsertSortB(int *array, int len)
{
    if (array == nullptr || len < 0)
    {
        return;
    }
    for (int curr = 1; curr < len; ++curr)
    {
        if (array[curr] < array[curr-1])
        {
            int tmp = array[curr];
            for (before = curr -1; before >=0 && array[before] > tmp; before--)
            {
                array[before+1] = arry[before];
            }
            
            array[before+1] = tmp;
        }
    }
}

第三种实现的思想是: 将array[j]插入到array[0 … j-1]步骤进行改写, 使用数据交换代替数据整体后移。即如果array[j]的前一个数据array[j-1] > array[j], 那么就将array[j-1]和array[j]交换,然后j–, 直至array[j-1] <= array[j], 从而实现将数据插入效果

void insertSortC(int *array, int len)
{
	if (array == nullptr || len < 0)
	{
		return;
	}
	for (int curr = 1; curr < len; ++curr)
	{
		for (int before = curr -1; before >=0 && array[before] > array[curr]; before--)
		{
			swap(before, before + 1);
		}
	}
}

void swap(int &a, int &b)
{
	int tmp = a;
	a = b;
	b = tmp;
}

参考链接: http://blog.csdn.net/morewindows/article/details/6665714

点赞