直接插入排序非常容易理解,只需要在【0,end】这个有序区间内把end+1按照大小比较插入到相应位置即可。其中直接插入排序复杂度为O(N^2),而希尔排序接近O(N^1.3),和O(N)差不太多。
void InsertSort(int* a, int n)
{
for (int i = 0;i < n - 1;++i)
{
int end = i;
int tmp = a[end + 1];
while (end >= 0)
{
if (a[end] > tmp)
{
a[end + 1] = a[end];
end--;
}
else
{
break;
}
}
a[end + 1] = tmp;
}
}
这里的参数是首地址,n代表数组内的个数。首先需要理解的是先定义一个tmp来保存end+1的值(在后续的后移过程中会被覆盖),下面进行while 循环,如果end>=0则进行操作。在a[end]>tmp时需要后移同时需要对end--。剩下就是在合适的位置放入即可,这个放入数值需要注意2点。
第一点是在while结束时,也就是比如说要插入的值是最小的,那么end需要一直减,最后减为-1跳出了while循环。
第二点是找到了合适的位置(找到了应该插入的位置)但因为end--的作用,使得在插入时应该是end+1的位置赋值。
这两种情况对应的插入都是end+1位置赋值,所以在while循环中使用了break来跳出。
剩下需要思考的就是end的数值了,这里是利用for循环进行遍历,从0开始,到达的位置是n-2!这是因为在while循环操作中,虽然有n 个数值,但是最后一个数值对应的下标是n-1,只有在end为n-2时,进行插入赋值的end+1才到达n-1,这才不会出现数组越界的问题。
希尔排序是在直接插入排序的基础上进行的,其主要思想就是先进行分块,每一块排好序,最终再实现全排序。
void ShellSort(int* a, int n)
{
int gap = n;
while (gap > 0)
{
gap = gap / 2;
for (int i = 0;i < n - gap;i++)
{
int end = i;
int tmp = a[end + gap];
while (end >= 0)
{
if (a[end] > tmp)
{
a[end + gap] = a[end];
end -= gap;
}
else
{
break;
}
}
a[end + gap] = tmp;
}
}
}
里面的内容还是直接插入排序的,只不过将1替换成了gap而已。使用gap来分为具体的块数来进行跳级操作。这里需要确定一下gap的数值,可以根据数组里面数值的个数来确定,通过对n 的除法(除以2可以得到gap为1的情况,此时也就是直接插入排序了)以及while循环来进行gap的变更。
下面是测试用例和全代码
#include<iostream>
using namespace std;
void InsertSort(int* a, int n)
{
for (int i = 0;i < n - 1;++i)
{
int end = i;
int tmp = a[end + 1];
while (end >= 0)
{
if (a[end] > tmp)
{
a[end + 1] = a[end];
end--;
}
else
{
break;
}
}
a[end + 1] = tmp;
}
}
void ShellSort(int* a, int n)
{
int gap = n;
while (gap > 0)
{
gap = gap / 2;
for (int i = 0;i < n - gap;i++)
{
int end = i;
int tmp = a[end + gap];
while (end >= 0)
{
if (a[end] > tmp)
{
a[end + gap] = a[end];
end -= gap;
}
else
{
break;
}
}
a[end + gap] = tmp;
}
}
}
void PrintArray(int* a, int n)
{
for (int i = 0;i < n;i++)
cout << a[i] << " ";
}
int main()
{
int a[] = { 3,5,2,7,8,6,1,9,4,0 };
InsertSort(a, sizeof(a) / sizeof(int));
PrintArray(a, sizeof(a) / sizeof(int));
cout << "\n";
cout << "The Another Sort:" << endl;
ShellSort(a, sizeof(a) / sizeof(int));
PrintArray(a, sizeof(a) / sizeof(int));
return 0;
}
下面是输出结果:
![](https://i-blog.csdnimg.cn/blog_migrate/282f1138df6179228437dafbacbb0271.png)