2010-01-21 68 views
2

我正在寫一個文本標籤解析器和我目前使用這種遞歸的方法來創建的ň字標籤。有沒有辦法可以非遞歸地完成或至少進行優化?假設$ this-> dataArray可能是一個非常大的數組。優化遞歸方法在PHP

/** 
* A recursive function to add phrases to the tagTracker array 
* @param string $data 
* @param int $currentIndex 
* @param int $depth 
*/ 
protected function compilePhrase($data, $currentIndex, $depth){ 
    if (!empty($data)){ 
     if ($depth >= $this->phraseStart){ 
      $this->addDataCount($data, $depth); 
     } 
     if ($depth < $this->phraseDepth){ 
      $currentIndex = $currentIndex + 1; 
      //$this->dataArray is an array containing all words in the text 
      $data .= ' '.$this->dataArray[$currentIndex]; 
      $depth += 1; 
      $this->compilePhrase($data, $currentIndex, $depth); 
     } 
    } 
} 

回答

3

看看你能不能用tail recursion,而不是基於調用的遞歸。一些重寫可能是必需的,但粗略的看起來可以做。

尾遞歸是偉大的遞歸函數的一個子集,以及良好的實踐發現,當循環可以替代遞歸,以及如何改寫。

這麼說,我不知道里面有什麼PHP的開銷是電話的。可能只是一個返回指針類型的設置,而不是真正的堆棧風。

原來差不多。 PHP是否優化自己的尾部遞歸調用?

這是我的重寫,但要小心,我的大腦現在睡眠不足了!

protected function compilePhrase($data, $currentIndex, $depth){ 
    /* Loop until break condition */ 
    while(true) { 
     if (!empty($data)){ 
      if ($depth >= $this->phraseStart){ 
       $this->addDataCount($data, $depth); 
      } 
      if ($depth < $this->phraseDepth){ 
       $currentIndex = $currentIndex + 1; 
       // A test here might be better than the !empty($data) 
       // in the IF condition. Check array bounds, assuming 
       // array is not threaded or anything 
       $data .= ' '.$this->dataArray[$currentIndex]; 
       $depth += 1; 
      }else{ 
       break; 
      } 
     }else{ 
      break; 
     } 
    } 
    /* Finish up here */ 
    return($this->dataArray); 
} 
+0

嗯。如果爲第二個嵌套的if語句添加else/break,它將起作用。但是,它似乎與遞歸函數的平均速度大致相同。 – VirtuosiMedia 2010-01-21 05:58:15

+0

很酷,會編輯。 – 2010-01-21 05:59:39

+1

尾遞歸通常不被視爲速度優化(儘管展開堆棧確實需要時間,但與所有正在進行的字符串連接相比,它應該很小)。這是一個空間優化,以防止您溢出堆棧。 – 2010-01-21 19:56:13