直接插入排序的思想是:将一个待排序的数字按照指定的排序规则,插入到一个前面已经排好序的的子序列中, 从而形成一个新的子序列,等待下一个数字的插入, 直至所有数字排序结束。
假设有数组a[0 … n – 1], 排序流程为:
- a[0]位第一个有序子序列, a[1 … n -1]为无序序列,令i = 1。
- 将a[i]插入到指定位置, 插入后形成a[0 … i] 有序子序列。
- 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