Я хочу сделать обход глубины для этого двоичного дерева:
1
/ \
4 5
/ \ \
4 4 5
Здесь структура узла:
function TreeNode(data){
this.data = data
this.left = this.right = []
this.addLeft = function(node){
this.left.push(node)
}
this.addRight = function(node){
this.right.push(node)
}
}
Функция посещения (только для распечатки данных узла):
function visit(node){
console.log(node.data)
}
Поперечная функция:
function traverse(node){
if(node === null) return
visit(node)
//visit left branch
for(node of node.left) traverse(node)
//visit right branch
for(node of node.right) traverse(node)
}
Добавьте двоичную древовидную структуру:
let rootNode = new TreeNode(1)
let node_4A = new TreeNode(4)
let node_4B = new TreeNode(4)
let node_4C = new TreeNode(4)
let node_5A = new TreeNode(5)
let node_5B = new TreeNode(5)
//add root node branches
rootNode.addLeft(node_4A)
rootNode.addRight(node_5A)
node_4A.addLeft(node_4B)
node_4A.addRight(node_4C)
node_5A.addRight(node_5B)
Выход:
1
4
4
4
5
5
5
Таким образом, он правильно выводит данные узла, но всегда есть дополнительный правый узел, который дважды печатается (т.е. последние 5
). У вас есть идеи, почему это происходит?
Я не слишком хорошо знаком с стеклом вызовов Javascript, но может быть причина, по которой я запускаю 2 for
циклов в рекурсивной функции?
Спасибо.
Вы берете ту же ссылку на объект для левой и правой.
this.left = this.right = []
Вам нужны независимые массивы:
this.left = [];
this.right = [];
Для принятия правильного узла используйте разные имена, кроме node
для итерации.
function traverse(node) {
if (!node) return; // you never have a value of null for a node
visit(node)
//visit left branch
for (let n of node.left) {
traverse(n);
}
//visit right branch
for (let n of node.right) {
traverse(n);
}
}
function TreeNode(data) {
this.data = data
this.left = [];
this.right = [];
this.addLeft = function (node) {
this.left.push(node)
}
this.addRight = function (node) {
this.right.push(node)
}
}
function visit(node) {
console.log(node.data)
}
function traverse(node) {
if (!node) return; // you never have a value of null for a node
visit(node)
for (let n of node.left) {
traverse(n);
}
for (let n of node.right) {
traverse(n);
}
}
let rootNode = new TreeNode(1)
let node_4A = new TreeNode(4)
let node_4B = new TreeNode(4)
let node_4C = new TreeNode(4)
let node_5A = new TreeNode(5)
let node_5B = new TreeNode(5)
//add root node branches
rootNode.addLeft(node_4A)
rootNode.addRight(node_5A)
node_4A.addLeft(node_4B)
node_4A.addRight(node_4C)
node_5A.addRight(node_5B)
traverse(rootNode);
Ты делаешь это:
this.left = this.right = []
Таким образом, левый лист на самом деле тот же, что и правый. Ты хочешь:
this.left = [];
this.right = [];
Просто для удовольствия: на самом деле это будет хорошая утилита для генераторов:
TreeNode.prototype.leftFirst = function*() {
yield this.data;
for(const child of this.left.concat(this.right))
yield* child.leftFirst();
};
Таким образом, вы можете:
for(const node of tree.leftFirst())
console.log(node);
*
после function
?
left
иright
массивов, а вторая использует одно и то же имя переменной в функцииtraverse
. Является лиlet
необходимо? Потому что я считаю, что код работает нормально:for(currentNode of node.left) traverse(currentNode)
я не используюlet
. Будет ли это проблемой позже?