算法初探--递归算法

【本文概要和说明】
1、简要说明递归算法
2、实例说明和演示

(本文采用 PHP 语言在CI框架下进行编写和说明)
【⚠️:文中使用的表述和说明,仅代表个人观点和理解来书写,非正式官方解释】
复制代码

一、什么是递归算法

递归:就是指函数调用自身的方法。

二、理解和注意事项(要素)

理解:
调用自身,其实就是说逻辑和最外层的函数实现是一样的,我们可以理解为在外层函数执行到某一点时,逻辑就会和外层函数一样,即:每一次调用都是将大问题化解成规模较小的问题进行解决。
我们的使用递归的目的是为了实现某个功能,所以我们应该有停止递归的条件,然后将递归结果返回作为功能实现的数据信息,我们就需要有一个条件可以停止递归,停止之后需要根据功能的需求做对应的逻辑处理。

要素:
1、需要提取出重复的逻辑,为递归做好准备。
2、需要一个停止递归的条件节点,防止无限递归。
3、需要给出停止递归后的实现方式,根据需求结果而定。

三、实例说明

1、我们先用几个简单的例子理解一下递归。

案例一:求 n 的阶乘
分析:我们知道阶乘的表达式为 n! = 1 * 2 * 3 * ... * n

我们先以 5 的阶乘为例:
1! = 1 --------------------------- 1 --------- 1
2! = 2 * 1 ------------------------ 2 * 1! ----- 2 * (2 - 1)!
3! = 3 * 2 * 1 --------------------- 3 * 2! ----- 3 * (3 - 1)!
4! = 4 * 3 * 2 * 1 ------------------ 4 * 3! ----- 4 * (4 - 1)!
5! = 5 * 4 * 3 * 2 * 1 --------------- 5 * 4! ----- 5 * (5 - 1)!
... ... ... ... ... ... ... ... ...
n! = n * (n - 1)!

我们用常规方法实现阶乘,代码如下:

public function factorial_normal($num)
{
    $n = 1;
    $result = 1;
    while($n <= $num){
        $result *= $n;
        $n ++;
    }

    return $result;
}
复制代码

我们用递归方式实现阶乘,代码如下:

public function factorial_recursive($num)
{
    if($num == 1)
    {
        return 1;
    }

    $result = $num * $this->factorial_recursive($num - 1);
    return $result;
}
复制代码

案例二:给定一个关键字,将数组中包含该关键字的 key 对应的 value 前都加上一个标记 ‘Mark:’。

// 遍历数组,找出给定数组中所有指定 key 的值,并添加 Mark 标记
public function deepLoop(&$arr, $keyword = '')
{
    // 设置匹配正则表达式
    $reg = "/" . $keyword . "/i";

    // 判断数组和关键字的有效性
    if( ! is_array($arr) || $keyword == '' || $keyword == null)
    {
        return $arr;
    }

    // 循环数组,找出指定的 key, 并给对应的值加上 Mark 标记
    foreach($arr as $key => $value)
    {
        if(is_array($value))
        {
            $this->deepLoop($value, $keyword);
        }
        else
        {
            if(preg_match($reg, $key))
            {
                $value = 'Mark: ' . strval($value);
            }
        }

        $arr[$key] = $value;
    }

    return $arr;
}
复制代码

调试(我们执行 $this->deepLoop($userInfo, 'name');):
我们首先使用一维数组:

$userInfo = [
    'userName' => 'user1',
    'userAge' => 18,
    'testName' => 'user test name'
];
复制代码

运行截图:

多维数组:

$userInfo = [
    'userName' => 'user1',
    'userAge' => 18,
    'testName' => 'user test name',
    'child' => [
        'userName' => 'user1',
        'userAge' => 18,
        'testName' => 'user test name',
        'child' => [
            [
                'userName' => 'user1',
                'userAge' => 18,
                'testName' => 'user test name'
            ],
            [
                'userName' => 'user1',
                'userAge' => 18,
                'testName' => 'user test name'
            ]
        ]
    ]
];
复制代码

运行截图:

案例三:打印出指定路径下的目录结构
分析:
1、我们首先需要知道该目录下有些什么东西(文件夹和文件)
2、要对目录下的东西进行分类处理

实现代码:

public function dirLoop($path, &$treeData = [])
{
    // 判断给定的 path 是否是一个正确的路径
    if( ! is_dir($path))
    {
        return $path;
    }

    $docList = scandir($path);

    $reg = '/^\.[\w]+$/';
    foreach($docList as $key => $doc)
    {
        if($doc == '.' || $doc == '..' || preg_match($reg, $doc))
        {
            continue;
        }
        else
        {
            $newPath = $path . '/' . $doc;
            if(is_dir($newPath))
            {
                $treeData[$path][$newPath] = [];
                $this->dirLoop($newPath, $treeData[$path]);
            }
            else
            {
                $treeData[$path][$newPath] = 'f';
            }
        }
    }

    return $treeData;
}
复制代码

运行截图:

最后的返回处理需要根据自己的需求进行返回。

【如若文档有错误,欢迎大家不吝赐教。如果发现有侵权等行为,请联系我,我将对应处理,谢谢~~~】

转载于:https://juejin.im/post/5bd7b8366fb9a05cdd2d54f0

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值