I was building a tree traverse function and it has to use recursion.
What I want the output to be is
'{"value":9,"left":{"value":4,"left":{"value":1},"right":{"value":6}},"right":{"value":20,"left":{"value":15},"right":{"value":170}}}'
Could someone figure out how to use recursion in the traverse function to get the output?
Here is my JS:
class Node {
constructor(value){
this.left = null;
this.right = null;
this.value = value;
}
}
class BinarySearchTree {
constructor(){
this.root = null;
}
insert(value){
const newNode = new Node(value);
if (this.root === null) {
this.root = newNode;
} else {
let currentNode = this.root;
while(true){
if(value < currentNode.value){
//Left
if(!currentNode.left){
currentNode.left = newNode;
return this;
}
currentNode = currentNode.left;
} else {
//Right
if(!currentNode.right){
currentNode.right = newNode;
return this;
}
currentNode = currentNode.right;
}
}
}
}
}
const tree = new BinarySearchTree();
tree.insert(9)
tree.insert(4)
tree.insert(6)
tree.insert(20)
tree.insert(170)
tree.insert(15)
tree.insert(1)
JSON.stringify(traverse(tree.root))
// 9
// 4 20
//1 6 15 170
function traverse(node) {
const tree = { value: node.value };
tree.left=node.left
if(node.left===null) {
return null
}else{
traverse(node.left);
}
tree.right=node.right
if(node.right===null) {
return null
}else{
traverse(node.right);
}
}
You're on the right track; I see that you need specially-formatted objects in your result string. I recommend starting by checking whether the current node is null; if so, return nothing (this key will be ignored by the calling function). Otherwise, create a node object to prepare for return and traverse left and right children. After traversing both subtrees recursively, return the root node. This will build the result structure up from the leaves and end with the root.
In your code,
if(node.left===null) {
return null
is a bit premature, for example. If node has a right subtree, we don't want to abandon traversing it. It's also necessary to return something to the caller in all cases except for empty children.
Also, you may consider putting traverse in the BinaryTree class and have it operate on its member field; I left it as-is in the below example.
Lastly, this is a pre-order traversal; visit the root first, then the left and right subtrees.
function traverse(node) {
if (node) {
const left = traverse(node.left);
const right = traverse(node.right);
return {
value: node.value,
[left&&"left"]: left,
[right&&"right"]: right
};
}
}
class Node {
constructor(value, left=null, right=null) {
this.value = value;
this.left = left;
this.right = right;
}
}
class BinarySearchTree {
constructor() {
this.root = null;
}
insert(value) {
const newNode = new Node(value);
if (this.root === null) {
this.root = newNode;
}
else {
let currentNode = this.root;
while (true) {
if (value < currentNode.value) {
if (!currentNode.left) {
currentNode.left = newNode;
return this;
}
currentNode = currentNode.left;
}
else {
if (!currentNode.right) {
currentNode.right = newNode;
return this;
}
currentNode = currentNode.right;
}
}
}
}
}
const tree = new BinarySearchTree();
tree.insert(9);
tree.insert(4);
tree.insert(6);
tree.insert(20);
tree.insert(170);
tree.insert(15);
tree.insert(1);
console.log(JSON.stringify(traverse(tree.root)));
console.log(traverse(tree.root));
// 9
// 4 20
// 1 6 15 170
Related
I wrote the small class below for playing with a binary tree. Is it possible to do depth first search with out recursion?
It looks like you might need a queue to remember where you are in the traversal, but I'm not sure.
Is there a way to do it with out adding another data structure?
class Node {
constructor(data) {
this.left = null;
this.right = null;
this.data = data;
}
}
class BinaryTree {
constructor(data) {
this.root = new Node(data);
this.makeTree();
}
makeTree(){
this.insert(15);
this.insert(5);
this.insert(7);
this.insert(3);
this.insert(20);
this.insert(13);
}
insert(data) {
let iter = this.root;
let node = new Node(data);
while(iter) {
if(iter.left && (node.data < iter.data)){
iter = iter.left;
}
if(!iter.left && (node.data < iter.data)){
iter.left = node;
return;
}
if(iter.right && (node.data >= iter.data)){
iter = iter.right;
}
if(!iter.right && (node.data >= iter.data)){
iter.right = node;
return;
}
}
}
df() {
function dfInner (node) {
if(node === null) {
return node;
}
// pre order
dfInner(node.left);
// in order
dfInner(node.right);
// post order
}
dfInner(this.root);
}
}
const tree = new BinaryTree(10);
tree.df();
I am getting undefined after the node is inserted in the tree, don't know why is that happening. Here's what is happening - after the node is inserted, the function should return true, but it instead returns undefined. After inserting the node, the code doesn't stop and goes back to if check condition, sets 'current' to '7', this keeps happening until 'current' is '10'(root value) and then it finally goes back to insert() function which returns undefined. My only problem is that why is it returning undefined, and why is it going back to root after inserting the node in the desired place. Can someone please tell me? Am I missing something very small?
by the way, the value I inserted is 8. tree.insert(8);
class Node{
constructor(val){
this.val = val;
this.left = null;
this.right = null;
}
}
class BinarySearchTree{
constructor(){
this.root = null;
}
insert(val){
if(!this.root){
this.root = newNode;
return this;
}
let newNode = new Node(val);
if(val === this.root.val)return false;
function recursiveInsert(current,newNode){
if(newNode.val === current.val)return false;
if(newNode.val > current.val){
if(!current.right){
current.right = newNode;
return true;
}
recursiveInsert(current.right,newNode);
}
if(newNode.val<current.val){
if(!current.left){
current.left = newNode;
return true;
}
recursiveInsert(current.left, newNode);
}
}
return recursiveInsert(this.root,newNode);
}
}
let tree = new BinarySearchTree();
tree.root = new Node(10);
tree.root.left = new Node(7);
tree.root.right = new Node(15);
tree.root.left.right = new Node(9);
There are these issues:
In the if(!this.root){ block, you reference newNode before it has received a value, so move the initialisation of newNode before this if statement.
In the same block you return this, but you write that you want to return a boolean, so change that to return true;
The recursive calls should be used to return whatever that call returned, so prefix them with return, just like you have done in the last line where you made that initial call.
Demo
I would also suggest building the initial tree with the insert method. And add an iterator so you can have a quick output of your tree in inorder sequence.
Note that there is an else if condition that is always true, so just use else:
class Node {
constructor(val) {
this.val = val;
this.left = null;
this.right = null;
}
// Add this method for inorder traversal of the values
* inorder() {
if (this.left) yield * this.left.inorder();
yield this.val;
if (this.right) yield * this.right.inorder();
}
}
class BinarySearchTree {
constructor() {
this.root = null;
}
insert(val) {
let newNode = new Node(val); // First create the node
if (!this.root) {
this.root = newNode;
return true; // you wanted a boolean
}
// This is not necessary: it already happens in the function below
// if(val === this.root.val)return false;
function recursiveInsert(current,newNode) {
if (newNode.val === current.val) return false;
if (newNode.val > current.val) {
if (!current.right) {
current.right = newNode;
return true;
}
// Return the result
return recursiveInsert(current.right, newNode);
} else { // it is the only possibility left
if (!current.left) {
current.left = newNode;
return true;
}
// Return the result
return recursiveInsert(current.left, newNode);
}
}
return recursiveInsert(this.root, newNode);
}
}
let tree = new BinarySearchTree();
// Build the tree only with the insert-method
tree.insert(10);
tree.insert(7);
tree.insert(15);
tree.insert(9);
tree.insert(8); // Add the value you wanted to test with
tree.insert(15); // Try some duplicate
console.log(...tree.root.inorder());
You can make the code still a bit nicer by making the recursive insert function a method of the Node class. Also, enrich the BinarySearchTree constructor, so that it can get a number of values to start with, much like the native Array constructor works.
class Node {
constructor(val) {
this.val = val;
this.left = null;
this.right = null;
}
* inorder() {
if (this.left) yield * this.left.inorder();
yield this.val;
if (this.right) yield * this.right.inorder();
}
insert(val) {
if (val === this.val) return false;
if (val > this.val) {
if (this.right) return this.right.insert(val);
this.right = new Node(val);
} else {
if (this.left) return this.left.insert(val);
this.left = new Node(val);
}
return true;
}
}
class BinarySearchTree {
constructor(...values) {
this.root = null;
for (let val of values) this.insert(val);
}
* inorder() {
if (this.root) yield * this.root.inorder();
}
insert(val) {
if (this.root) return this.root.insert(val);
this.root = new Node(val);
return true;
}
}
let tree = new BinarySearchTree(10, 7, 15, 9);
tree.insert(8);
tree.insert(15);
console.log(...tree.inorder());
You should return the recursiveCall or you will get undefined because the recursive call take time to execute and the function won't wait for it to return something.
// ...code
return recursiveInsert(current.right,newNode);
// and
return recursiveInsert(current.left,newNode);
class Node {
constructor(val) {
this.value = val;
this.left = null;
this.right = null;
}
}
class BinarySearchTree {
constructor() {
this.root = null;
}
insert(val) {
var node = new Node(val);
if(!this.root) {
this.root = node;
return this;
} else{
var root = this.root;
while(root) {
if(val === root.value) return undefined;
if(val < root.value) {
if(!root.left) {
root.left = node;
return this;
} else{
root = root.left;
}
} else if(val > root.value) {
if(!root.right) {
root.right = node;
return this;
} else{
root = root.right;
}
}
}
}
}
}
var bts = new BinarySearchTree();
bts.insert(100);
I get an infinite loop most of the time with this method, I have no idea why, can anybody please help me to find the error in my code, Sometime this methods works fine, but other times an infinite loop. Thank you
In the last method dfs(), after the node will be '1' the two if statement will not go into and it will go until the return statement without any line that call the method again, !!!but it call it self again!!!
who does that come?
I'm using JS.
Here is the code with online compiler: https://repl.it/repls/EnchantingSpanishBlockchain
class Node {
constructor(value) {
this.left = null;
this.right = null;
this.value = value;
}
}
class BinarySearchTree {
constructor() {
this.root = null;
}
insert(value) {
const newNode = new Node(value);
if (this.root === null) {
this.root = newNode;
} else {
let currentNode = this.root;
while (true) {
if (value < currentNode.value) {
//Left
if (!currentNode.left) {
currentNode.left = newNode;
return this;
}
currentNode = currentNode.left;
} else {
//Right
if (!currentNode.right) {
currentNode.right = newNode;
return this;
}
currentNode = currentNode.right;
}
}
}
}
}
function dfs(node, list) {
if (node.left) {
dfs(node.left, list);
}
if (node.right) {
dfs(node.right, list);
}
list.push(node.value);
return list;
}
// 9
// 4 20
//1 6 15 170
const tree = new BinarySearchTree();
tree.insert(9)
tree.insert(4)
tree.insert(6)
tree.insert(20)
tree.insert(170)
tree.insert(15)
tree.insert(1)
//DFTPostOrder
console.log(dfs(tree.root, []));
I was building a BinarySearchTree by using javascript
but the insert function in my code deoesn't run what i want
my ideal result is
{"value":9,"left":{"value":4,"left":{"value":1,"left":null,"right":null},"right":{"value":6,"left":null,"right":null}},"right":{"value":20,"left":{"value":15,"left":null,"right":null},"right":{"value":170,"left":null,"right":null}}}
but my result is
'{"value":9,"left":null,"right":{"left":null,"right":{"left":null,"right":{"left":null,"right":{"left":null,"right":{"left":null,"right":{"left":null,"right":null}}}}}}}'
I think the problem is in my insert function
Here is my JS:
class Node {
constructor(value){
this.left = null;
this.right = null;
this.value = value;
}
}
class BinarySearchTree {
constructor(){
this.root = null;
}
insert(value){
var root=this.root
if(!root){
this.root=new Node(value)
}else{
var currentNode=root;
var newNode=new Node(value)
while(currentNode){
if(value<currentNode.value){
if(!currentNode.left){
currentNode.left=new Node;
break;
}
else{
currentNode=currentNode.left;
}
}else{
if(!currentNode.right){
currentNode.right=new Node;
break;
}else{
currentNode=currentNode.right
}
}
}
}
}
lookup(value){
var root=this.root
var searchNode = new Node(value)
if(!this.root){
return null;
}
if(searchNode===root){
return root
}else{
if(searchNode.value>root){
return root.right.value
}else{
return root.left.value
}
}
}
}
const tree = new BinarySearchTree();
tree.insert(9)
tree.insert(4)
tree.insert(6)
tree.insert(20)
tree.insert(170)
tree.insert(15)
tree.insert(1)
JSON.stringify(traverse(tree.root))
// 9
// 4 20
//1 6 15 170
function traverse(node) {
const tree = { value: node.value };
tree.left = node.left === null ? null : traverse(node.left);
tree.right = node.right === null ? null : traverse(node.right);
return tree;
}
Your Node class was instantiated as newNode so change all new Node into newNode *except for the first instance of new Node of course.
var newNode=new Node(value) // Leave this one alone and fix the rest
var searchNode = new Node(value) // Leave this one alone as well
var insertNode = function(node, newNode) {
if (newNode.key < node.key) {
if (node.left === null) {
node.left = newNode;
} else {
insertNode(node.left, newNode);
}
} else {
if (node.right === null) {
node.right = newNode;
} else {
insertNode(node.right, newNode);
}
}
};