I'm having a hard time to get the insert function to work correctly. The cout statement isn't matching the one for my assignment. If I try to insert 5, I get inserted: 5 right child of: 3 but it should be inserted: 5 right child of: 22 Can someone help me out?
Node* insert(Node *root, int value){
Node *tmp = root;
while(tmp != NULL){
if (tmp->key == value){
return tmp;
}
else if (value > tmp->key){
Node *tm = new Node(NULL, NULL, NULL);
tm->key = value;
tm->left = tmp->right;
tm->right = tmp->left;
tmp->right = tm;
cout << "inserted: " << tm->key << " right child of: " << tmp->key <<endl;
tmp = tmp->right;
}
else if (value < tmp->key){
Node *tm = new Node(NULL, NULL, NULL);
tm->key = value;
tm->left = NULL;
tm->right = NULL;
tmp->left = tm;
cout << "inserted: " << tm->key << " left child of: " << tmp->key <<endl;
tmp = tmp->left;
}
}
return tmp;
}
There are a few problems with your insertion code:
You always insert the new node as a child of the root (which does not always produce a BST)
When you link your tree, you either (if you place as right child) make the left child of the root also the left child of the new node, or (if left child) lose track of the original left subtree of root.
What happens if root is NULL
The following code should work for you
//The following code assumes the following definition of Node
struct Node {
Node(int val, Node* l, Node* r):key(val),left(l),right(r){}
int key;
Node* left;
Node* right;
}
// Returns the root of the tree after inserting val into tree (no duplicates)
Node * insert (Node * root, int val){
if (root == NULL) return new Node(val, NULL, NULL);
if (root->key == val) return root;
if (root->key > val) return insert(root->left, val);
return insert(root->right, val);
}
The above code defines insert recursively. Base case : tree is empty. Insert new value as the root. If the root is the key then you're done (no duplicated keys). Otherwise, insert the value into the left or right subtree (left if value is less than root->key or right otherwise).
Or you can define insert iteratively using a while loop.
Node * insert (Node * root, int val){
// is this an empty tree?
if (root == NULL) return new Node(val, NULL, NULL);
Node* tmp = root;
while (tmp != null){
if (tmp->key == val) break;
if (tmp->key > val){
if (tmp->left == NULL){
tmp->left = new Node(val, NULL, NULL);
break;
} else {
tmp = tmp->left;
}
} else {
if (tmp->right == NULL){
tmp->right = new Node(val, NULL, NULL);
break;
} else {
tmp = tmp->right;
}
}
}
return root;
}
In either case you can use insert the same way.
Node * tree1 = NULL;
tree1 = insert(tree1, 3);
tree1 = insert(tree1, 1);
tree1 = insert(tree1, 2);
tree1 = insert(tree1, 4);
Aftewards tree1 will be the following tree.
3
/ \
1 4
\
2
Related
I have a left child right sibling as below:
10
* |
* 2 -> 3 -> 4 -> 5
* | |
* 6 7 -> 8 -> 9 */
I want to traverse from root to the last node, the traversal function is as below:
void traverseTree(Node * root)
{
if (root == NULL)
return;
while (root)
{
cout << " " << root->data;
if (root->child)
traverseTree(root->child);
root = root->next;
}
}
As I understood, if the node has a child, then the pointer points to its child, otherwise points to the sibling (next). In this case, when the pointer points to element 6, it will go to the root->next element (which is NULL). However, the function can still be able to print the remaining element (5,7,8,9). Can any one help me explain how traverseTree works?
Here's the code to recreate the tree:
// CPP program to create a tree with left child
// right sibling representation.
#include<bits/stdc++.h>
using namespace std;
struct Node
{
int data;
struct Node *next;
struct Node *child;
};
// Creating new Node
Node* newNode(int data)
{
Node *newNode = new Node;
newNode->next = newNode->child = NULL;
newNode->data = data;
return newNode;
}
// Adds a sibling to a list with starting with n
Node *addSibling(Node *n, int data)
{
if (n == NULL)
return NULL;
while (n->next)
n = n->next;
return (n->next = newNode(data));
}
// Add child Node to a Node
Node *addChild(Node * n, int data)
{
if (n == NULL)
return NULL;
// Check if child list is not empty.
if (n->child)
return addSibling(n->child, data);
else
return (n->child = newNode(data));
}
// Traverses tree in level order
void traverseTree(Node * root)
{
if (root == NULL)
return;
while (root)
{
cout << " " << root->data;
if (root->child)
traverseTree(root->child);
root = root->next;
}
}
//Driver code
int main()
{
Node *root = newNode(10);
Node *n1 = addChild(root, 2);
Node *n2 = addChild(root, 3);
Node *n3 = addChild(root, 4);
Node *n4 = addChild(n3, 6);
Node *n5 = addChild(root, 5);
Node *n6 = addChild(n5, 7);
Node *n7 = addChild(n5, 8);
Node *n8 = addChild(n5, 9);
traverseTree(root);
return 0;
}
After executing traverseTree(root->child) the control flow will continue from the next line. You're not returning from the function, just calling another function from within this function.
void traverseTree(Node * root)
{
if (root == NULL)
return;
while (root)
{
cout << " " << root->data;
if (root->child)
traverseTree(root->child); // First, if child exists, traverse child. No return statement following here.
root = root->next; // Next, traverse sibling
}
}
If you still have doubts it would do you good to read about the program flow when calling a function.
Update(completely irrelevant to the question): As requested by OP, solution using stack:
void traverseTree(Node * root)
{
if (root == NULL)
return;
stack<Node*> s;
s.push(root);
while (!s.empty())
{
Node* top = s.top();
cout << " " << top->data;
s.pop();
if (top->next) s.push(top->next);
if (top->child) s.push(top->child);
}
}
I have a recRemove function that recursively removes the given node. I also have a findMin function that finds the smallest node in the BST. I'm having trouble merging the two so that I can remove the smallest(or largest) node. This is what I tried doing but it just returned garbage: Full code: https://pastebin.com/HCVsUZ4S
//remove min node in BST
node * extractMin()
{
return recRemove(root, findMin(root));
}
//delete node from tree
node * recRemove(node * root, double data)
{
//3 cases: no children, one child, 2 children
if (root == NULL)
{
return NULL;
}
else if (data < root->data)
{
root->left = recRemove(root->left, data);
}
else if(data > root->data)
{
root->right = recRemove(root->right, data);
}
else
{
if (root->right == NULL && root->left == NULL) //no children
{
delete root;
root = NULL;
return root;
}
else if(root->left == NULL) //only right child
{
temp = root;
root = root->right;
delete temp;
return root;
}
else if(root->right == NULL) //only left child
{
temp = root;
root = root->left;
delete temp;
return root;
}
else //2 children
{
temp->data = findMin(root->right);
root->data = temp->data;
root->right = recRemove(root->right, temp->data);
}
}
return root;
}
//find min node in BST
double findMin(node * p)
{
if(p == NULL)
{
return -1;
}
else
{
//in a balanced BST the minimum node is the leftmost node so,
//we traverse the left subtree until we get to the leftmost node and return and remove it.
temp = p;
while(temp->left != NULL)
{
temp = temp->left;
}
return temp->data;
}
}
sorry , can't write comments yet (will delete this later)
Where is temp defined? If it is a global variable than this is probably the issue...
Edit:
Have now seen the pasebin.....
temp is a member variable. Change it to a local variable.
Make sure to delete it before leaving the function. (best use std::unique_ptr<>)
I'm currently writing a program that will delete a node from a binary search tree (among other things, but the deletion is my issue) and I'm having a problem with the final step of deletion, specifically the final step of deleting a node with 2 children.
The way that I'm deleting is the way described here.
I take the farthest down left child-node (if on the right side of root) or the farthest down right child-node (if on the left) and replace the value of the node I want to delete with that value, then delete the node I just copied from.
I have all the steps complete except deleting the node I copied from; for some reason my code does not properly delete it and creates a random number value as well as a random parent value for the node I just tried to delete. I believe this is caused by an unrepaired link in the tree somewhere but being a non-experienced programmer, I cannot find it. Hopefully someone more well versed in BSTs can help me.
Here is my code (I only included code that influences the deletion function, I didn't think it necessary to include things that come after such as the destroy function):
#include <iostream>
using namespace std;
struct node
{
int data; //Stores data within the trees pointers
node * parent; //Used to move up in the tree
node * left; //Used to move left in the tree
node * right; //Used to move right in the tree
};
node * create (int data, node **tree); //Function to insert elements into the tree
void printTree (node * tree); //Function to print the tree
node *search(int key, node *tree); //Function to find data in the tree
node * delNode (node * tree, node * root); //Function to delete data from the tree
node * findSmallestRight (node * tree, node **smallest);
node * findLargestLeft (node * tree, node **smallest);
int main()
{
node * root = NULL; //Root will be the first element in the tree
node * current = NULL; //Return value for insert function to keep changes
int value; //Value entered by user
while (true) //Loop to fill tree with data
{
cout << "Enter an integer, 0 to quit" << endl;
cin >> value;
if (value == 0) //Quit when 0 is entered, BEFORE entering it into the tree
break;
current = create(value, &root); //Insert value into the tree
cout << "After inserting " << value << " tree is:" << endl;
printTree(root); //Print the tree
}
while (true) //Loop to delete data from tree
{
cout << "Search for a value to delete from the tree, 0 to quit" << endl;
cin >> value;
if (value == 0)
break;
current = search(value, root); //Find the value in the tree
if (current == NULL)
cout << value << " is not in tree. Could not delete." << endl;
else
{
root = delNode(current, root); //Delete the data
cout << value << " has been deleted. The tree is now:" << endl;
printTree(root); //print the tree
}
}
destroy(root); //Destroy the tree
return 0;
}
void printNode (node * Node) //Function to print a node in the tree
{
cout << "addr= " << Node << " parent= " << Node->parent << " left= " << Node->left << " right= " << Node->right << " data= " << Node->data << endl;
}
node * createNode (int data) //Function to create a new node in the tree
{
node * newNode = NULL; //Create a new pointer
newNode = new node; //Make that pointer a node
newNode->data = data; //Fill it with data
newNode->left = NULL; //Make it point left to NULL
newNode->right = NULL; //and right to NULL
return newNode;
}
node * create (int data, node **tree) //Function to insert elements into the tree
{
node * newNode = NULL; //Create a new pointer
if ((*tree) == NULL) //Check if tree exists already
{
//If it doesn't, create a new node and make it the root
newNode = createNode(data);
*tree = newNode;
(*tree)->parent = NULL; //Root has a parent of NULL
}
else if (data < (*tree)->data) //If the data is smaller than root, insert on the left
{
if ((*tree)->left == NULL)//If there is no node on the left, create a new one and point to it
{
newNode = createNode(data);
(*tree)->left = newNode;
newNode->parent = *tree;
}
else
{
newNode = create(data, &((*tree)->left));//If there is a node on the left, repeat function until there isn't
}
}
else //If the data is greater than or equal to root, insert on the right
{
if ((*tree)->right == NULL)
{
newNode = createNode (data); //If there is no node on the right, create a new one and point to it
(*tree)->right = newNode;
newNode->parent = *tree;
}
else
{
newNode = create(data, &((*tree)->right)); //If there is a node on the right, repeat function until there isn't
}
}
return newNode; //Return the new node to keep the changes to the value
}
void printTree (node * tree) //Function to print the tree
{
if (tree != NULL) //Check if tree actually existsreturn root;
{
//Recursively print the left side, then the root, then the right side
printTree(tree->left);
printNode(tree);
printTree(tree->right);
}
}
node *search(int key, node *tree) //Function to find data in the tree
{
if (tree == NULL || tree -> data == key)
{
return tree; //If the data either does not exist or has been found, return
}
if (key < tree->data)
{
return search(key, tree->left); //If the data is less than the current data, keep checking the left
}
else
{
return search(key, tree->right); //If the data is more than the current data, keep checking the right
}
}
node * delNode (node * tree, node * root)
{
node * parent; //Node for quick-reference and manipulation of tree's parent
if (tree->parent != NULL) //If tree value is not root assign a parent (root has parent of NULL so assigning would crash)
{
parent = tree->parent;
}
node * curr = tree;
//Removing node with 2 children on right
//There would also be cases for no children, 1 child, and 2 children on left but I did not include them as the two former are done and the latter can be copied once this is solved :)
else if (tree->left != NULL && tree->right != NULL && parent->right == tree && parent != NULL)
{
node * smallest; //Node to find smallest data value on left side
//Initialise and make it point to nothing
smallest = new node;
smallest->left = NULL;
smallest->right = NULL;
smallest->parent = NULL;
node * nReplace = NULL; //Node to replace data in tree
//Initialise and make it point to nothing
nReplace = new node;
nReplace->left = NULL;
nReplace->right = NULL;
nReplace->parent = NULL;
nReplace = findSmallestRight(tree, &smallest); //Function to find smallest data value on right side
tree->data = nReplace->data; //Replace tree's data with the new data
cout << nReplace << " " << nReplace->data << endl; //Debugging code
delete nReplace; //Delete nReplace
cout << nReplace << " " << nReplace->data << endl; //Debugging code
}
return root; //Return root to keep changes in tree
}
node * findSmallestRight (node * tree, node **smallest) //Function to find smallest data value on right side
{
node * parent = tree->parent; //Node for easy manipulation of tree's parent
//Check if current value is a potential candidate for smallest
if (tree->left == NULL && tree->right == NULL && parent->left == tree)
{
*smallest = tree; //If it is, make smallest equal to it
}
if (tree->left == NULL && tree->right != NULL) //Check if the are only branches on the right
{
findSmallestRight (tree->right, smallest); //Recurse through the right
}
else if (tree->left != NULL && tree->right == NULL) //Check if there are only branches on the left
{
findSmallestRight (tree->left, smallest); //Recurse through the left
}
else if (tree->left == NULL && tree->right == NULL) //Check if there are no branches on both sides
{
return *smallest; //Return the smallest
}
else
{
//If there are branches on both sides recurse through both
findSmallestRight (tree->left, smallest);
findSmallestRight (tree->right, smallest);
}
return *smallest; //Return the smallest
}
I think your findSmallestRight() is all messed up from recursion to returning the values.
You just have to find the SMALLEST element on the Right subtree i.e for the right child go on iterating it's Left children until last one, that'll be minimum one.
Code is as simple as : (First see picture for name associations)
if (current->left != NULL && current->right != NULL) //condition if you Current Node (to be deleted) has 2 Children
{ if((current->right)->left!=NULL) //If Right Child has left child go till last leftmost child.
{
Node* leftCurrent;
Node* leftCurrentPred;
leftCurrentPred=current->right;
leftCurrent=(current->right)->left;
while(leftCurrent->left != NULL)
{
leftCurrentPred=leftCurrent;
leftCurrent=leftCurrent->left;
}
current->data=leftCurrent->data;
delNode(leftCurrent, root); //Delete leftCurrent node i.e node with no child
leftCurrentPred->left=NULL;
cout<<item<<" has been removed from the Tree."<<endl;
}
else
{ //If Right Child of current doesn't has Left child it is itself smallest one.
Node* temp=current->right;
current->data=temp->data;
current->right=temp->right;
delNode(temp,root); //Delete temp node i.e node with no child
cout<<item<<" has been removed from the Tree."<<endl;
}
}
I was trying to implement a simple Binary Search Tree for practice. I tried to just add values and print the values in the nodes. However, I am not getting the proper ascending order of values in the nodes. Here is what I have:
struct Node
{
int data;
Node* leftN;
Node* rightN;
};
typedef Node* Node_ptr;
Node_ptr head;
//INSERT_VALUE FUNCTION
Node* insert_value(Node_ptr leaf, int key)
{
//Root case when there is no set value yet
if(leaf == NULL)
{
leaf = new Node;
head = leaf;
cout << "Make the first node" << endl;
leaf->data = key;
leaf->leftN = NULL;
leaf->rightN = NULL;
return leaf;
}
//Left child Node
if(key < leaf->data)
{
//Search for a spot in the tree to add a Node (left value < root value < right value)
//This is only true for the left child Node
if(leaf->leftN != NULL)
insert_value(leaf, key);
//We have found a spot in the tree to add a new Node and add the value of key
else
{
cout << "Insert-left" << endl;
leaf->leftN = new Node;
leaf = leaf->leftN;
leaf->data = key;
leaf->leftN = NULL;
leaf->rightN = NULL;
return leaf;
}
}
//Right child Node
else if(key >= leaf->data)
{
//Search for a spot to add a new Node in the tree (only amongst the right child Nodes)
if(leaf->rightN != NULL)
insert_value(leaf, key);
//Once we have found a spot to add a new Node, append the new Node
else
{
cout << "Insert-right" << endl;
leaf->rightN = new Node;
leaf = leaf->rightN;
leaf->data = key;
leaf->leftN = NULL;
leaf->rightN = NULL;
return leaf;
}
}
}
//PRINT FUNCTION
void printTree(Node_ptr leaf)
{
if(leaf == NULL)
return;
printTree(leaf->leftN);
cout << "Data element: " << leaf->data << endl;
printTree(leaf->rightN);
}
//MAIN
int main()
{
Node_ptr root = NULL;
int i;
//initialize values
for(i = 1; i < 12; i+=2)
root = insert_value(root, i);
root = head;
for(i = 0; i < 11; i+=2)
root = insert_value(root, i);
root = head;
printTree(root);
root = head;
cout << "Head Node: " << root->data << endl;
return 0;
}
When I printed the results, this is what I got:
0, 2, 4, 6, 8, 10, 1, 3, 5, 7, 9, 11 and the value of the head node is 1
Because you are calling the insertion as:
root = insert_value(root, i);
the location at which you insert is always using a subtree starting at the last insertion. Except the time that you re-start to add the odd numbers, when you start inserting at the head.
If you create a class BinarySearchTree that contains a head pointer, and an insert method taking an int value that calls Node::insert( head, value ), then you can just call insert on that class, without passing it a node, and it can always see to it that the insertions use the root of the tree for the start of the recursion.
Just me, but I would have a constructor for Node that takes an int and initializes the pointers to NULL. That way you don't have to do that in the insert method.
In the leaf->node? != NULL case, I think instead of calling
insert_value(leaf, key);
you want to say
leaf->node? = insert_value(leaf->node?, key)
where ? is either L or R, of course.
Something you might consider is adding a comment to the method like so:
// Adds the given key to the (sub-)tree rooted at node* then returns the new root
// of that (sub-)tree.
node *insert_value_and_return_root(node *root, int value) { ... }
After a few questions and some nice answers and friendly helpers here. I got the sulotion to my porblem with the deleting in the binary tree, i got suggested that, i can not just delet the largest number in the tree cause its may not the last or it has childrens 1 ,2 or none, so i made the code down below, i used a lot commenting hope that can help you people help me. What i actually dont know now, is how do i call this RemoveLargest() function in my public and then later in main, even though i dont know if the code will run properly.
#include <iostream>
#include <string>
#include <cstdlib>
using namespace std;
template<class T>
class BinaryTree
{
struct Node
{
T data;
Node* lChildptr;
Node* rChildptr;
Node(T dataNew)
{
data = dataNew;
lChildptr = NULL;
rChildptr = NULL;
}
};
private:
Node* root;
void Insert(T newData, Node* &theRoot) //Insert elements into the tree start.
{
if(theRoot == NULL)
{
theRoot = new Node(newData);
return;
}
if(newData < theRoot->data)
Insert(newData, theRoot->lChildptr);
else
Insert(newData, theRoot->rChildptr);
} //end.
void PrintTree(Node* theRoot) //print me the tree /start
{
if(theRoot != NULL)
{
PrintTree(theRoot->lChildptr);
cout<< theRoot->data<<" \n";
PrintTree(theRoot->rChildptr);
}
} //end.
T Largest( Node* theRoot) // show me largest number /start.
{
if ( root == NULL )
{
cout<<"There is no tree";
return -1;
}
if (theRoot->rChildptr != NULL)
{
return Largest(theRoot->rChildptr);
}
T value = theRoot->data;
return value;
} //end.
void RemoveLargest(Node* theRoot) //remove the largest priority number from tree /start.
{
Node* current; //the current tree?
Node* parent; //the parent of the current node?
current=theRoot;
// 3 cases :
// 1. We're removing a leaf node
// 2. We're removing a node with a single child
// 3. we're removing a node with 2 children
//Node with single child.
if((current->lChildptr == NULL && current->rChildptr != NULL)||(current->lChildptr != NULL && current->rChildptr == NULL))
{
if(current->lChildptr == NULL && current->rChildptr != NULL)
{
if(parent->lChildptr==current)
{
parent->lChildptr = current->rChildptr;
delete current;
}
else
{
parent->rChildptr = current->rChildptr;
delete current;
}
}
else //left child ok, no right child
{
if(parent->lChildptr==current)
{
parent->lChildptr = current->lChildptr;
delete current;
}
else
{
parent->rChildptr = current->lChildptr;
delete current;
}
}
return;
}
//We found a leaf(a node with not a single child)
if(current->lChildptr == NULL && current->rChildptr == NULL)
{
if (parent->lChildptr == current)
parent->lChildptr = NULL;
else
parent->rChildptr = NULL;
delete current;
return;
}
//Node with 2 children
// replace node with smallest value in right subtree
if (current->lChildptr != NULL && current->rChildptr != NULL)
{
Node* checkr;
checkr = current->rChildptr;
if((checkr->lChildptr == NULL)&&(checkr->rChildptr == NULL))
{
current=checkr;
delete checkr;
current->rChildptr = NULL;
}
else //right child has children
{
//if the node's right child has a left child
//Move all the way down left to locate smallest element
if ((current->rChildptr)->lChildptr != NULL)
{
Node* lcurr;
Node* lcurrp;
lcurrp = current->rChildptr;
lcurr = (current->rChildptr)->lChildptr;
while(lcurr->lChildptr != NULL)
{
lcurrp = lcurr;
lcurr = lcurr->lChildptr;
}
current->data = lcurr->data;
delete lcurr;
lcurrp->lChildptr = NULL;
}
else
{
Node* temp;
temp = current->rChildptr;
current->data = temp ->data;
current->rChildptr = temp->rChildptr;
delete temp;
}
}
return;
}
};
public:
BinaryTree()
{
root = NULL;
}
void AddItem(T newData)
{
Insert(newData, root);
}
void PrintTree()
{
PrintTree(root);
}
T Largest()
{
return Largest(root);
}
void RemoveLargest()
{
RemoveLargest();
}
};
int main()
{
BinaryTree<int> *myBT = new BinaryTree<int>();
myBT->AddItem(5);
myBT->AddItem(1);
myBT->AddItem(4);
myBT->AddItem(2);
myBT->AddItem(3);
//for(int i = 0; i < 10; i++) //randommal tolti fel/fill with random
//myBT->AddItem(rand() % 100);
cout << "BinaryTree:" << endl; //kilistazaa a fat/ list my tree
myBT->PrintTree();
cout << "Largest element: " << myBT->Largest() << endl; //visszaadja a legnagyobb elemet/shows the largest number
myBT->RemoveLargest(); //suposed to delet the largest number
myBT->PrintTree(); //shows list again
}
edited the code, now its running, its creating the tree, shows the largest, but after i call my remove function still crashing... =/
Like I said before, I think you're making things overly complicated. You have to think of what it means that your node is the largest one, in the context of a binary search tree and the relationship between the keys in its nodes.
If a node is the largest one in the tree it cannot possibly have a right child pointer, because the right child would have to have a larger key. And then, if you know that it has at most a left child, you just replace your node with its possibly null left child, and you're done.
T ExtractLargest(Node*& n){
if (!n)
return -1;
if (n->rChildptr)
return ExtractLargest(n->rChildptr);
T result = n->data;
Node *d = n;
n = n->lChildptr;
delete d;
return result;
}