php 4大排序算法及二分法查找

插入排序

   1.从第一个元素开始,该元素可以认为已经被排序
   2.取出下一个元素,在已经排序的元素序列中从后向前比较
   3.如果该元素(已排序)大于新元素,将该元素移到下一位置

/**
     * 插入排序
     */
    public function Insert_sort($arr=array(5,2,7,1,3)){
        $count=count($arr);
        for($i=1;$i<$count;$i++){
            $j=$i-1;
            $temp=$arr[$i];   //临时比较元素
            while($j>=0){    //从后往前逐个比较元素大小
                if($arr[$j]>$temp){      //临时比较元素比较小则交换前后元素位置
                    $arr[$j+1]=$arr[$j];
                    $arr[$j]=$temp;
                }
                $j--;
            }
            var_dump($arr);echo "<br>";
        }
        return $arr;
    }

 

简单选择排序

思想:

1)循环n次,每次找到最小的元素进行元素交换 。

/**
     * 简单排序
     * 循环n次,每次找到最小的元素进行元素交换
     */
    public function Select($arr=array(2,16,8,6,3,19)){
        $count=count($arr);
        for($i=0;$i<=$count;$i++){
            $min=$i;
            for($j=$i+1;$j<$count;$j++){    //从未比较的元素开始循环
                if($arr[$j]<$arr[$min]){
                    $min=$j;    //比较到小元素则记录其下标
                }
            }
            if($min!=$i){    //使用临时变量交换最小元素
                $temp = $arr[$min];
                $arr[$min] = $arr[$i];
                $arr[$i] = $temp;
            }
        }
        return $arr;
    }

 

冒泡排序

思路:

1)第一次循环控制循环次数,数组长度n-1次(最坏的结果是比较n-1次才出结果)

2)第二次循环比较数组的每个元素,后一位元素比前一位元素小则交换位置(需要一个临时变量$tmp
 

 

function bubbleSort($arr){  
        $count=count($arr);
        #对于一个长度为N的数组,我们需要排序 N-1 轮,每 i 轮 要比较 N-i 次。对此我们可以用双重循环语句,外层循环控制循环轮次,内层循环控制每轮的比较次数。
        for($i=1;$i<$count;$i++){ 
            for($k=0;$k<$count-$i;$k++){
                if($arr[$k]>$arr[$k+1]){
                    $tmp=$arr[$k+1];
                    $arr[$k+1]=$arr[$k];
                    $arr[$k]=$tmp;
                }
            }
        }
        return $arr;
}

 

快速排序

思路: 
1)选择一个基准元素,通常选择第一个元素或者最后一个元素, 
2)通过一趟排序讲待排序的记录分割成独立的两个数组,其中小数组记录的元素值均比基准元素值小,大数组记录的 元素值比基准值大。 
3)然后同样的方法递归大、小数组进行排序,直到整个序列有序。 
4)最后合并小数组、基准元素、大数组。 

 /**
     * 快速排序
     */
    public function Quick_sort($arr = array(50, 43, 54, 62, 21, 66, 32, 78, 36, 76, 39,2)){
        //判断参数是否是一个数组
        if(!is_array($arr)) return false;

        //递归出口:递归至数组长度为1,则返回数组
        $length = count($arr);
        if($length<=1) return $arr;

        //数组元素有多个,则定义两个空数组
        $left = array();
        $right = array();

        //使用for循环遍历数组
        for($i=1; $i<$length; $i++) {
            $value = $arr[0] ; //把 第一个元素 当做 比较对象

            if($arr[$i] < $value){
                $left[]=$arr[$i];    //小于 比较对象放入 $left 数组
            }else{
                $right[]=$arr[$i];    //大于 比较对象放入 $right 数组
            }
        }

        //不断递归 $left、$right数组知道数组长度为1
        $left = $this->Quick_sort($left);
        $right = $this->Quick_sort($right);


        //将所有的结果合并
        return array_merge($left,$value,$right);
    }

 

归并排序

归并(Merge)排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个有序的子序列,再把有序的子序列合并为整体有序序列。

/**
* mergeSort 归并排序
* 是开始递归函数的一个驱动函数
* @param &$arr array 待排序的数组
*/
function mergeSort(&$arr) {
    $len = count($arr);//求得数组长度
 
    mSort($arr, 0, $len-1);
}
/**
* 实际实现归并排序的程序
* @param &$arr array 需要排序的数组
* @param $left int 子序列的左下标值
* @param $right int 子序列的右下标值
*/
function mSort(&$arr, $left, $right) {
 
    if($left < $right) {
        //说明子序列内存在多余1个的元素,那么需要拆分,分别排序,合并
        //计算拆分的位置,长度/2 去整
        $center = floor(($left+$right) / 2);
        //递归调用对左边进行再次排序:
        mSort($arr, $left, $center);
        //递归调用对右边进行再次排序
        mSort($arr, $center+1, $right);
        //合并排序结果
        mergeArray($arr, $left, $center, $right);
    }
}
 
/**
* 将两个有序数组合并成一个有序数组
* @param &$arr, 待排序的所有元素
* @param $left, 排序子数组A的开始下标
* @param $center, 排序子数组A与排序子数组B的中间下标,也就是数组A的结束下标
* @param $right, 排序子数组B的结束下标(开始为$center+1)
*/
function mergeArray(&$arr, $left, $center, $right) {
    //设置两个起始位置标记
    $a_i = $left;
    $b_i = $center+1;
    while($a_i<=$center && $b_i<=$right) {
        //当数组A和数组B都没有越界时
        if($arr[$a_i] < $arr[$b_i]) {
            $temp[] = $arr[$a_i++];
        } else {
            $temp[] = $arr[$b_i++];
        }
    }
    //判断 数组A内的元素是否都用完了,没有的话将其全部插入到C数组内:
    while($a_i <= $center) {
        $temp[] = $arr[$a_i++];
    }
    //判断 数组B内的元素是否都用完了,没有的话将其全部插入到C数组内:
    while($b_i <= $right) {
        $temp[] = $arr[$b_i++];
    }
 
    //将$arrC内排序好的部分,写入到$arr内:
    for($i=0, $len=count($temp); $i<$len; $i++) {
        $arr[$left+$i] = $temp[$i];
    }
 
}
 
 
//do some test:
$arr = array(4, 7, 6, 3, 9, 5, 8);
mergeSort($arr);
print_r($arr);

 

 

二分法查找

前提:查找数组必须是有序的

1)获取并记录数组上限、下限、中间下标

2)用中间下标值与目标值进行比较,如果:

    ①目标值 < 中间值 ,上限减1,并改变对应中间下标

    ②目标值 > 中间值 ,下限加1,并改变对应中间下标

    ③目标值 = 中间值,匹配成功

/**
     * 二分查找法
     * 使用前提是有序数组
     */
    public function binarySearch($value = 22, $arr = array(3, 4, 6, 7, 9, 16, 22) ){
        $low = 0;    //数组下限下标
        $high = count($arr)-1;    //数组上限下标

        // 注意凡是使用到while的时候,一定要防备无限循环的时候,注意终止循环的判断。
        while($low <= $high){
            //获取中间比较的中间下标(强制整形)
            $middle = intval(($low + $high)/2);

            if($value < $arr[$middle]){    //目标值 < 中间值 ,上限减1
                $high = $middle - 1;
            }elseif ($value > $arr[$middle]){    //目标值 > 中间值 ,下限加1
                $low = $middle + 1;
            }else{
                return $middle;     //目标值 = 中间值,匹配成功返回下标值
            }
        }

        return -1;
    }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值