2010-01-21 4 views
2

Я пишу текстовый тег парсера, и в настоящее время я использую этот рекурсивный метод для создания тегов n слов. Есть ли способ сделать это нерекурсивно или, по крайней мере, оптимизировать? Предположим, что $ 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

Хм. Он работает, если вы добавите else/break для второго вложенного оператора if. Однако он, как представляется, в среднем примерно такой же скорости, как и рекурсивная функция. – VirtuosiMedia

+0

Прохладный, отредактирует. –

+1

Рекурсия хвоста обычно не считается оптимизацией скорости (хотя разматывание стека требует времени, оно должно быть небольшим по сравнению со всеми конкатенациями строк, которые происходят). Это оптимизация пространства, чтобы предотвратить переполнение стека. –

Смежные вопросы