Rebuild BST from preorder, error in logic - recursion

Trying to wrap my head around how to correct my code. I have the idea up, but I get stuck during the implementation.
when I step through the code below, I can reconstruct part of the BST from a pre-order traversal. But at some point, I will have function call like:
recon(preOrd,2,2)
which results in a leaf not being assigned. I do yet know how to correct this.
I have seen other threads on this topic, but want to iron out my issue so I can really learn this concept of rebuilding the BST.
public static Node recon(int[] preOrd,int start,int end){
if (start==end){
return null;
}
Node root = new Node (preOrd[start]);
int div=start;
for (i=start+1;i<=end && preOrd[i]<preOrd[start];i++){
div=i;
}
Node left= reconstruct(preOrd,start+1,div);
Node right= reconstruct(preOrd,div+1,end);
root.setLeft= left;
root.setRight=right;
return root;
}

Turns out this is pretty straightforward. Just needed to correct my thinking on the updating of leaf nodes..
public static Node recon(int[] preOrd,int start,int end){
Node root = new Node (preOrd[start]);//declare the new node
if (start>end){ //this is illegal, so return null
return null;
}
if (start==end){
return root;
}
int div=start;
for (int i=start+1;i<=end preOrd[i]<preOrd[start];i++){
div=i;
}
Node left= reconstruct(preOrd,start+1,div);
Node right= reconstruct(preOrd,div+1,end);
root.setLeft= left;
root.setRight=right;
return root;
}

Related

How can i get this tree to work properly?

I cannot get this tree to act correctly. i keep getting exit error codes. What is going on with the tree and how would i use the search function in main? it seems the methods are coded correctly but i am not using it correctly in main. i keep geting exit errors that are not 0 and none of the methods i try to use in the main function work. now i am just typing to fill in space because apparently my post is mostly code and not enough text!
//Binary Tree Practice
#include <iostream>
struct node{
int data;
node* right;
node* left;
};
class bTree{
public:
bTree(){
root=NULL;
}
~bTree(){
destroyTree();
}
void addNode(int key);
node *search(int key);
void destroyTree();
private:
node* root;
void addNode(int key,node*nod);
node *search(int key, node *leaf);
void destroyTree(node*&node);
};
node *bTree::search(int key)
{
return search(key, root);
}
void bTree::destroyTree()
{
destroyTree(root);
}
void bTree::addNode(int key)
{
if(root!=NULL)
addNode(key, root);
else
{
root=new node;
root->data=key;
root->left=NULL;
root->right=NULL;
}
}
void bTree::addNode(int key, node* nod) {//ADD a node in correct position.
if (key < nod->left->data) {
if (nod->left != NULL)
addNode(key, nod->left);//RECURSION traverse tree to the left until
find a NULL node
else {//When NULL node is found
nod->left = new node;
nod->left->data = key;
nod->left->left = NULL;
nod->right = NULL;
std::cout<<"node added"<<std::endl;
}
} else if (key > nod->right->data) {
if (nod->right != NULL)
addNode(key, nod->right);//RECURSIONTraverse right till find a null
node
else {//NULL node found
nod->right = new node;//Create new node
nod->right->data = key;//set NODE data to KEY
nod->right->right = NULL;
nod->left = NULL;
}
}
}
node *bTree::search(int key, node *leaf)
{
if(leaf!=NULL)
{
if(key==leaf->data)
return leaf;
if(key<leaf->data)
return search(key, leaf);
else
return search(key, leaf->right);
}
else return NULL;
}
void bTree:: destroyTree(node*&node){
if(node==NULL){
destroyTree(node->left);
destroyTree(node->right);
delete node;
}
}
int main() {
bTree *trees=new bTree();
trees->addNode(10);
trees->addNode(6);
trees->addNode(14);
node *check;
}
The first thing your addNode function with signature void bTree::addNode(int key, node* nod) does is this:
if (key < nod->left->data) {
The problem with your code is that nod->left will lead to a crash, since the left node has not been initialized and leads to an unauthorized memory access, or what is called a segmentation fault. Let's go through the main loop.
addNode(10) - The addNode function with signature void bTree::addNode(int key) is called, root is null, so root is created with left and right nodes set to NULL.
addNode(6) - The addNode function with signature void bTree::addNode(int key) is called, root is NOT null, so addNode with signature void bTree::addNode(int key, node* nod) is called. Then nod->left, and crash.
This is a common problem in low level programming, and my advice to you is to put debug prints inside the functions to see which parameters entered, and where exactly the code crashed. If you can pinpoint the exact line that leads to the crash (in thise case the line with nod->left) you can solve these kinds of problems more easily in the future.
In order to fix your issue, simply make sure to initialize the left and right nodes before you access them.

insertion in binary node tree using recursion

Below is my code. I'm trying to return head node back after I insert value to either left or right node. I understood the concept of insertion, but I'm unable to understand how can I return my head node back to that now it is back to original state with addition node added.
Here is exactly I don't understand.
When I insert my node how can I break the loop and return its head node back.
Recursion is stack concept which will output based on LIFO and if it is lifo how can I have head node returned back
Here's my code:
class Node {
int data;
Node left;
Node right;
}
static Node Insert(Node root,int value)
{
return nodeHelper(root,value);
}
static Node nodeHelper(Node root,int value){
Node nodeTracker = root;
Node temp;
if(root!=null){
if(value>root.data){
if(root.right==null){
temp =new Node();
temp.data = value;
root.right = temp;
return nodeTracker;
}
else{
nodeHelper(root.right,value);
}
}
else{
if(root.left==null){
temp=new Node();
temp.data = value;
root.left = temp;
return nodeTracker;
}
else{
nodeHelper(root.left,value);
}
}
}
else{
temp=new Node();
temp.data = value;
return temp;
}
}
}
To return the root of the tree, you need a third parameter that you pass around to keep track of the root. Like this:
Node* nodeHelper(Node* nodeTracker, Node* parent, int value)
Remove the local nodeTracker variable.
Your recursive calls become:
return nodeHelper(nodeTracker, parent.left, value);
(and, of course, same thing for the right branch)
And your initial call in the insert function is:
return nodeHelper(root, root, value);

how to code simple minimax algorithm in C#?

i want to build a simple tree and compare the child and recursive call, its like a mini-max algorithm. compare the value of each node and return the child of root.
i have tried all the day and i cant code it right yet. if u have experience with mini-max algorithm please help me or if u have any source to learn about it please tell me.
can someone make an example code with 3 or more depth (iteration) based on this node ?
class node
{
public int value;
public int id;
public List <node> child = new List <node>();
}
Try this:
make global variable:
public node minNode;
public node maxNode;
create function :
public void Compare(node currentNode)
{
if (minNode.value>currentNode.value)
{
minNode=currentNode;
}
if (maxNode.value<currentNode.value)
{
maxNode=currentNode;
}
foreach(var currNode in currentNode.child)
{
Compare(currNode);
}
}
and then in your code call it:
minNode=rootNode;
maxNode=rootNode;
Compare(rootNode);
And after that your will take max and min in this variable, where rootNode is your root node in a tree

BinaryTree count leaves infinite loof

I wrote countLeaf method in my binary tree class to count every leaves from root.
However, it gave me stack overflow error, but I couldn't figure what I did wrong.
this is the countLeaf class from my binaryTree
public int countLeaf(Node node){
if(root == null){return 0;} // this part work when I create null Tree
else if(root.left == null && root.right == null){
return 1; //this work when I create tree without left and right
}
else {
System.out.print(root.data); // check infinite loop
return countLeaf(root.left) + countLeaf(root.right);
}
}
And this is my main
public static void main (String[] args){
BinaryTree a = new BinaryTree("A?",
new BinaryTree("B?",
new BinaryTree("D"),
new BinaryTree("E")),
new BinaryTree("C?",
new BinaryTree("E"),
new BinaryTree("F")));
System.out.print(a);
int n = a.countLeaf(a.root);
}
and when I run it, it gave me
A?A?A?A?A?A?A?A?A?A?A?A?A? ... and stackoverflow error
why it keep repeating original root instead of follow left or right??
Replace public int countLeaf(Node node) with public int countLeaf(Node root).
I believe it will help.
Anyways, variable node is never used.

segfault after return 0;

I wrote a program to test my binary tree and when I run it, the program seems to crash (btree.exe has stopped working, Windows is checking for a solution ...).
When I ran it through my debugger and placed the breakpoint on the function I suspect is causing it, destroy_tree(), it seemed to run as expected and returned back to the main function. Main, in turn, returned from the program but then the cursor jumped back to destroy_tree() and looped recusively within itself.
The minimal code sample is below so it can be ran instantly. My compiler is MinGW and my debugger is gdb (I'm using Code::Blocks).
#include <iostream>
using namespace std;
struct node
{
int key_value;
node *left;
node *right;
};
class Btree
{
public:
Btree();
~Btree();
void insert(int key);
void destroy_tree();
private:
node *root;
void destroy_tree(node *leaf);
void insert(int key, node *leaf);
};
Btree::Btree()
{
root = NULL;
}
Btree::~Btree()
{
destroy_tree();
}
void Btree::destroy_tree()
{
destroy_tree(root);
cout<<"tree destroyed\n"<<endl;
}
void Btree::destroy_tree(node *leaf)
{
if(leaf!=NULL)
{
destroy_tree(leaf->left);
destroy_tree(leaf->right);
delete leaf;
}
}
void Btree::insert(int key, node *leaf)
{
if(key < leaf->key_value)
{
if(leaf->left!=NULL)
insert(key, leaf->left);
else
{
leaf->left = new node;
leaf->left->key_value = key;
leaf->left->left = NULL;
leaf->left->right = NULL;
}
}
else if (key >= leaf->key_value)
{
if(leaf->right!=NULL)
insert(key, leaf->right);
else
{
leaf->right = new node;
leaf->right->key_value = key;
leaf->right->left = NULL;
leaf->right->right = NULL;
}
}
}
void Btree::insert(int key)
{
if(root!=NULL)
{
insert(key, root);
}
else
{
root = new node;
root->key_value = key;
root->left = NULL;
root->right = NULL;
}
}
int main()
{
Btree tree;
int i;
tree.insert(1);
tree.destroy_tree();
return 0;
}
As an aside, I'm planning to switch from Code::Blocks built-in debugger to DDD for debugging these problems. I heard DDD can display visually pointers to objects instead of just displaying the pointer's address. Do you think making the switch will help with solving these types of problems (data structure and algorithm problems)?
Your destroy_tree() is called twice, you call it once and then it gets called after the execution leaves main() from the destructor.
You may think it should work anyway, because you check whether leaf!=NULL, but delete does not set the pointer to NULL. So your root is not NULL when destroy_tree() is called for the second time,
Not directly related (or maybe it is) to your problem, but it's good practice to give structs a constructor. For example:
struct node
{
int key_value;
node *left;
node *right;
node( int val ) : key_val( val ), left(NULL), right(NULL) {}
};
If you do this, your code becomes simpler, because you don't need worry about setting the pointers when you create a node, and it is not possible to forget to initialise them.
Regarding DDD, it;'s a fine debugger, but frankly the secret of debugging is to write correct code in the first place, so you don't have to do it. C++ gives you a lot of help in this direction (like the use of constructors), but you have to understand and use the facilities it provides.
Btree::destroy_tree doesn't set 'root' to 0 after successfully nuking the tree. As a result, the destructor class destroy_tree() again and you're trying to destroy already destroyed objects.
That'll be undefined behaviour then :).
Once you destroy the root.
Make sure it is NULL so it does not try to do it again (from the destructor)
void Btree::destroy_tree(node *leaf)
{
if(leaf!=NULL)
{
destroy_tree(leaf->left);
destroy_tree(leaf->right);
delete leaf;
leaf = NULL; // add this line
}
}

Resources