通过学习简单排序我们可以观察到它们的一个共同点就是每次都是比较相邻的两个元素,并对其进行操作。这样每次解决的都是一个逆序对(数组中大小逆序的两个数),若 其平均时间复杂度为N^2。
而我们要优化这个排序方法,则需要通过一次操作来解决多个逆序对。最直接的操作便是每次对相隔较远的元素进行操作,这样便可以实现一次操作解决多个逆序对。
- 排序思路:先通过对相隔较远的元素进行插入排序,再逐渐缩小间隔元素的范围,最后缩小到1即可
- 补充:对于元素间隔的大小会直接影响到算法的时间复杂度。当每次比较的间隔为倍数时,对其时间复杂度的优化最差。
- 优点:当需要排序的数目较大时,通过希尔排序可以更快的进行排序
- 缺点:当需要排序的数目较小时,可能会出现希尔排序排序的时间复杂度更高。除此以外,因为希尔排序是对间隔较远的元素进行排序,所以会导致无法确保稳定性(两个相同的数无法按照原来的顺序排序
void xiersort(int* a, int n)//我们这里暂且不考虑优化d的取值
{
int tmp;
int d=3;
do//若d=1还要做一遍
{
for (int i=d;i<2*d ;i++ )//对间隔范围内的每个元素遍历
//这里i=d和i<2*d是为了防止下面访问a[j-d]时越界
{
for (int k = i; k < n; k += d)
{
for (int j = k; j >= 0; j -= d)
{
if (a[j - d] > a[j])
{
tmp = a[j];
a[j] = a[j - d];
a[j - d] = tmp;
}
else break;
}
}
}
d = d / 2 ;} while (d !=0);
return;
}
因为d的取值直接影响了循环的次数,而我们发现但d的取值每次以倍数减少时,它的时间复杂度还是n^2,所以对于d的取值我们认为若能采用sedgewick增量序列,便能使其时间复杂度降到最低。