1. 程式人生 > >[閉目洞察算法系列之二]插入排序三種實現

[閉目洞察算法系列之二]插入排序三種實現

直接插入排序的思想是:將一個待排序的數字按照指定的排序規則,插入到一個前面已經排好序的的子序列中, 從而形成一個新的子序列,等待下一個數字的插入, 直至所有數字排序結束。

假設有陣列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