2017-05-07 4 views
4

mondial.sql 데이터베이스를 사용하여 육로를 통해 한 나라에서 다른 나라로 이동하여 육로로 도달 할 수있는 모든 국가를 찾으려고합니다. 재귀 적으로 수행되어야하며, 시퀀스에 가입하고 이미 발견 된 국가를 제외 할 수 있다고 생각되는 온라인 기능을 온라인에서 찾았습니다.XQuery에서 재귀를 처리하는 방법?

제외 할 국가가 제대로 처리되는 것처럼 보이지만 문제는 결국 루프에 있습니다. 따라서 가능한 모든 국가가 발견되면 재귀를 중지시키기 위해 기본 케이스를 정의해야 할 수도 있습니다. XQuery로이를 수행하는 방법은 무엇입니까? $reachedCountries

(:functx.value-union and is-value-in-sequence were found at http://www.xqueryfunctions.com/xq/:) 
declare namespace functx = "http://www.functx.com"; 
declare function functx:value-union 
    ($arg1 as xs:anyAtomicType* , 
    $arg2 as xs:anyAtomicType*) as xs:anyAtomicType* { 

    distinct-values(($arg1, $arg2)) 
}; 

declare function functx:is-value-in-sequence 
    ($value as xs:anyAtomicType? , 
    $seq as xs:anyAtomicType*) as xs:boolean { 

    $value = $seq 
} ; 

(:Recursive function for finding reachable countries:) 
declare function local:findReachable($countries, $country, $reachedCountries) { 
    let $reachableCountries := $countries[@car_code = $country/border/@country] 
    for $c in $reachableCountries 
    where not(functx:is-value-in-sequence($c, $reachedCountries)) 
    return functx:value-union($c, local:findReachable($countries, $c, functx:value-union($reachableCountries, 
    $reachedCountries))) 
}; 

let $countries := //country 
let $startingCountry := //country[@car_code = 'S'] 
return local:findReachable($countries, $startingCountry, $startingCountry) 

답변

6

귀하의 검사는 국가가 동일한 경로에 두 번 을 표시되지 않습니다,하지만 당신은 여전히 ​​시간이 오래 걸리는 모든 가능한 경로를 따라 모든 국가를 방문 보장합니다. 루프가 없으며 많은 중복성이 있습니다. 여기

당신이 원하는 않는 간단한 깊이 우선 검색입니다 :

declare function local:dfs($stack, $seen) { 
    if(empty($stack)) then $seen 
    else (
    let $country := $stack[1] 
    let $neighbors := 
     for $code in $country/border/@country[not(. = $seen/@car_code)] 
     return $country/../country[@car_code = $code] 
    return local:dfs(($neighbors, $stack[position() > 1]), ($seen, $neighbors)) 
) 
}; 

local:dfs(doc('mondial.xml')//country[@car_code = 'S'],())/name 
관련 문제