Definition
又称为缩小增量排序,是对插入排序的一种改进(建立在插入排序对基本有序的排序表和数据量不大的排序表上较好的performance上):
- 取一个小于 n n n 的步长 d 1 d_{1} d1 ,把表中元素分为 d 1 d_{1} d1 份
- 对每一组进行插入排序
- 缩小步长 d 1 d_{1} d1 的值,重复上述过程,直到 d 1 = 1 d_{1}=1 d1=1 时,即此时对整个序列进行插入排序,而此时的序列已经基本有序(局部有序性),可以很快得到最终的结果
Implementation
这里我们使用的增量序列为: n i + 1 = n i n_{i+1}=n_{i} ni+1=ni,直到最后的增量为 1 1 1
void shellSort(ElementType* A, int n){
for(int d = 0; d >= 1; d = d / 2){
// using A[0] as temp
for(int i = d + 1; i < n; i++){
// check if insertion is needed
if(A[i] < A[i - d]){
A[0] = A[i];
int j = i - d;
// move all elements greater than A[i] back
for(;j > 0 && A[0] < A[j];j -= d){
A[j + d] = A[j];
}
// insert
A[j + d] = A[0];
}
}
}
}
Performance
关于希尔排序的性能:
- 空间效率:显然,这是一个就地算法,空间复杂度为 O ( 1 ) O(1) O(1)
- 时间效率:分析困难,约为 O ( n 1.3 ) O(n^{1.3}) O(n1.3) ,最坏情况下为 O ( n 2 ) O(n^{2}) O(n2),即退化为插入排序
- 稳定性:当同位数被划分到不同的子表中时,可能会改变相对次序,因此希尔排序是一个不稳定的排序算法
- 适用性:适用于顺序存储的线性表(因为需要跨步长,不适合适用需要顺序访问的链式存储)