1、冒泡排序 Bubble Sort

排队,依次交换

$arr = [1,4,2,9,7,5,8];

//2、 让下面的可以每次找出最大值的代码重复执行
for($i =0, $len = count($arr); $i < $len; $i++) {
    //1、将最大的放到最右边
    for($j = 0; $j < $len - 1 - $i; $j++ ) {
        //判断:两两相比
        if($arr[$j] > $arr[$j+1]) {
            //左边比右边大:交换
            $temp = $arr[$j];
            $arr[$j] = $arr[$j+1];
            $arr[$j+1] = $temp;
        }
    }
}


2、选择排序 Selection sort

不稳定 [5, 5, 3] 第一次将[5]和[3]交换,导致第一个5到第二个5后面
每次从待排序数据元素中挑选出最小元素,存放在序列的起始位置

$arr = [1,5,2,9,3,4];

//1、 确定要交换多少次:一次只能找到一个最小的,需要找数组长度对应的次数
for($i = 0,$len = count($arr); $i < $len; $i++) {
    //2、 假设当前第一个已经排好序了
    $min = $i; //当前第一个数是最小的
    //3、 拿该最小的比较剩余的其他
    for($j = $i + 1; $j < $len; $j++) {
        //4、 比较:比较当前元素与选定的最小元素
        if($arr[$j] < $arr[$min]) {
            //说明当前指定的$min不合适
            $min = $j;
        }
    }
    //5、 交换当前选定的值与实际最小的元素值
    if($min != $i) {
        $temp = $arr[$i];
        $arr[$i] = $arr[$min];
        $arr[$min] = $temp;
    }
}

3、插入排序 Insert sort

使用少量数据排序,稳定

$arr = [4,2,6,8,9,5];

//1、 确定要插入多少回(假设一个数字一次性出入对的位置,同时第一个位置是对的)
for($i = 1,$len = count($arr); $i < $len; $i++) {
    //2、 取出当前要插入的元素的值
    $temp = $arr[$i];
    //标记: 默认说明当前要插入的数组的位置是对的
    $change = fales;
    //3、 让该数据与前面已经排好序的元素重复比较(挨个比较),知道对的位置(交换)
    for($j = $i - 1; $j >=0; $j--) {
        //4、 比较
        if($arr[$j] > $temp) {
            //说明当前要插入的元素,比前面的已经排好序的元素值小:交换位置
            $arr[$j+1] = $arr[$j];
            //$arr[$j] = $temp;
            // 说明前面顺序的数组元素有不合适的位置
            $change = true;
        }else{
            //说明当前待插入元素,比前面元素大:说明位置正确
            break;
        }
    }
    //判断位置是否需要变动
    if($change) {
        //有数据移动:站错位置了
        $arr[$j+1] = $temp;
    }
}

4、快速排序 Quicksort

对冒泡排序的改进 不稳定 (递归)

$arr = [5,6,3,4,9,2,7,8];

// 快速排序
function quick_sort($arr) {
    //递归出口
    $len = count($arr);
    if($len <= 1) return $arr;

    //去除某个元素,将剩余的数组元素分散到两个不同的数组中
    $left = $right = [];
    for($i = 1; $i < $len; $i++) {
        //第一个元素作为比较元素
        //比较:小的放left中,大的放right中
        if($arr[$i] < $arr[0]) {
            $left[] = $arr[$i];
        }else{
            $right[] = $arr[$i];
        }
    }
    //$left和$righ数组元素没有排好序:递归点
    $left = quick_sort($left);
    $right = quick_sort($right);
    // 合并三个"数组"
    return array_merge($left, (array)$arr[0], $right);
}

5、归并排序 MERGE-SORT

采用分治法 Divide and Conquer

// 二路归并
$arr1 = [1,3,5];
$arr2 = [2,4,6];

//去除一个空数组用于归并空间
$arr3 = [];
while(count($arr1) && count($arr2)) {
    //只要$arr1和$arr2里面还有元素,就进行循环
    //去除每个数组的第一个元素:进行比较
    $arr3[] = $arr1[0] < $arr2[0] ? array_shitf($arr1) : array_shift($arr2);
}

//合并结果
array_merge($arr3, $arr1, $arr2);
$arr = [4,7,2,1,5,9,3];
//归并排序函数
function merge_sort($arr) {
    //递归出口
    $len = count($arr);
    if($len <= 1) return $arr;
    //拆分
    $middle = floor($len / 2);
    $left = array_slice($arr, 0, $middle);
    $right = array_slice($arr, $middle);

    //递归点:$left和$right都没有排好序:而且可能是多个元素的数组
    $left = merge_sort($left);
    $right = merge_sort($right);

    //假设左边和右边都已经排好序:二路归并
    $m = [];
    while(count($left) && count($right)) {
        //只要$arr1和$arr2里面还有元素,就进行循环
        //去除每个数组的第一个元素:进行比较
        $m[] = $left[0] < $right[0] ? array_shitf($left) : array_shift($right);
        //返回结果
    }
    return array_merge($m, $left, $right);
}
Scroll to Top