直接插入排序
- 方法:将一部分排好序,然后将之后的关键字插入排好序的有序序列中。
- 例子:12,15,9,20,6,31,24 -
个人算法及实现
一次插入排序:将最后一个数num[j],插入之前存在的序列里
- 从有序序列的最后一位num[i]开始向前遍历
- 如果(num[j] < num[i]) && (num[j] >= num[i - 1])
- 或者(num[j] < num[i]) && (i == 0)
- 则将num[j]保存到temp,并此位开始向后移动各个元素。
`int j = x - 1;//x为当前的序列长度,j为数组的最后一个元素
for (int i = j - 1; i >= 0; i–)
{
if ((num[j] < num[i]) && (num[j] >= num[i - 1]) || (num[j] < num[i]) && (i == 0))
{
int temp = num[j];
for (int t = j; t >= i + 1; t–)
{
num[t] = num[t - 1];}
num[i] = temp;
}
}`- 然后将序列长度从一开始执行上面的代码
for (int x = 1; x < n+1; x++){上面代码 }
- -
网上和教材的代码中,都用数组的第一个元素作为“哨兵”,输入的序列第一位要空着,这我觉得有些不必要。。。难道每次输入数字序列都要第一位空着?欢迎交流指点。
- 希尔排序
- 方法
- 设一个增量,一般取gap = n/2(n为待排序序列长度)
- 找出隔着gap的数进行排序,用直接插入排序法
- 不断缩小gap,直到gap= 0(也就意味着相邻的两个元素都是有序的了,那么整个序列就是有序的了)
- 例子:59,20,17,36,98,14,23,83,13,28
- gap= 5 比较59 14, 20 23, 17 83, 36 13,98 28
- gap = 2 比较 {14 17 28 23 36 }{20 13 59 83 98}
- 如此继续
- 算法及实现
- 一次插入排序:比如当gap=2时候,将{14 17 28 23 36 }先排好序
- 方法
//一次直接插入排序
for (int j = gap+a; j < n;j = j+gap)
{
for (int i = j - gap; i >= 0;i = i-gap)
{
if (((num[j]<num[i]) && (num[j]>num[i - 1])) || ((num[j]<num[i]) && (i-gap)<0))
{
int temp = num[j];
for (int t = j; t>=i + gap;t = t-gap)
{
num[t] = num[t - gap];
}
num[i] = temp;
}
}
}
- 将这个gap的各个分组都排序`//一个gap执行过程
for (int a = 0; a < gap;a++)
{上面代码}`
- gap不断缩小`for(int gap = n / 2; gap>=1; gap = gap / 2 )
{上面代码叠加}`
- 直接插入排序和希尔排序的复杂度
- 直接插入
- 最坏时间复杂度:O(n*n)逆序情况,比较还要移动
- 最好时间复杂度:O(n)只和有序序列的最后一个元素比较
- 平均时间复杂度:O(n*n)
- 空间复杂度:O(1)
- 稳定性:稳定(相同的数字顺序是否改变)
- 希尔排序(计算比较复杂,是所取增量的函数)
- 最坏时间复杂度:O(n*n)
- 平均时间复杂度:O(n^1.3)
- 空间复杂度:O(1)
- 稳定性:不稳定
- 直接插入