- 内排序
- 稳定排序
- 冒泡排序 折半排序 插入排序 基数排序
- 非稳定排序
- 希尔排序 快速排序 堆排序 选择排序
- 稳定排序
- 外排序
插入排序
- 直接插入
<?php
//[0,..., i] 从1开始向后i循环 插入排序的位置
//若a[x] < a[x-1] 那么 temp = a[x] a[x] = a[x-1]
//继续从当前x-1向 0的方向比较 如果 a[x-n] > temp -> a[x-n+1] = a[x-n]
// 直到x-n < 0 || a[n] < temp
//和冒泡的思想类似
//不同点是 冒泡每次只需要移动一个元素
//
//稳定排序
//最好情况:正序 O(n-1)
//平均 : O(n^2)
//空间复杂度O(1)
function insertSort($arr)
{
$count = count($arr);
if ($count <= 1) return $arr;
for ($index=1; $index < $count; $index++) {
//当存在反序时
if ($arr[$index] < $arr[$index-1]) {
$temp = $arr[$index];
$pre = $index-1;
while ($pre >= 0 && $arr[$pre] > $temp) {
$arr[$pre+1] = $arr[$pre];
$pre--;
}
$arr[$pre+1] = $temp;
}
}
return $arr;
}
- 折半插入
<?php
//折半插入排序 是在直接插入的基础上进行优化
//通过减少比较次数(查找插入位置)
//然后集中将找到的位置 到 当前位置 区间进行移动
//稳定排序
//平均复杂度 O(n^2)
//最坏 O(n^2)
//最好 O(n)
//空间复杂度O(1)
function binarySort($arr)
{
$count = count($arr);
if ($count <= 1) return $arr;
//外层从1开始逐一比较
for ($index=1; $index < $count; $index++) {
//如果存在反序 才寻找需要插入的位置
if ($arr[$index-1] > $arr[$index]) {
$temp = $arr[$index];
$low = 0;
$high = $index-1;
while ($low<=$high) {
$mid = $low +intval(($high-$low)/2);
if ($temp < $arr[$mid]) $high = $mid-1;
else $low = $mid+1;
}
//插入位置插入元素前 将[low,index-1]向右移动一个单位
for ($j=$index-1; $j >= $mid; $j--) {
$arr[$j+1] = $arr[$j];
}
//最后放入插入位置
$arr[$low] = $temp;
}
}
}
- 希尔排序
<?php
//希尔排序也是基于直接插入的基础上进行排序
//元素n 每次以间隔为n/2为一组进行直接插入
// d = n/4 ... d= n/8
//非稳定排序
//时间复杂度O(n^(1.3--2))
//空间复杂度O(1)
function ShellsSort($arr)
{
$count = count($arr);
if ($count <= 1) return $arr;
//设置初始增量
$d = intval($count/2);
//增量最小为1
while ($d > 0) {
//间隔为d的直接插入
for ($index=$d; $index < $count; $index++) {
if ($arr[$index-$d] > $arr[$index]) {
$temp = $arr[$index];
$j = $index-$d;
while ($j >= 0 && $arr[$j] > $temp) {
$arr[$j+$d] = $arr[$j];
$j -= $d;
}
$arr[$j+$d] = $temp;
}
}
$d = intval($d/2);
}
return $arr;
}
上面三种 直接插入、折半插入、希尔插入 都是基于直接插入的基础上进行部分优化 而其中直接插入与折半插入又属于稳定排序, 因为希尔基于增量间隔进行的插入排序 进行的多次插入排序相同元素位置可能变化