原理
把元素按下标的一定增量分组,然后对每组进行插入排序;随着增量逐渐减少,每组包含的元素越来越多,当增量减至1时,所有元素成为一组,算法便终止。其实也是插入排序的一种,区别在于插入排序是相邻元素的比较(类似于希尔排序中增量h=1的情形)
代码
function shell_sort(array $arr){
// 将$arr按升序排列
$len = count($arr);
$f = 3;// 定义因子
$h = 1;// 最小为1
while ($h < $len/$f){
$h = $f*$h + 1; // 1, 4, 13, 40, 121, 364, 1093, ...
}
while ($h >= 1){ // 将数组变为h有序
for ($i = $h; $i < $len; $i++){ // 将a[i]插入到a[i-h], a[i-2*h], a[i-3*h]... 之中 (算法的关键
for ($j = $i; $j >= $h; $j -= $h){
if ($arr[$j] < $arr[$j-$h]){
$temp = $arr[$j];
$arr[$j] = $arr[$j-$h];
$arr[$j-$h] = $temp;
}
//print_r($arr);echo '<br/>'; // 打开这行注释,可以看到每一步被替换的情形
}
}
$h = intval($h/$f);
}
return $arr;
}
$arr = array(14, 9, 1, 4, 6, -3, 2, 99, 13, 20, 17, 15, 3);
$shell = shell_sort($arr);
echo '<pre>';
print_r($shell);
时间复杂度
O(n^2)
空间复杂度
O(1)
稳定性
不稳定
适用场景
适用于大部分元素已完成排序的情况。