xQuery - BFS查找两个节点之间的所有路径

时间:2014-06-24 08:01:43

标签: xquery breadth-first-search exist-db xquery-3.0

我问过2个月左右的问题,我需要帮助在xquery中实现BFS算法,以找到有向图中两个节点之间的最短路径,幸运的是有人帮助我,他们给我的代码与一些未成年人一起工作修改

现在的事情是测试整个程序我得出的结论是我需要找到两个节点之间的所有路径。我现在的代码是:

declare function local:result($steps, $dest) {
let $pred := 
for $node in $steps
return if($node/@to = $dest)then string($node/@from) else ()
return if(exists($pred)) then (local:result($steps, $pred), $dest)
else $dest
};

declare function local:BFS($graph, $start, $end) {
local:BFS($graph, $start, <edge to="{$start}" />, $end, 1)
};

declare function local:BFS($graph, $queue, $steps, $end, $iteracion) {
if(empty($queue)) then error(xs:QName('local:NOTFOUND'), $iteracion)
else (
  let $curr := $queue[1], $rest-queue := $queue[position() > 1]
  return (
     if($curr eq $end) then local:result($steps, $end)
     else (
        let $successors :=  if (empty($graph)) then error(xs:QName('local:NOTFOUND'), 'no grafo') else 
        for $node in $graph/Enlaces/Enlace/origen
        return if(string($node) = $curr) then $graph[Enlaces/Enlace/origen/text() = $node]/id/text() else  ()
        let $new-steps  := 
        for $succ in $successors
          return <edge from="{$curr}" to="{$succ}" />
        return local:BFS( $graph,($rest-queue, $successors),($steps, $new-steps),$end, $iteracion + 1)
  )
)
)};

代码本身正在工作,但只找到两个节点之间的最短路径,它甚至可以找到几条路径,当它们的长度相同但我需要它来查找所有可能的路径。

所以我的问题是如何修改给定的代码以找到所有路径?或者我甚至可以接受另一种算法,如DFS,我知道如何在其他语言中实现,但我不知道如何将其转换为xQuery

我不熟练使用xQuery,也不熟悉函数式编程,所以尽管我尝试过,但我自己也不这样做。

编辑:

此程序的示例输入将是一个图表,例如

<node>
  <id> 123-456-789</id>
  <name> something </name>
  <Links>
     <Link>
        <origin></origin>
     </Link>
  <Links/>

 <node>
  <id> 245-678-901</id>
  <name> node 2</name>
  <Links>
     <Link>
        <origin> 123-456-789 </origin>
     </Link>
  <Links/>

  <node>
  <id> xxx-xxx-xxx</id>
  <name> node 3</name>
  <Links>
     <Link>
        <origin> 123-456-789 </origin>
     </Link>
  <Links>

  <node>
  <id> 234-546-768</id>
  <name> node 4</name>
  <Links>
     <Link>
        <origin> 245-678-901</origin>
     </Link>
  <Links/>

然后,如果我在第一个节点上调用该函数,则必须返回所有后续节点,因为在此示例中第一个节点是“根”,但如果我在节点2上调用该函数,则必须将节点4返回为它的起源是节点2

1 个答案:

答案 0 :(得分:1)

对于所有路径,您也可以使用DFS:

<nodes>
  <node>
    <id>1</id>
    <edges>
      <edge to="2"/>
      <edge to="5"/>
    </edges>
  </node>
  <node>
    <id>2</id>
    <edges>
      <edge to="3"/>
      <edge to="1"/>
    </edges>
  </node>
  <node>
    <id>3</id>
    <edges/>
  </node>
  <node>
    <id>5</id>
    <edges>
      <edge to="3"/>
      <edge to="4"/>
    </edges>
  </node>
  <node>
    <id>4</id>
    <edges>
      <edge to="3"/>
    </edges>
  </node>
</nodes>

然后使用此

declare function local:DFS($graph, $visited as xs:string*, $start, $end) {
  if ($start/id = $end/id) then (string-join($visited, '->')) else (
  for $edge in $start//edge
    return if (not($visited = $edge/@to)) then (local:DFS($graph, ($visited, data($edge/@to)), $graph//node[id = $edge/@to], $end)) else ())
};

declare function local:DFS($graph, $start, $end) {
  local:DFS($graph, ($start/id/text()), $start, $end)
};

local:DFS(., //node[id='1'], //node[id='3'])