下面是一个比较标准的希尔排序(Shell Sort)的实现,它使用了逐渐减小的间隔(gap)来重新排列数组,直到间隔为1,此时算法退化为普通的插入排序,但此时数组已经接近有序,因此效率较高。
void ShellSort(int arr[], int n)
{
int gap;
for (gap = n / 2; gap > 0; gap /= 2) // 从间隔gap开始,对每个子列表进行插入排序
{
for (int i = gap; i < n; i++)
{
int temp = arr[i]; 如果前面的元素大于temp,则将其向后移动gap位
int j;
for (j = i; j >= gap && arr[j - gap] > temp; j -= gap)
{
arr[j] = arr[j - gap]; // 注意:这里不需要担心j-gap会越界,因为外层循环保证了j >= gap
}
arr[j] = temp; 当找到合适的位置时,将temp插入到该位置
} // 此时,j可能是i(如果arr[i]已经在其正确位置),也可能是i之前的一个位置
}
}
在这个内层循环中,j
从当前元素的位置 i
开始,并向前移动到 gap
的倍数位置,直到找到一个不大于 temp
的元素或 j
小于 gap
(这意味着 j - gap
会越界,因此循环会停止)。在每次迭代中,如果 arr[j - gap]
大于 temp
,则 arr[j - gap]
会被移动到 arr[j]
的位置,这样 temp
就可以在后面的迭代中找到一个正确的位置插入。
一旦内层循环完成,temp
(即原始 arr[i]
)就被插入到了由间隔 gap
定义的子列表中它应该出现的位置。然后,外层循环继续,为下一个元素重复这个过程,直到数组被完全排序(尽管在希尔排序的每次迭代中,数组只是部分排序的,直到 gap
减小到 1,算法才退化为普通的插入排序来完成最终的排序)。
请注意,希尔排序的性能很大程度上取决于 gap
序列的选择。在上面的代码中,gap
是由外层循环的某个逻辑(在您提供的代码片段之外)来逐步减小的。不同的 gap
序列选择可能会导致不同的排序速度和稳定性。