【问题标题】:Convert function from recursion to iteration将函数从递归转换为迭代
【发布时间】:2009-12-30 22:38:29
【问题描述】:

我写的这个函数非常慢,因为 php 不能很好地处理递归。我正在尝试将其转换为 while 循环,但在思考如何做时遇到了麻烦。

谁能给我一些建议?

    public function findRoute($curLoc, $distanceSoFar, $expectedValue) {

    $this->locationsVisited[$curLoc] = true;
    $expectedValue += $this->locationsArray[$curLoc]*$distanceSoFar;

    $at_end = true;
    for($i = 1; $i < $this->numLocations; $i++) {
        if($this->locationsVisited[$i] == false) {
            $at_end = false;

            if($expectedValue < $this->bestEV)
                $this->findRoute($i, $distanceSoFar + $this->distanceArray[$curLoc][$i], $expectedValue);
        }
    }

    $this->locationsVisited[$curLoc] = false;

    if($at_end) {
        if($expectedValue < $this->bestEV) {
            $this->bestEV = $expectedValue;
        }
    }
}

【问题讨论】:

  • 您是否尝试过将某种调试/打印语句添加到 for 循环的主体中,显示递归发生的时间和次数。从检查来看,代码对我来说有点奇怪。在转换为使用迭代之前,我会检查一下。

标签: php recursion iteration


【解决方案1】:

我不打算转换您的代码,但您可以通过创建堆栈将递归函数转换为迭代函数:

$stack= array();

不要调用$this-&gt;findroute(),而是将参数推送到此堆栈:

$stack[] = array($i, $distanceSoFar + $this->distanceArray[$curLoc][$i], $expectedValue);

现在基本上将函数中的所有内容都包含在一个 while 循环中,在启动后排空堆栈:

while ($stack) { 
    // Do stuff you already do in your function here

【讨论】:

  • 这给了我一个良好的开端,但我无法弄清楚如何处理回溯步骤。我需要设置 $this->locationsVisited[$curLoc] = true 然后迭代它为 true 然后再次将其关闭。
【解决方案2】:

您可以通过使用堆栈来存储当前状态,将递归函数转换为迭代函数。查看array_push()array_pop()

【讨论】:

    【解决方案3】:

    乍一看,我不认为递归是你的问题,是的,它在 PHP 中很慢,但看起来你对值的处理超出了你的需要,将值放在一个堆栈或几个堆栈中并处理它们,可能很好。

    自定义排序功能一直帮助我解决此类问题。

    function sort_by_visited($x,$y)
    {
       return ($this->locationsVisited[$x] > $this->locationsVisited[$y]) ? -1 : 1;
    }
    
    uasort($locationsVisited,'sort_by_visited');
    

    这将优先考虑堆栈顶部的所有未访问位置。

    【讨论】:

      【解决方案4】:

      这看起来像是您试图找到遍历图中一系列节点的最佳路线。

      我猜你没有学过计算机科学,因为“旅行推销员”问题是人工智能的一个原型。当然,它也有自己的维基百科页面:

      http://en.wikipedia.org/wiki/Travelling_salesman_problem

      抱歉 - 但只是从递归函数切换到迭代函数不会让它更快(“php 不能很好地处理递归。” - 你能提供这个断言的参考吗)。如果您需要更快的解决方案,则需要查看非详尽/模糊的方法。

      C.

      【讨论】:

      • "[7 Aug 1999 12:25pm UTC] zeev at cvs dot php dot net PHP 4.0 (Zend) 将堆栈用于密集数据,而不是使用堆。这意味着它的容差递归函数明显低于其他语言。告诉 Zend 不要使用堆栈来存储这些数据相对容易,而是使用堆来代替 - 这将大大增加可能的递归函数的数量 - 以降低速度为代价。如果你'对这样的设置感兴趣,告诉我,我们可能会添加一个编译时开关。”我可能应该切换到 C 或其他东西..
      • 它对性能或可靠性没有说“容忍” - 我想你会发现这个语句的含义是递归因此受到堆栈大小的限制(默认情况下比在大多数设置中堆。将您的开发切换到 C 不会降低算法的顺序 - 它仍然是 N!C。
      猜你喜欢
      • 1970-01-01
      • 2020-08-08
      • 2015-05-30
      相关资源
      最近更新 更多