常用算法的php实现

php常用算法实现

#冒泡算法

/**
 * 冒泡排序是最基础的排序算法,他设计的逻辑也是我们最容易想到的,通过两层循环遍历。
 * 第一层遍历是根据这个数组的元素个数,因为要保证每次遍历后数组中最大的值跑到底部
 * 第二层遍历是真正的比较两个数值大小,把大的数值往后靠
 * 最后有个优化的点是通过一个标识如swag变量来记录第二层遍历是否有交换过数据
 * 因为如果没有交换数据了,说明就已经排好序的了,直接退出。
 */
<?php
function bubble_sort($array)
{
    $len = count($array);
    $swag = false;
    
    for ($j = 0; $j < $len; $i++) {
        for ($j = 1; $j < $len - $i; $j++) {
            if ($array[$j-1] > $array[$j]) {
                [$array[$j-1], $array[$j]] = [$array[$j], $array[$j-1]];
                $swag = true;
            }
        }

        if ($swag === false) {    //判断上次循环是否有交换,没有交互说明已经有序,就不用循环了
            break;
        }
    }

    return $array;
}

#归并排序

/**
 *	归并排序用到了分治思想,将一个大问题,拆分成各个小的子问题,最后将子问题得到的结果再合并成最终的结果
 *	分治思想的实现是通过递归算法,递归算法刚好符合分治思想
 *	重点是最后的合并两个有序数组merge函数,不过这个也不难
 *	时间复杂度是O(nlogn)
 *	空间复杂度是O(n)
 *	非原地排序,稳定排序
 */
<?php
function merge_sort($a)
{
    $n = count($arr);
    return merge_sort_c($a, 0, $n-1);
}

function merge_sort_c($a, $left, $right)
{
    if ($left >= $right) {
        return [$a[$right]];    //递归退出条件,获取return [$a[$left]];
    }

    $mid = floor(($left + $right) / 2);
    $left = merge_sort_c($a, $left, $mid);
    $right = merge_sort_c($a, $mid+1, $right);
    
    return merge($left, $right);
}

function merge($left, $right)
{
    $i = 0; $j = 0;
    $tmp = [];

    while (isset($left[$i]) && isset($right[$j])) {
        If ($left[$i] < $right[$j]) {
            $tmp[] = $left[$i];
            $i++;
        } else {
            $tmp[] = $right[$j];
            $j++;
        }
    }
    
    while (isset($left[$i]) {
        $tmp[] = $left[$i];
        $i++;
    }
    
    while (isset($right[$j])) {
        $tmp[] = $right[$j];
        $j++;
    }

    return $tmp;
}

#快速排序

<?php
/**
 * 快速排序是时间复杂度也是O(nlogn)
 * 但是空间复杂度O(1)
 * 所以相对来说大家都喜欢用快速排序,而且利用快速排序可以很快就能计算出第K大/小的值是多少
 * 快速排序相对于归并排序的区别点是:快速排序是选择一个值pviot,然后将数组分成三部分, < pviot, pviot, > pviot。
 * 重点是这个pviot这个值的函数partition(),这个函数实现了原地排序,空间复杂度是O(1)。
 * 利用两个指针i,j一开始同时指向第一个,在遍历过程中,如果遇到比pviot值小的,就将i,j所指的数据交换位置,如果比pviot大,i不动,j往后移动一位
 * 最后交换pviot与i所指的数据位置,这样就能将数组划分三部分了,然后对左右进行相同的递归操作。
 */
function quick_sort($a)
{
    quick_sort_c($a, 0, $n1);
}

function quick_sort_c(&$a, $left, $right)
{
    if ($left >= $right) {
        return;
    }

    $partition = partition($a, $left, $right);

    quick_sort_c($a, $left, $partition-1);
    quick_sort_c($a, $partition+1, $right);
}

function partition(&$a, $left, $right)
{
    $p = $a[$right];
    $j = $left;
    for ($i = $left; $i < $right; $i++) {
        If ($a[$i] < $p) {
            [$a[j], $a[$i]] = [$a[$i], $a[$j]];
            $j++;
        }
    }
    
    [$a[$j], $a[$right]] = [$a[$right], $a[$j]];
    
    return $j;
}

#二分查找

<?php

function binary_search($a, $v)
{
    $n = count($a);
    
    return binary_search_c($a, 0, $n - 1, $v);
}

//递归实现
function binary_search_c($a, $low, $hight, $v)
{
    If ($low > $hight) {
        return false;
    }
    
    $mid = floor(($low + $hight) / 2);
    if ($a[$mid] > $v) {
        return binary_search_c($a, $mid + 1, $hight, $v);
    } else if ($a[$mid] < $v) {
        return binary_search_c($a, $low, $mid - 1, $v);
    } else {
        return $mid;
    }
}

//非递归实现
function binary_search_u($a, $v)
{
    $low = 0;
    $hight = count($a);
    If ($hight == 0) {
        return -1;
    }

    while ($low <= $hight) {
        $mid = floor(($low + $hight) / 2);
        If ($a[$mid] > $v) {
            $hight = $mid - 1;
        } else if ($a[$mid] < $v) {
            $low = $mid + 1;
        } else {
            return $mid;
        }    
    }
    
    return -1;
}

未完待续。。。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值