有向循环图遍历算法(JavaScript)

有向循环图遍历算法(JavaScript),javascript,language-agnostic,graph,traversal,Javascript,Language Agnostic,Graph,Traversal,我有一个连通的,有向的,循环图。任务是发现图中的每个节点,而不会像常规的树遍历算法那样陷入无限循环 您可以假设我已经知道从哪个节点开始,以便到达有向图中的所有点,并且对于每个节点,我都有一个函数返回它指向的节点。是否存在查找所有节点的已知算法 主要的问题是真正避免循环,如果有一种方法可以做到这一点,而不必跟踪每个节点并将其与已经遍历的节点列表进行比较,我会很高兴 如果需要更多详细信息,实际任务是获取JavaScript中每个命名函数的列表,包括作为其他对象属性的函数。因此,我尝试了以下方法,因为

我有一个连通的,有向的,循环图。任务是发现图中的每个节点,而不会像常规的树遍历算法那样陷入无限循环

您可以假设我已经知道从哪个节点开始,以便到达有向图中的所有点,并且对于每个节点,我都有一个函数返回它指向的节点。是否存在查找所有节点的已知算法

主要的问题是真正避免循环,如果有一种方法可以做到这一点,而不必跟踪每个节点并将其与已经遍历的节点列表进行比较,我会很高兴

如果需要更多详细信息,实际任务是获取JavaScript中每个命名函数的列表,包括作为其他对象属性的函数。因此,我尝试了以下方法,因为我认为JS对象之间的相互引用形成了一棵树(但当然不是):

function\uu findffunctions(obj){
用于(obj中的var f){
//对于带自变量的边的特殊情况
如果(obj==obj[f]){
持续
}
如果(对象类型[f]=“功能”&&
对象hasOwnProperty(f)&&
//排除本机函数,我们只需要用户定义的函数
!(/\[(本机\scode |对象\sffunction)\]/i.test(obj[f].toString())&&
//排除前缀为_u的函数
!(/^\s*函数\s*。/).test(obj[f].toString())
){
document.write(f+“
”+obj[f].toString()+“
”); } //警报(obj[f]+“\n”+obj+“\n”+obj[f]+“\n”+f的类型) __findFunctions(obj[f]); } } __findFunctions(窗口);

此代码的问题在于它会陷入循环中。

如果要避免循环,则需要维护已访问节点的列表

例如

如果有一种方法可以做到这一点,而不必跟踪每个节点并将其与已经遍历的节点列表进行比较,我会很高兴

它可能没有检查已遍历节点的列表那么糟糕。相反,您可以为每个节点提供某种类型的唯一ID:

// psuedo
id=0;
for each node
    node.id = id++;
等等

然后,可以在遍历时将每个节点的ID添加到哈希中:

var alreadyTraversed = {};

// Traversing a node:
alreadyTraversed[node.id] = true;
node._traversed = true;

// Later:
if (someNode._traversed) // already traversed.
稍后,当您需要检查其是否已被遍历时:

if (node.id in alreadyTraversed) // It's already been traversed...

或者,对于真正基本的解决方案,只需在您遍历的每个对象上设置一些属性:

var alreadyTraversed = {};

// Traversing a node:
alreadyTraversed[node.id] = true;
node._traversed = true;

// Later:
if (someNode._traversed) // already traversed.

请忽略正则表达式,在这个问题的上下文中不太重要。虽然我很想知道是否有更好的方法来区分用户定义函数和本机函数。但很遗憾,您的伪代码无法工作,因为每个节点的
实际上就是我所寻求的图形遍历算法。然而,如果JS允许的话,它确实给了我一个想法:使用节点对象本身作为ID,而不是整数。我在Ruby中做过类似的事情,我将在JS中尝试一下。谢谢@ehsanul:看我的第二个建议方案:)啊,好主意。这不仅是初步的,而且是正确的解决方案。现在我可以睡觉了,知道有一个合理的解决方案让我醒来。你不会碰巧知道除了字符串之外,哪些JS对象不能有属性,是吗?
Null
未定义的
字符串
布尔
数字
。。。虽然从技术上讲,后三个可以有属性,但它们不会保留它们,因为它们没有包装(请尝试
newstring()
而不是…)