插入类排序
- 直接插入排序
- 直接插入排序:首先以一个元素为有序的序列,然后将后面的元素依次插入到有序的序列中合适的位置直到所有元素都插入有序序列。
- 时间复杂度为O(n)
- 直接插入排序是稳定性是稳定的。
void InsertSort(SqList *L)
{
int i,j;
for(i=2;i<=(*L).length;++i)
if LT((*L).r[i].key,(*L).r[i-1].key)
{
(*L).r[0]=(*L).r[i];
for(j=i-1;LT((*L).r[0].key,(*L).r[j].key);--j)
(*L).r[j+1]=(*L).r[j];
(*L).r[j+1]=(*L).r[0];
}
}
- 折半插入排序
- 折半插入排序将比较和移动这两个操作分离出来,也就是先利用折半查找找到插入的位置,然后一次性移动元素,再插入该元素。
- 折半插入排序的时间复杂度为O(n^2)
- 稳定性:和直接插入排序稳定性相同,是稳定的。
void BInsertSort(SqList *L)
{
int i,j,m,low,high;
for(i=2;i<=(*L).length;++i)
{
(*L).r[0]=(*L).r[i];
low=1;
high=i-1;
while(low<=high)
{
m=(low+high)/2;
if LT((*L).r[0].key,(*L).r[m].key)
high=m-1;
else
low=m+1;
}
for(j=i-1;j>=high+1;--j)
(*L).r[j+1]=(*L).r[j];
(*L).r[high+1]=(*L).r[0];
}
}
- 希尔排序
- 希尔排序的基本思想:希尔排序本质上还是插入排序,只不过是把待排序序列分成几个子序列,再分别对这几个子序列进行直接插入排序。
- ①先以增量5来分割序列,也就是下标为0,5,10,15…的关键字分成一组,下标为1,6,11,16…分成一组,然后对这些组分别进行直接插入排序,这就完成了一轮希尔排序。
- ②缩小增量(d1=n/2,di+1= [di/2],比如10个数据序列,第一次增量d1=10/2=5,第二次增量d2= [d1/2]= [5/2]=2,并且最后一个增量等于1),所以第二轮以增量为2进行类似的排序过程。
- ③接下来的第三轮,第四轮…都是类似的过程,直到最后一轮以增量为1。此时就是前面所说的直接插入排序。
- 概要:
- 时间复杂度:… 希尔排序的时间复杂度约为O(n^1.3) 在最坏情况下希尔排序的时间复杂度为O(n^2)
- 空间复杂度:希尔排序的空间复杂度为O(1)
- 稳定性:不稳定,由于不同的增量可能就会把相等的关键字划分到两个直接插入排序中进行排序, 可能就会造成相对顺序变化。
void Shell_Sort(int *list,int count)
{
int i,j;
int temp;
int increment = count;
do
{
increment = increment/2;
for(i = increment;i<count;i++)
{
if(list[i]<list[i-increment])
{
temp = list[i];
for(j=i-increment;j>=0&&list[j]>temp;j-=increment)
{
list[j+increment] = list[j];
}
list[j+increment] = temp;
}
}
}while(increment>1);
}