直接插入排序(straight insertion sort)的作法是:
每次从无序表中取出第一个元素,把它插入到有序表的合适位置,使有序表仍然有序。
第一趟比较前两个数,然后把第二个数按大小插入到有序表中; 第二趟把第三个数据与前两个数从后向前扫描,把第三个数按大小插入到有序表中;依次进行下去,进行了(n-1)趟扫描以后就完成了整个排序过程。
直接插入排序属于稳定的排序,时间复杂性为o(n^2),空间复杂度为o(1)。
直接插入排序是由两层嵌套循环组成的。外层循环标识并决定待比较的数值。内层循环为待比较数值确定其最终位置。直接插入排序是将待比较的数值与它的前一个数值进行比较,所以外层循环是从第二个数值开始的。当前一数值比待比较数值大的情况下继续循环比较,直到找到比待比较数值小的并将待比较数值置入其后一位置,结束该次循环。
值得注意的是,我们必需用一个存储空间来保存当前待比较的数值,因为当一趟比较完成时,我们要将待比较数值置入比它小的数值的后一位 插入排序类似玩牌时整理手中纸牌的过程。插入排序的基本方法是:每步将一个待排序的记录按其关字的大小插到前面已经排序的序列中的适当位置,直到全部记录插入完毕为止。
初始序列:
i=1 [46] 58 15 45 90 18 10 62
↓
i=2 [46 58] 15 45 90 18 10 62
┌――┘
↓
i=3 [15 46 58] 45 90 18 10 62
┌――┘
↓
i=4 [15 45 46 58] 90 18 10 62
↓
i=5 [15 45 46 58 90] 18 10 62
┌―――――┘
↓
i=6 [15 18 45 46 58 90] 10 62
┌――――――――┘
↓
i=7 [10 15 18 45 46 58 90] 62
┌―┘
↓
i=8 [10 15 18 45 46 58 62 90]
c/c++代码实现直接插入排序
for(i = 1; i < n; ++i)
{
int temp = a[i];
for (j = i; j > 0 && temp < a[j - 1]; --j)
{
a[j] = a[j - 1];
}
a[j] = temp;
}
直接插入排序是一种最简单的排序方法,它的基本思想是依次将每个记录插入到一个有序中去。就是说,第i(i>=1)遍整理时,a1,a2,...,ai-1已经是排好序的子序列;取出第i个元素ai,在已排好序的子序列为ai找到一个合适的位置,并将它插到该位置上。易知上述排序当i=1时实际上为空操作,故可直接从i=2开始。
为了便于控制循环结束,引入元素a[0],行时可以节省时间,直接插入排序的算法如下:
procedure straightsort(var a:list);
begin
for i:=2 to n do //从第二个记录起进行插入//
[ a[0]:=a[j];
j:=i-1;
while a[0].key<a[j].key do
[ a[j+1]:=a[j];
j:=j-1];
//将第j个记录赋值给第j+1个记录,直至关键字不大于待插入记录的关键字//
a[j+1]:=a[0]]//将第i个记录插入//
end;
算法中引进附加记录a[0]有两个作用:其一是进入查找循环之前,它保存了a[ i ]的值,使得不致于因记录的后移而丢失a[ i ]中的内容;其二是在while循环"监视"下变量j是否越界,一旦越界(即j<1),a[0]自动控制while循环的结束,从而避免了在while循环中每一次都要检测j是否越界(即省略了循环条件"j>=1")。因此我们把称为"监视哨",这种技巧,使得测试循环条件的时间大约减少一半,对于记录数较大的文件,节约的时间相当可观。希望读者能掌握这种技巧。
由此可见,直接插入排序算法简洁,易理解,容易实现。当序列中的记录“基本有序”或n值较小时,它是最佳的排序方法。但是,通常待排记录的数量n很大,此时直接插入排序就不适用了。
常用的插入排序有:直接插入排序、折半插入排序、表插入排序和希尔排序。
转载于:https://www.cnblogs.com/kangderui/archive/2010/01/01/1637376.html