【问题标题】:Depth First Traversal with Javascript使用 Javascript 进行深度优先遍历
【发布时间】:2018-02-05 04:43:56
【问题描述】:

我一直在阅读以下文章: https://code.tutsplus.com/articles/data-structures-with-javascript-tree--cms-23393

这设置了以下类和方法。

function Node(data) {
    this.data = data;
    this.parent = null;
    this.children = [];
}

function Tree(data) {
    var node = new Node(data);
    this._root = node;
}

Tree.prototype.traverseDF = function(callback) {
    (function recurse(currentNode) {
        for (var i = 0, length = currentNode.children.length; i < length; i++) {
            recurse(currentNode.children[i]);
        }

        callback(currentNode);
    })(this._root);

};
var tree = new Tree('one');

tree._root.children.push(new Node('two'));
tree._root.children[0].parent = tree;

tree._root.children.push(new Node('three'));
tree._root.children[1].parent = tree;

tree._root.children.push(new Node('four'));
tree._root.children[2].parent = tree;

tree._root.children[0].children.push(new Node('five'));
tree._root.children[0].children[0].parent = tree._root.children[0];

tree._root.children[0].children.push(new Node('six'));
tree._root.children[0].children[1].parent = tree._root.children[0];

tree._root.children[2].children.push(new Node('seven'));
tree._root.children[2].children[0].parent = tree._root.children[2];

这棵树看起来像

 one
 ├── two
 │   ├── five
 │   └── six
 ├── three
 └── four
     └── seven

所以当我们最终进行遍历调用时

tree.traverseDF(function(node) {
    console.log(node.data)
});

返回:

five
six
two
three
seven
four
one

这打破了我对“深度优先”的理解。如果你先谷歌深度,维基百科有以下图片:

在这张图片下感觉应该打印之前的代码:

one
two
five 
six

根据维基百科:

从根开始(在图的情况下选择某个任意节点作为根)并在回溯之前沿着每个分支尽可能地探索

这个问题中的当前实现实际上是从底部开始打印,最小的孩子并向上移动而不是从上到下移动它是如何由维基百科定义的。谁能帮我理解我错过了什么?

【问题讨论】:

    标签: javascript tree


    【解决方案1】:

    您的代码确实执行了深度优先搜索,但在决定何时将节点视为“已访问”时仍有灵活性:它是在第一次遇到时,还是在回溯时?

    如果你在循环之前移动你的console.log,你会得到你所期望的:

    Tree.prototype.traverseDF = function(callback) {
        (function recurse(currentNode) {
            callback(currentNode); // <-----
            for (var i = 0, length = currentNode.children.length; i < length; i++) {
                recurse(currentNode.children[i]);
            }
        })(this._root);
    };
    

    这里没有对错。

    实际上有三种口味。见Wikipedia

    • 预购(如您所愿)
    • 有序(与二叉树相关)
    • 后订购(您的版本)

    【讨论】:

    • 请问这是如何自我终止的?是因为当不再有孩子时,绕过了 for 循环并调用了回调?作为问题的一部分,我忘了问这个。
    • 它是自终止的,因为对没有子节点的树的叶子没有递归调用,因此循环对这些叶子没有任何迭代。在这种情况下,唯一发生的事情就是回调函数的调用,并且递归回溯到前一个调用。在那里循环将进入下一次迭代,......等等。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-08-10
    • 2019-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多