插入排序是一种直观的排序方法,基本思想是每次把一次待排序的记录插入到已经排好序的子序列中去,知道全部的元素都插入到子序列中。由插入的思想的不一致可以将插入排序分为两种重要的排序算法:直接插入排序和希尔排序。
直接插入排序
直接插入排序的时间复杂度是O(N*N),空间复杂度是O(1),因为直接插入排序每次是在有序的子序列中从后向前一次查找插入的位置,并且可能会后移,因此出现在相同位置的元素不会出现相对位置的变化,因此是一个稳定的排序方法。
直接插入排序的算法如下:
void insert_sort(int A[],int n)
{
int i,j,temp;
for(int i=1;i<n;++i)
{
if(A[i]<A[i-1])
{
temp=A[i];
for(j=i-1;j>0&&temp>A[j];--j)
{
A[j+1]=A[j];
}
A[j+1]=temp;
}
}
}
希尔排序
希尔排序的基本思想是:先将待排序的表分割成几部分,取一个数d1=len/2把无序数分成d1组,所有相隔d1的数为一组,然后在每一组内进行直接插入排序;然后把数据整合后再取d2=d1/2,再进行上述操作,直到di=1为止,进行一次插入操作就可以实现最终的排序。
希尔排序的空间复杂度是O(1),时间复杂度依赖于增量序列的函数,计算比较复杂,最差的情况是O(N*N),希尔排序是不稳定的排序算法,因为在分组的时候可能会改变相同元素的相对位置。
例如有一个数组[ 13 14 94 33 82 25 59 94. 65 23 45 27 73 25 39 10 ],如果我们以步长为d1=len/2=5开始进行排序,我们可以通过将这列表放在有5列的表中来更好地描述算法,这样他们就应该看起来是这样:
13 14 94 33 82
25 59 94. 65 23
45 27 73 25 39
10
为了区分,我把第二个94用94.来标识,每一列为一组,进行插入排序后结果如下:
10 14 73 25 23
13 27 94 33 39
25 59 94. 65 82
45
现在的数组应该是[10 14 73 25 23 13 27 94 33 39 25 59 94. 65 82 45],然后取d2=d1/2=2.5,我们取3,然后跟第一步一样的操作:
10 14 73
25 23 13
27 94 33
39 25 59
94. 65 82
45
进行插入排序后结果如下:
10 14 13
25 23 33
27 25 59
39 65 73
45 94 82
94.
最后以1步长进行排序(此时就是简单的插入排序了)。
希尔排序的算法如下:
void shell_sort(int A[],int len)
{
int i,j,dk,temp;
for(dk=len/2;dk>=1;dk=dk/2)
{
for(i=dk;i<len;++i)
{
if(A[i]<A[i-dk])
{
temp=A[i];
for(j=i-1;j>0&&temp>A[j];j=j-dk)
{
A[j+dk]=A[j];
}
}
A[j+dk]=temp;
}
}
}