插入排序
原理就像玩扑克牌,右手从桌子上【待排序数组】抽一张牌后递给左手【已排序数组】,左手拿到第一张牌,之后每次抽牌就扫描左手数组,找到相应位置并插入。
实现过程
示例数组:$array=[-5,17,1,2,4,5,9,3,0,1,12,-10],下划线表示左手数组放到左手中已排序的部分,未划线是桌子上待排序部分,起牌顺序是固定的,它和选择排序的不同在于选择排序类似所有牌摊在桌上,每次从桌上选择最小(大)的牌放到左手,而插入排序是每次顺序起一张牌,在左手中选择它合适的位置并插入。
抽第1张牌:-5,17,1,2,4,5,9,3,0,1,12,-10 //抽到了-5,排在第1位
抽第2张牌:-5,17,1,2,4,5,9,3,0,1,12,-10 //抽到了17,排在队尾
抽第3张牌:-5,1,17,2,4,5,9,3,0,1,12,-10 //抽到了1,排在17前
抽第4张牌:-5,1,2,17,4,5,9,3,0,1,12,-10 //抽到2,排在17前
抽第5张牌:-5,1,2,4,17,5,9,3,0,1,12,-10 //抽到4,排在17前
抽第6张牌:-5,1,2,4,5,17,9,3,0,1,12,-10 //抽到5,排在17前
... ...
桌子上牌起完后,手里的牌也摆好了。
PHP代码实现
(升序)
$array=[-5,17,1,2,4,5,9,3,0,1,12,-10];
$count = count($array);
echo '<pre>';
for ($i = 1; $i < $count; $i++) {//第i个元素
$temp = $array[$i];//当前元素
//降序时改为: while($i - 1 >= 0 && $array[$i - 1] < $temp) { 比当前元素小的向后错1位之意
while($i - 1 >= 0 && $array[$i - 1] > $temp) { //从已排序数组末尾开始对比,比当前元素大的,向后错一位,下标都+1
$array[$i] = $array[$i - 1];
$i--;
}
$array[$i] = $temp;//当前元素补上空位
}
print_r($array);
时间复杂度计算
悲观情况下,每插入一个元素需要对比的元素个数为0+1+....+(n-1)=(-n)/2,记做O()。
空间复杂度计算
本例使用了$count、$i、$j这些变量来辅助计算,在整个运算过程中各变量最多同时出现1次,因此其空间复杂度是一个常量,记做O(1)。
希尔排序
是对插入排序的优化,“缩小增量排序”,记录按下标的一定增量分组,对每组使用直接插入排序算法排序,增量逐渐减小到1。