2011-02-02 64 views
2

我想执行特定类型的搜索。我不知道它是否有名字,但我可以描述它,并且有执行代码。在算法中组合循环

对于2维矩阵,起始于点0,0和工作右下,搜索代将如下所示:

  •     1,    4,    9,16, ...
  •     2,    3,    8,15,...
  •     5,    6,    7,第14,...
  • 10,11,12,13,...
  • ...

所以第一搜索循环将检查1 ,第二环路2检查,3,4,所述第三循环检查5,6,7,8,9,等等

产生该搜索中的代码是:

$row_search = 0; 
$point_not_found = true; 

while ($point_not_found && $row_search < $matrix_height/2) 
{ 
    $current = array(0, $row_search); 

    while ($current[0] < $row_search) 
    { 
     if (searchForPoint($matrix, $current) !== false) 
      $point_not_found = false; 

     ++$current[0]; 
    } 

    if (!$anchor_not_found) 
     break; 

    while ($current[1] >= 0) 
    { 
     if (searchForPoint($matrix, $current) !== false) 
      $point_not_found = false; 

     --$current[1]; 
    } 

    ++$row_search; 
} 

我不满意以及如何将搜索分解为两个循环,因为循环内的代码几乎相同。您能否提出一种方法来组合或嵌套循环,并消除searchForPoint的多余呼叫?

回答

3

什么像这样

$pointFound = false; 
$row = 0; 

while(!$pointFound && $row < $matrixSize) 
{ 
    $y = $row; 
    $x = 0; 
    while($y >= 0) 
    { 
     if (searchForPoint($matrix,$x,$y) !== false) 
     { 
      $pointFound = true; 
      break; 
     } 

     // If we reached the right column, start moving upwards (decreasing y) 
     if($x == $row) 
      $y--; 
     // Else move right 
     else 
      $x++; 
    } 
    // EDIT (forgot the next line) 
    $row++; 
} 
0

存在一个办法窝的循环,但你分解的问题分为两个循环的方式很直观,并且最重要的是,已经工作。

假设我们正在评估数学表达式ln(x^2 + 1) - sqrt(x^2 + 1)。把它写成f(x) = ln(g(x)) - sqrt(g(x)), g(x) = x^2 + 1不是很方便吗?这似乎是你问题的本质,这个比喻的意义在于你应该考虑两个功能。

你有一种迭代方法,从左上角到右下角。给这个策略一个名字并且把它作为一个迭代器抽象出来。如果你喜欢使用OOP。然后,你就有了对迭代器给你的每件事都做些什么的概念。给这个东西一个名字,让它使用你的迭代器。附加奖励:您可以在找到一场比赛后立即中止搜索,而不是一段时间之后。

伪代码:

$iterator = new MatrixRippleIterator($matrix); 
$needle = 1337; 
$found_match = false; 
while ($iterator->hasNext()) { 
    $current = $iterator->next(); 
    if ($current == $needle) { 
     $found_match = true; 
     break; 
    } 
}