1.0参考:十大经典排序算法动画与解析
$arr = [1, 33, 24, 8, 21, 2, 21, 3, 32, 16, 2, 80];
冒泡排序
for ($i = 0; $i < count($arr) - 1; $i++) {
// 设定一个标记,若为true,则表示此次循环没有进行交换,也就是待排序列已经有序,排序已经完成。
$flag = true;
for ($j = 0; $j < count($arr) - $i - 1; $j++) {
if ($arr[$j] > $arr[$j + 1]) {
$temp = $arr[$j];
$arr[$j] = $arr[$j + 1];
$arr[$j + 1] = $temp;
$flag = false;
}
}
if ($flag) break;
}
var_dump($arr);
选择排序
for ($i = 0; $i < count($arr) - 1; $i++) {
for ($j = $i + 1; $j < count($arr); $j++) {
if ($arr[$i] > $arr[$j]) {
$tmp = $arr[$j];
$arr[$j] = $arr[$i];
$arr[$i] = $tmp;
}
}
}
var_dump($arr);
插入排序
for ($i = 1; $i < count($arr); $i++) {
$tmp = $arr[$i];
$j = $i;
while ($tmp < $arr[$j - 1] && $j > 0) {
$arr[$j] = $arr[$j - 1];
$j--;
}
if ($j != $i) {
$arr[$j] = $tmp;
}
}
var_dump($arr);
希尔排序(即增加了步长的插入排序)
$gap = floor(count($arr) / 2);
while ($gap > 0) {
for ($i = $gap; $i < count($arr); $i++) {
$tmp = $arr[$i];
$j = $i;
while ($tmp < $arr[$j - $gap] && $j > 0) {
$arr[$j] = $arr[$j - $gap];
$j -= $gap;
}
if ($j != $i) {
$arr[$j] = $tmp;
}
}
$gap = floor($gap / 2);
}
var_dump($arr);
归并排序
function arraySlice($arr)
{
if (count($arr) <= 1) return $arr;
$mid = floor(count($arr) / 2);
$left = arraySlice(array_slice($arr, 0, $mid));
$right = arraySlice(array_slice($arr, $mid));
return mergeSort($left, $right);
}
function mergeSort($left, $right)
{
$arr = [];
while (count($left) && count($right)) {
$arr[] = $left[0] < $right[0] ? array_shift($left) : array_shift($right);
}
return array_merge($arr, $left, $right);
}
$arr = arraySlice($arr);
var_dump($arr);
快速排序
function quickSort($arr)
{
if (count($arr) <= 1) return $arr;
$mid = $arr[0];
$left = $right = [];
for ($i = 1; $i < count($arr); $i++) {
if ($arr[$i] < $mid) {
$left[] = $arr[$i];
} else {
$right[] = $arr[$i];
}
}
return array_merge(quickSort($left), [$mid], quickSort($right));
}
$arr = quickSort($arr);
var_dump($arr);
堆排序
//因为是数组,下标从0开始,所以,下标为n根结点的左子结点为2n+1,右子结点为2n+2;
//每次循环拿到最大值放在新长度的数组最后
for($len=count($arr);$len>1;$len--){
buildHeap($arr,$len);
}
//用数组建立大顶堆
function buildHeap(&$arr,$len){
//左子结点为2n+1,右子结点为2n+2,所以从($len/2-1)处对一个树进行循环比较即可,然后形成大顶堆
for($index=intval($len/2)-1; $index>=0; $index--){
//如果有左子节点,将其下标存进最大值$max
if($index*2+1<$len){
$max=$index*2+1;
//如果有右子结点,比较左右结点的大小,如果右子结点更大,将其结点的下标记录进最大值$max
if($index*2+2<$len && $arr[$index*2+2]>$arr[$max]){
$max=$index*2+2;
}
//将子结点中较大的和父结点比较,若子结点较大,与父结点交换位置
if($arr[$max]>$arr[$index]){
swap($arr,$max,$index);
}
}
}
//将堆的根(最大的元素)拿出来与最后一个叶子交换,接下来的循环长度-1即可
swap($arr,0,$len-1);
}
//此函数用来交换数组$arr中下标为$max和$index的数据
function swap(&$arr,$max,$index){
$tmp=$arr[$max];
$arr[$max]=$arr[$index];
$arr[$index]=$tmp;
}
var_dump($arr);