I'm stuck with recursion. I've read a few similar questions, but it brought me no relief. My function works well inside, but it returns "undefined" at the end.
I have a binary tree. Now I'm trying to make a function, which can get me an answer: if any nodes on this level have children.
class tree_node {
constructor(n_array, parent) {
this.n_array = n_array;
this.has_children = false;
this.children = [];
if (parent != null) {
this.parent = parent;
this.level = this.parent.level + 1;
}
else {
this.level = 0;
}
// run the tree
this.child();
}
child() {
if (this.n_array.length != 1) {
this.has_children = true;
let m = Math.floor(this.n_array.length / 2);
let l = this.n_array.slice(0, m);
let r = this.n_array.slice(m);
const left = new tree_node(l, this);
const right = new tree_node(r, this);
this.children.push(left, right);
}
else return 0
}
get_if_node_has_children(node, level) {
console.log(node.level, node.has_children)
if (node.has_children && node.level < level) {
console.log("in loop")
node.children.forEach(element => {
return element.get_if_node_has_children(element, level);
});
}
else {
console.log("first else")
if (node.level == level && node.has_children) {
console.log("node.level == level && node.has_children " + node.n_array)
return true;
}
else {
console.log("return false")
return false;
}
}
}
show() {
console.log(this.n_array + " | Level: " + this.level + ". " + this.branch + " Has children = " + this.has_children);
if (this.has_children) {
this.children.forEach(element => {
return element.show();
});
}
else {
return 0;
}
}
}
get_if_node_has_children(node, level)
work inside, so to speak. I've expected the exact behaviour and log. Except on thing: function returns "undefined". But I have no idea where I missed the point.
let root = [];
class tree_node {
constructor(n_array, parent) {
this.n_array = n_array;
this.has_children = false;
this.children = [];
// при создании экземпляра класса то parent == null
if (parent != null) {
this.parent = parent;
this.level = this.parent.level + 1;
} else {
this.level = 0;
}
// run the tree
this.child();
}
child() {
if (this.n_array.length != 1) {
this.has_children = true;
let m = Math.floor(this.n_array.length / 2);
let l = this.n_array.slice(0, m);
let r = this.n_array.slice(m);
const left = new tree_node(l, this);
const right = new tree_node(r, this);
this.children.push(left, right);
} else return 0
}
get_if_node_has_children(node, level) {
console.log(node.level, node.has_children)
if (node.has_children && node.level < level) {
console.log("in loop")
node.children.forEach(element => {
return element.get_if_node_has_children(element, level);
});
} else {
console.log("first else")
if (node.level == level && node.has_children) {
console.log("node.level == level && node.has_children " + node.n_array)
return true;
} else {
console.log("return false")
return false;
}
}
}
show() {
console.log(this.n_array + " | Level: " + this.level + ". " + "Has children = " + this.has_children);
if (this.has_children) {
this.children.forEach(element => {
return element.show();
});
} else {
return 0;
}
}
// CLASS END ===========================
}
root = new tree_node([1, 3, 5, 7, 9, ])
console.log("=== root.show() ===")
root.show();
console.log("=== let a = root.get_if_node_has_children(root, 2) ===")
let a = root.get_if_node_has_children(root, 2)
console.log(" a is " + a)
There are two problems:
return
inside a callback (for instance, your forEach
callback) just returns from the callback, not the function that called forEach
. In general, in modern code, use for-of
unless you need the index of the element.
You're not checking the result of the recursive call before returning it. But if the first child node you call it on returns false
, you want to keep looking, rather than immediately returning false
.
Fixing both:
get_if_node_has_children(node, level) {
console.log(node.level, node.has_children)
if (node.has_children && node.level < level) {
console.log("in loop")
for (const element of node.children) { // *** #1, using `for-of` instead of `forEach` so we can return below
const hasChild = element.get_if_node_has_children(element, level);
if (hasChild) { // *** #2, only return here if you got `true`
return true; // ***
} // ***
}
return false; // *** #2 part 2 -- didn't find it anywhere, return `false`
} else {
console.log("first else")
if (node.level == level && node.has_children) {
console.log("node.level == level && node.has_children " + node.n_array)
return true;
} else {
console.log("return false")
return false;
}
}
}
I'd reorganize that slightly though, which is easier if I remove some no-longer-needed logging:
get_if_node_has_children(node, level) {
console.log(node.level, node.has_children)
if (node.has_children) {
if (node.level === level) {
return true;
}
if (node.level < level) {
for (const element of node.children) {
if (element.get_if_node_has_children(element, level)) {
return true;
}
}
}
}
return false;
}