PHP常见算法与排序

冒泡排序

思路分析:在未排序的数组中,从前往后对相邻的两个数一次对比,较大的数往下沉,较小的往上冒。
即,从左到右,数组中相邻的两个元素进行比较,将较大的放到后面。

function bubbleSort($arr) {
    if(empty($arr)) return $arr;
    $len = count($arr);
    //该层循环控制 需要冒泡的轮数
    for($i=0; $i< $len; $i++) {
        //该层循环用来控制每轮 冒出一个数 需要比较的次数
        for($j=0; $j<($len-1-$i); $j++) {
            if($arr[$j] > $arr[$j+1]){
                $tmp = $arr[$j];
                $arr[$j] = $arr[$j+1];
                $arr[$j+1]= $tmp;
            }
        }
    }
    return $arr;
}
$arr = [1,3,4,5,76,34,72,65,78,22,88];
var_dump(bubbleSort($arr));

选择排序

思路分析:在要排序的一组数中,选出最小的一个数与第一个位置的数交换。然后在剩下的数当中再找最小的与第二个位置的数交换,如此循环到倒数第二个数和最后一个数比较为止。
即,从第一个位置开始比较,找出最小的,和第一个位置互换,开始下一轮。

function selectSort($arr) {
    if (empty($arr)) return $arr;
    $len = count($arr);
    //双重循环完成,外层控制轮数,内层控制比较次数
    for($i=0; $i<$len-1; $i++) {
        //先假设最小的值的位置
        $min = $i;
        for($j=$i+1; $j<$len; $j++){
            if($arr[$min] > $arr[$j]){
                $min = $j;
            }
            if ($min != $i) {
                $tmp = $arr[$min];
                $arr[$min] = $arr[$i];
                $arr[$i] = $tmp;
            }
        }
    }
    return $arr;
}
$arr = [1,3,4,5,76,34,72,65,78,22,88];
var_dump(selectSort($arr));

快速排序

思路分析:选择一个基准元素,通常选择第一个元素或者最后一个元素。通过一趟扫描,将待排序列分成两部分,一部分比基准元素小,一部分大于等于基准元素。
此时基准元素在其排好序后的正确位置,然后再用同样的方法递归地排序划分的两部分。

function quickSort($arr) {
    $len = count($arr);
    if ($len <= 1) return $arr;
    //选择第一个元素作为标准
    $baseTmp = $arr[0];
    $leftArr = [];
    $rightArr = [];
    //遍历,按照大小关系放入两个数组内。注意从1开始
    for($i=1; $i<$len; $i++) {
        if ($arr[$i] < $baseTmp) {
            $leftArr[] = $arr[$i];
        } else {
            $rightArr[] = $arr[$i];
        }
    }
    $leftArr = quickSort($leftArr);
    $rightArr = quickSort($rightArr);
    return array_merge($leftArr, [$baseTmp], $rightArr);
}
$arr = [1,3,4,5,76,34,72,65,78,22,88];
var_dump(quickSort($arr));

插入排序

思路分析:在要排序的一组数中,假设前面的数已经是排好顺序的,现在要把第n个数插到前面的有序数中,使得这n个数也是排好顺序的。
第n个数与前面n-1个数分别依次作比较,如果比前面的数小就交换位置,否则就终止循环,如此反复循环,直到全部排好顺序。

function insertSoet($arr) {
    if (empty($arr)) return $arr;
    $len = count($arr);
    for($i=1; $i< $len; $i++) {
        //要插入的数
        $tmp = $arr[$i];
        //依次与前面的每个数作比较,$tmp小就互换位置,否则终止循环;
        for($j=$i-1; $j>=0; $j--) {
            if ($tmp < $arr[$j]) {
                //发现插入的元素要小,交换位置,将后边的元素与前面的元素互换
                $arr[$j+1] = $arr[$j];
                $arr[$j] = $tmp;
            } else {
                //如果碰到不需要移动的元素,由于是已经排序好是数组,则前面的就不需要再次比较了。
                break;
            }
        }
    }
    return $arr;
}
$arr = [1,3,4,5,76,34,72,65,78,22,88];
var_dump(insertSoet($arr));

二分查找

思路分析:折半算法,先找到中间节点,用K与中间节点的关键词比较,中间节点把线性表分为两个子表,直到查找到或查找结束。
注:针对已经排好序的数组

//递归方法
function binSch($arr, $k, $start=0, $end=0) {
    if ($start > $end) return -1;
    if (count($arr) !== 0 && $end ==0) {//判断是否为第一次调用
        $end = count($arr);
    }
    $mid = floor(($start + $end) / 2);
    if ($k == $arr[$mid]) {
        return $mid;
    } elseif ($k < $arr[$mid]) {
        $newStart = $start;
        $newEnd = $mid -1;
        return binSch($arr, $k, $newStart, $newEnd);
    } else {
        $newStart = $mid + 1;
        $newEnd = $end;
        return binSch($arr, $k, $newStart, $newEnd);
    }
}
$arr = array(1,2,4,6,10,40,50,80,100,110);
echo bin_search($arr,80);

//循环方法:
function bin_search($arr,$key) {
    $high = count($arr);
    if($high <= 0)
        return 0;
    $low = 0;
    while($low <= $high) {     
        //当前查找区间arr[low..high]非空
          $mid=intval(($low + $high) / 2);
        if($arr[$mid] == $key) 
            return $mid; //查找成功返回
        if($arr[$mid] > $key)
            $high = $mid - 1; //继续在arr[low..mid-1]中查找
        else
            $low = $mid + 1; //继续在arr[mid+1..high]中查找
    }
    return 0; //当low>high时表示查找区间为空,查找失败
}
$arr = array(1,2,4,6,10,40,50,80,100,110);
echo bin_search($arr,80);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值