【问题标题】:Locating element in a nested tree - JavaScript在嵌套树中定位元素 - JavaScript
【发布时间】:2016-12-16 23:22:11
【问题描述】:

在编写函数以搜索示例树中的元素时需要帮助。

var sampletree = [
  "a",
  "b",
  "c",
  [
    "d",
    "e",
    [
      "f",
      "h",
      "i",
      [
        "z",
        "x"
      ]
    ]
  ],
  [
    "y",
    "q",
    "t",
    [
      "m",
      "n",
      [
        "o",
        "p"
      ],
      [
        "r",
        "s",
        [
          "u",
          "v"
        ]
      ]
    ]
  ],
  "g"
]

希望通过仅使用 javascript 而没有框架/库的广度优先搜索在树中搜索内部元素(例如 o、p、u、v)来返回真/假。

我用for循环遍历然后.indexOf但无法获取。

【问题讨论】:

  • 那么如果你搜索“u”,你想要什么作为返回值?
  • 为什么在您的问题上标记了 [dom]?您是否尝试手动遍历 DOM?不要那样做。

标签: javascript dom search tree breadth-first-search


【解决方案1】:

你可以使用这个功能:

function findNodeBFS(tree, node) {
    var queue = tree.slice();
    for (var i = 0; i < queue.length; i++) {
        if (queue[i] === node) return true;
        if (Array.isArray(queue[i])) queue = queue.concat(queue[i]);
    }
    return false;
}

var sampletree = [ "a", "b", "c", [ "d", "e", [ "f", "h", "i", [ "z", "x" ] ] ], [ "y", "q", "t", [ "m", "n", [ "o", "p" ], [ "r", "s", [ "u", "v" ] ] ] ], "g" ];

console.log(findNodeBFS(sampletree, "u")); // true
console.log(findNodeBFS(sampletree, "j")); // false

说明

此算法维护一个queue,您可以将其视为一种“待办事项”列表。它从树的副本开始。代码遍历节点,但仅限于顶级节点。每当它遇到一个代表更深层次的数组时,这些孩子就会被添加到队列的末尾,意思是:“我稍后再处理你”

这就是这行代码发生的事情:

if (Array.isArray(queue[i])) queue = queue.concat(queue[i]);

所以如果queue[i] 是一个数组,它的元素会被追加1(浅拷贝)到队列中。

1 其实concat不会改变给定的数组,而是产生一个新的,就是queue的串联队列[i]。通过将该新数组分配回 queue,我们获得了追加的效果。取而代之的是,我们可以使用 [].push.apply(queue, queue[i]),通过就地附加第二个来改变第一个。但它可能看起来有点神秘。

请注意,我们不附加我们找到的数组,而是附加中的每个元素。因此,当循环到达附加数据时,它实际上将访问原始树的更深层次。这确实是BFS的意思:先访问你当前所在关卡的节点,完成当前关卡后再处理更深的关卡。队列(先进先出)是实现这一目标的理想数据结构。

深度优先搜索变体

DFS 变体将是这个递归 ES6 函数:

function findNodeDFS(tree, node) {
    return Array.isArray(tree) && tree.some( val => findNode(val, node) ) 
           || node === tree;
}

【讨论】:

  • 啊,是的,感谢您强调 @4castle。把它变成了 BFS 版本。
  • 你能解释一下“if (Array.isArray(queue[i])) queue = queue.concat(queue[i]);”给我的代码@trincot
  • 我添加了一些解释。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-01-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多