直接插入排序:
它的本质仍然是对撞指针,只不过首指针固定在首位置不动,尾指针end依次--,让前end个数有序
想法:定义一个end变量=0,end从0++到n(数组长度)
(1)定义一个temp=a[end+1]:(又称岗哨)(反正理解为一个特殊的值即可)
(2)在升序的情况下:如果a[end]>temp:即a[end]>a[end+1]
那么我们就要使a[end+1]=a[end]:即后面一个数的值被前面一个数的值覆盖了
但是不用担心,我们已经用temp存储了a[end+1]的值
我们说过了:这个排序的想法是让前end个数有序
(3)所以作为尾指针,它要向左移动,即end--
接着重复(2)即可
如果遇到a[end]<a[end+1]的情况,我们就不需要end--了,break跳出循环
注意此时整个数列中并没有temp的值,
(4)我们需要将a[end]=temp,将temp还原到它的对应位置
#include<stdio.h>
void TestInsertsort();
void printarray(int *a, int n);
void Insertsort(int *a,int n);
void TestInsertsort()
{
int a[] = { 9,5,3,2,4,1,6,7,8,10 };
int n = sizeof(a) / sizeof(a[0]);
Insertsort(a, n);
printarray(a, n);
}
void Insertsort(int* a, int n)
{
for (int i = 0; i < n; i++)
{
int end = i;//尾指针
int temp = a[end + 1];//岗哨
while (end >= 0)
{
if (a[end] > temp)//如果前一个数比后一个数大,则前一个数的值覆盖后一个数的值
{
a[end + 1] = a[end];
end--;
}
else//反之,break,跳出循环
{
break;
}
}
a[end+1] = temp;//最后还原
}
}
void printarray(int* a, int n)
{
for (int i = 0; i < n; i++)
{
printf("%d ", a[i]);
}
}
int main()
{
TestInsertsort();
return 0;
}
时间复杂度:最坏情况:O(N^2) 最好情况:O(N) 平均:O(N^2)
希尔排序:
想要理解为什么有希尔排序,我们就得先理解透直接插入排序:
直接插入排序的最好情况:全是升序:时间复杂度仅为O(N)
因为根本没有交换的过程(都排好了,不需要交换了):外层只有一个for循环
最坏的情况:全是降序:时间复杂度为O(N^2)
因为每一个数,几乎都需要交换一个数组的长度
那么为了优化:我们是不是可以将数组先进行预处理?
也就是将数组先粗略排成类似有序(很重要!)
怎么做呢?:希尔这个大神找到了gap
gap是间隔,也就是说,它让间隔为gap的数组元素有序,比如这里的gap=3
将数组分为了三部分:
再将这三部分分别使用直接插入排序,因为数组此时很短,所以效率会很高
此时就完成了一次粗略的类似排序
这时我们将gap=gap/2——即gap=2
再对这两部分进行直接插入排序:由于是接近有序且短:所以效率会变高
接着gap=gap/2——即gap=1,由于此时已经非常接近有序,用直接插入排序即可完成
#include<stdio.h>
void ShellSort(int* a, int n);
void TestShellSort();
void printarray(int* a, int n);
void TestShellSort()
{
int a[] = { 9,7,5,3,1,2,4,6,8,10 };
int n = sizeof(a) / sizeof(a[0]);
ShellSort(a, n);
printarray(a, n);
}
void ShellSort(int* a, int n)
{
int gap = n;
while (gap > 1)
{
gap = gap / 2;
for (int i = 0; i < n - gap; i++)
{
int end = i;
int temp = a[end + gap];
while (end >= 0)
{
if (a[end] > temp)
{
a[end + gap] = a[end];
end = end - gap;
}
else
{
break;
}
}
a[end + gap] = temp;
}
}
}
void printarray(int* a, int n)
{
for (int i = 0; i < n; i++)
{
printf("%d ", a[i]);
}
}
int main()
{
TestShellSort();
return 0;
}
发现了吗?
希尔排序本质上就只是将直接插入排序的间隔1改为了gap
并且让gap=gap/2,并在最外层加上了gap的循环
看似一个很简单的想法:在测试一万个数据的时候
希尔排序的运行时间是直接插入排序的0.01倍: