直接插入排序
思路:
将未排序的元素逐个插入到已排序的元素中,使其保持有序:
假设前i个元素有序(初始时默认第一个元素一定是有序的)
而后n-i个元素无序,那么从第n-i个元素开始逐个将无序元素插入到有序元素当中,并保持有序元素集仍保持有序,从而使有序元素集不断增加,使无序元素集不断减少,直到全部元素都保持有序为止。
#include <stdio.h>
#include <stdlib.h>
//插入排序
void InsertionSort(int array[],int length)//length为数组长度
{
int temp;
int i,j,k;
for(i=1;i<=length-1;i++)//将待排序的length-1个元素插入到有序的位置
{
temp=array[i];
for(j=i;j>0&&temp<array[j-1];j--)
{
array[j]=array[j-1];
}
array[j]=temp;
}
}
//主函数调用插入排序
main()
{
int i,j,k;
int array[6]={2,5,1,3,6,4};
InsertionSort(array,6);
for(i=0;i<6;i++)
{
printf("%d ",array[i]);
}
}
稳定性:稳定排序
时间复杂度分析:
外层必然有一个长度为n的循环
此循环中嵌套一个循环
嵌套的循环每次最小为0,最大为i即当前外层循环次数
最坏时间复杂度为:
1+2+3+…+n-1 = n(n-1)/2
T(n)=O(n^2)
希尔排序
希尔排序是对直接插入排序的改进,因为在直接插入排序中,当待排序数列有序度越高时,直接插入排序的时间复杂度越小。
所以基于这样的一个事实,希尔排序的思路是先将原数组按一定间距分成多个子数组,对每一个子数组进行直接插入排序。之后再缩小该间距进行下一次排序,每一次排序后整体数组的有序性都将有所提高,直到当该间距缩减为1时对数组整体进行最后一次直接插入排序,此时待排序数组的有序性已经比较高了,所以最后一次直接插入排序的时间复杂度将大大减小。
图中可以看到在最终排序结果里,两个相同元素4的前后位置发生了交换,所以希尔排序是一种不稳定排序。
#include <stdio.h>
#include <stdlib.h>
//希尔排序
ShellSort(int array[],int n)
{
int i,j,k,gap,temp;
for(gap=n/2;gap>0;gap/=2)
{
//直接插入排序
//-----------------------
for(i=gap;i<n;i++)//从gap位置开始将第i个数插入到合适的位置
{
//因为后面要交换这个数的位置,所以先将该数暂存起来
temp=array[i];
//将这个数与其分组中前面的数逐个比较,如果该数小于前面的数,则交换它和组内前一个数的位置,否则或遍历到gap位置之前则结束本次插入
for(j=i;j>=gap&&temp<array[j-gap];j-=gap)
{
array[j]=array[j-gap];
}
//将之前要插入的数插入到最终位置
array[j]=temp;
}
//-----------------------
}
}
main()
{
int array[10]={4,2,7,1,0,6,5,8,9,3};
ShellSort(array,10);
int i;
for(i=0;i<10;i++)
{
printf("%d ",array[i]);
}
}
稳定性: 不稳定排序
时间复杂度分析:
最坏时间复杂度:O(n^2)
n在特定范围内时:O(n^1.3)