找到网络节点之间的路径距离?

时间:2013-02-11 18:07:35

标签: ruby recursion graph distance

我正在编写一个网络抓取工具,我需要找到两个网址之间的最小距离。

我用哈希表示网络。不在网络末端的每个节点都被键入到它所连接的节点的向量:

hash = {:v0 => [:v1,  :v2,  :v3],
        :v1 => [:v4,  :v5,  :v6], 
        :v2 => [:v7,  :v8,  :v9],
        :v3 => [:v10, :v11, :v12],
        :v4 => [:v13, :v14, :v15]}

此解决方案无效。问题是我只在找到目标时增加距离(dist变量),因此结果总是1

def path src, target, hash, dist
    return -1 if hash[src] == nil # invalid distance if source is invalid
    return dist += 1 if hash[src].include? target

    arr = Array.new
    for i in hash[src] do
        arr.push path(i, target, hash, dist) 
    end
    arr = arr.delete_if {|x| x < 0} # delete invalid values
    return -1 if arr.empty?
    return arr.min # return the shortest distance
end

如何修复它以便它会在网络的每一层上递增?

2 个答案:

答案 0 :(得分:1)

看起来你还没有完全理解递归的想法。为此,首先写下你的“路径距离”的定义。我引用的原因是我希望你要么想要距离,要么你想要路径(路径的长度是距离),但我真的不知道你需要什么。

现在,重要的原因是,在这种情况下,它可能类似于“路径是从当前URL到目标URL的最短距离”。实现类似于“如果目标URL是直接邻居,距离是1,否则它是距离任何邻居加1的最短距离”。在你的情况下,你传入一个现有的距离,这不是真的错,但不寻常。接下来,如果你在hash[src]中找到了这个URL,那么你增加那个距离(Ruby是按引用传递,BTW?)返回它。那时,我实际上希望你返回1,因为这是当前位置和目标之间的距离。同样,稍后,在将其传递给递归调用之前,您可能还需要递增dist

现在,存在一个完全不同的问题,那就是你的算法效率低下,以至于只有少数几个URL就会变得无用。让我们假设URL连接像“A - X - T”,X是开头,T是目标。如果你运气不好,你首先进入A,这可能是成千上万的URL云。在遍历整个图之后,这些中的每一个都将找到到T的路径。看一下广度优先搜索(BFS)和深度优先搜索(DFS)之间的区别,它将为您提供如何修复它的提示。

还有两件事:

  • 考虑A和A之间的路径。我会说它们的距离是零,你的函数应该处理它。然后距离变为:如果S = T,则距离为零,否则为一加上距离任何邻居的最短距离。
  • 我会尽量避免使用-1表示“未找到”。我宁愿什么都不回报(零?),因为那时你不太可能不小心做任何算术。

答案 1 :(得分:0)

我修好了。这是代码,如果它对某人有帮助。

def distance src, target, hash
    return 0 if src == target
    return nil if hash[src].nil?
    dist = 1

    if hash[src].include? target
        return dist
    else
        arr = hash[src].map {|x| distance x, target, hash}
    end
    arr = arr.delete_if {|x| x.nil?}

    return dist + arr.min if !arr.empty?
    return nil
end