Traversal pointer in tree while insertion - c++

#include<iostream>
using namespace std;
struct node
{
int data;
node *right;
node *left;
} ;
node *root = NULL;
node *right = NULL;
node *left = NULL;
node insert(int data)
{
node *ptr = new node;
ptr->data = data;
ptr->left = NULL;
ptr->right = NULL;
if(root==NULL)
{
root = ptr;
cout<<"Inserted "<<root->data<<" at root\n";
}
else
{
node *pos = root;
while(pos)
{
cout<<pos->data<<" pos->data\n";
if(pos->data > data)
{
cout<<pos->data<<": data\n";
pos = pos->left;
}
else if(pos->data < data)
{
cout<<pos->data<<": data\n";
pos = pos->right;
}
if(!pos)
cout<<"NULL\n";
}
pos = ptr;
cout<<"Inserted\n";
}
return *root;
}
void preorder(node *root)
{
if(root)
{
cout<<root->data;
preorder(root->left);
preorder(root->right);
}
}
int main()
{
insert(2);
insert(1);
insert(3);
insert(4);
insert(5);
preorder(root);
return 0;
}
Here, while inserting the new element, I am pointing root to new variable pos so that root is unaltered so that it becomes parameter to the function preorder() properly as it is the actual root
But, pos isn't inserting all the elements and also not displaying the required results. In short I have to use root instead of pos to insert, but using root directly is altering the 'actual' root (which in this case is 2).

But, pos isn't inserting all the elements and also not displaying the required results.
I think there are mainly two bugs.
root is never updated in the current insert function because ptr is just only assigned to a temporal variable pos after while loop finished.
We should consider the case that the value of the passed argument data is already saved in the binary tree.
In addition, preorder is displaying the root again and again is confusing.
An example of fixing the insert and preorder is following one.
DEMO is here.
node insert(int data)
{
node *ptr = new node;
ptr->data = data;
ptr->left = nullptr;
ptr->right = nullptr;
if(!root)
{
root = ptr;
}
else
{
node *pos = root;
while(true)
{
if(pos->data > data)
{
if(!pos->left){
pos->left = ptr;
break;
}
pos = pos->left;
}
else if(pos->data < data)
{
if(!pos->right){
pos->right = ptr;
break;
}
pos = pos->right;
}
else{
break;
}
}
}
return *root;
}
void preorder(node *next)
{
if(next)
{
cout << next->data << std::endl;
preorder(next->left);
preorder(next->right);
}
}

Related

Binary Search Tree is printing a random 0 and I can't find where its being created

I am working on a BST and when I print out the elements in any order, I get a random '0' appended to it, but I cannot find where its coming from.
I followed the pseudo code thats present in Introduction to algorithms by Cormen and have also looked at Geeks for Geeks but I have no luck getting rid of that 0.
#include <iostream>
using namespace std;
class Node {
public:
int data;
Node* LeftChild;
Node* RightChild;
Node(int data){
this->data = data;
this->LeftChild = NULL;
this->RightChild = NULL;
}
//pointers of the class
};
class BST {
private:
Node* root;
public:
BST(){ ///creating an empty tree in Constant Time
root = new Node(NULL);
}
Node* getRoot(){ return this->root; };
int i =0;
void printTree(Node *root)
{
if (root == NULL)
return;
else {
printTree(root->LeftChild);
cout << root->data << " ";
printTree(root->RightChild);
}
}
Node* InsertNode(Node *root,int data)
{
Node *z = new Node(data);
Node *y = new Node(NULL);
Node *x = this->root;
//if(x->data < z->data){
// x = z;
//return x;
//}
while(x!= NULL){
y = x;
if(data < x->data){
x = x->LeftChild;
}
else{
x = x->RightChild;
}
}
if(y== NULL) y= z;
else if(data < y->data){
y->LeftChild = z;
}
else{
y->RightChild =z;
}
return y;
/*
if(this->root->data== NULL){
this->root =z;
return root;
}
else{
this->root =y;
}
*/
//this->root = z;
//return root;
}
bool FindNode(Node *root,int data);
int Largest(Node *root){
return root->data;
}
};
int main()
{
BST myBst;
Node * root = (myBst.getRoot());
root = myBst.InsertNode(root, 24);
myBst.InsertNode(root, 60);
myBst.InsertNode(root, 55);
myBst.InsertNode(root, 32);
myBst.printTree(root);
return 0;
}
Here is the output:
0, 24,32,55,60
The constructor does not make a sense
BST(){ ///creating an empty tree in Constant Time
root = new Node(NULL);
}
There is created a dummy node with initialization of the data member data with NULL.
What you need is just to write
BST() : root( nullptr ) { ///creating an empty tree in Constant Time
}
The function InsertNode must have only one parameter instead of two parameters as you wrote
Node* InsertNode(Node *root,int data){
The pointer root is the data member of the class. So there is no need to pass it to the function. Otherwise the function should be declared as a static member function of the class (that nevertheless does not make a great sense).
That is the function should be declared like
void InsertNode( int data ){
Also the function has at least a memory leak
Node* InsertNode(Node *root,int data){
Node *z = new Node(data);
Node *y = new Node(NULL);
Node *x = this->root;
while(x!= NULL){
y = x;
//...
The function can be written for example the following way
void InsertNode( int data )
{
Node *new_node = Node( data );
Node **current = &root;
while ( *current != nullptr )
{
if ( data < ( *current )->data )
{
current = &( *current )->LeftChild;
}
else
{
current = &( *current )->RightChild;
}
}
*current = new_node;
}

How to implement complete binary in c++?

I want to try make insertion of complete binary tree using recursion . I make a piece of code and I cannot catch problem why value not inserted. I make height function and count nodes function with help of these function and recursive call I want to insert new node in Complete binary tree. In main get root by using get root function then send to insert function
#include<iostream>
#include<math.h>
using namespace std;
struct node{
int data;
node *left,*right;
};
class cbt{
node *root;
public:
cbt()
{
root=NULL;
}
node* get_node()
{
return root;
}
node* newNode(int key)
{
node* temp1 = new node;
temp1->data = key;
temp1->left = temp1->right = NULL;
return temp1;
}
void CBT_inseration(node* temp,int data)
{
node *ptr;
ptr=newNode(data);
if(root==NULL)
{
root=ptr;
return;
}
else
{
height = f_height(temp->left);
int excepted_node = pow(2,height)-1;
int left_tree_node_count = countNumNodes(temp->left);
int right_tree_node_count = countNumNodes(temp->right);
if(left_tree_node_count==right_tree_node_count)
{
CBT_inseration(temp->left,data);
}
else if(excepted_node != left_tree_node_count)
{
if(temp->left == NULL)
{
temp->left = ptr;
return;
}else
{
CBT_inseration(temp->left,data);
}
}
else if(temp->right == NULL)
{
temp->right=ptr;
return;
}
else if(excepted_node != left_tree_node_count)
{
if(temp->left == NULL)
{
temp->left=ptr;
return;
}
else
{
CBT_inseration(temp->right,data);
}
}
}
}
void print(node *root) {
if (root == NULL)
return;
print(root->left);
cout << root->data << " ";
print(root->right);
}
};
int main()
{
cbt obj;
node *r=NULL;
obj.CBT_inseration(obj.get_node(),4);
obj.CBT_inseration(obj.get_node(),3);
obj.CBT_inseration(obj.get_node(),5);
obj.CBT_inseration(obj.get_node(),8);
obj.print(obj.get_node());
return 0;
}
You would need to go through a debugger to see what is wrong with your code. I will tell you how I would do this:
First, you need a function to check if the tree is full. We will reuse your functions to do this:
bool isTreeFull(node* head) {
return head != NULL && countNumNodes(head) == (1 << find_height(head)) - 1;
}
Then for inserting I have to check if the number of nodes on each side are the same. This tells me that I am allowed to move one level deeper on the left side. If the number of nodes aren't the same, then I only move on to insert on the right subtree if the left subtree is full:
void CBT_inseration(int data) {
root = insert(root, data);
}
node* insert(node* head, int data) {
if (head == NULL) {
head = newNode(data);
} else {
int leftCount = countNumNodes(head->left);
int rightCount = countNumNodes(head->right);
if (leftCount == rightCount) {
head->left = insert(head->left, data);
} else {
if (isTreeFull(head->left)) {
head->right = insert(head->right, data);
} else {
head->left = insert(head->left, data);
}
}
}
return head;
}
Then you would call it like:
cbt obj;
obj.CBT_inseration(4);
obj.CBT_inseration(3);
obj.CBT_inseration(5);
obj.CBT_inseration(6);
obj.CBT_inseration(8);
obj.print(obj.get_node()); // 6 3 8 4 5

simple linked list delete fails

I'm learning C++, I try to implement simple singly linked list but the delete node part fails. I could not comprehend why this basic delete_node part is failing. It seems prev->set_next line in delete_node method does not working correctly. I tried to debug it too but failed to spot the error.
using namespace std; //ignore it for simplicity
class Node {
int data;
Node *next;
public:
Node() {}
void set_data(int a_data)
{
data = a_data;
}
void set_next(Node *a_next)
{
next = a_next;
}
int get_data()
{
return data;
}
Node* get_next()
{
return next;
}
};
class List {
Node *head;
public:
List()
{
head = NULL;
}
void print_list();
void append_node(int data);
void delete_node(int data);
};
void List::print_list()
{
Node *temp = head;
if(temp == NULL)
{
cout << "empty" << endl;
return;
}
if(temp->get_next() == NULL)
{
cout << temp->get_data() << "--->";
cout << "NULL" << endl;
}
else
{
do
{
cout << temp->get_data() << "+++>";
temp = temp->get_next();
} while(temp != NULL);
cout << "NULL" << endl;
}
}
void List::append_node(int data)
{
Node *new_node = new Node();
new_node->set_data(data);
new_node->set_next(NULL);
Node *temp = head;
if(temp != NULL)
{
while(temp->get_next()!=NULL)
{
temp = temp->get_next();
}
temp->set_next(new_node);
}
else
{
head = new_node;
}
}
void List::delete_node(int data)
{
Node *temp = head;
if(temp == NULL)
{
return;
}
else
{
Node *prev = NULL;
do
{
prev = temp;
if(temp->get_data() == data)
{
prev->set_next(temp->get_next());
delete temp;
break;
}
temp = temp->get_next();
} while(temp!=NULL);
}
}
int main()
{
List list;
list.append_node(10);
list.append_node(20);
list.append_node(30);
list.append_node(40);
list.append_node(50);
list.append_node(60);
list.delete_node(30); //
list.print_list();
return 0;
}
valgrind gives me following error.
==22232== Invalid read of size 8
==22232== at 0x400D38: Node::get_next() (20_1.cpp:25)
==22232== by 0x400A5E: List::print_list() (20_1.cpp:62)
==22232== by 0x400C6C: main (20_1.cpp:127)
==22232== Address 0x5abdd28 is 8 bytes inside a block of size 16 free'd
==22232== at 0x4C2F24B: operator delete(void*) (in /usr/lib/valgrind/vgpreload_memcheck-amd64-linux.so)
==22232== by 0x400BA8: List::delete_node(int) (20
Lets take a closer look at these lines from the List::delete_node function
prev = temp;
if(temp->get_data() == data)
{
prev->set_next(temp->get_next());
delete temp;
break;
}
The first one make prev point to the very same node that temp is pointing to. After this prev == temp is true.
So when you do
prev->set_next(temp->get_next());
it is the same as
temp->set_next(temp->get_next());
That is, you make temp->next point to temp->next which doesn't change it at all. You never unlink the node from the list, but you do delete it. That makes your printing of the list invalid, as you will dereference a deleted node.
As a simple solution, you could do something like this:
if (head->get_data() == data)
{
// Special case: Head node is the one we want to delete
Node* old_head = head;
// Make the head be the second node in the list, if any
head = head->get_next();
// Delete the old head
delete old_head;
}
else
{
// We know it's not the head node of the list, use the "next" to find it
for (Node* node = head; node->get_next() != 0; node = node->get_next())
{
if (node->get_next()->get_data() == data)
{
// It's the "next" node we want to remove
Node* old_next = node->get_next();
// Unlink the node
node->set_next(node->get_next()->get_next());
delete old_next;
break;
}
}
}
The problem is that at the beginning of your do / while loop pointers temp and prev point to the same Node. Hence, you re-point the node, and then delete it right away.
A better approach is to not use prev at all. Get next, see if its data matches the one being deleted. If it does, "bypass" and delete next. Otherwise, move on to the next node until you hit NULL:
void List::delete_node(int data) {
if(head == NULL) {
return;
}
if (head->get_data() == data) {
Node *toDelete = head;
head = head->get_next();
delete toDelete;
return;
}
Node *temp = head;
for ( ; ; ) {
Node *next = temp->get_next();
if (next == null) {
break;
}
if (next->get_data() == data) {
temp->set_next(next->get_next());
delete next;
break;
}
temp = temp->get_next();
}
}
The exact working solution is
void List::delete_node(int data)
{
Node *temp = head;
Node *prev = NULL;
//first check whether its a parent element or not
if(temp && temp->get_data() == data){
head = head->get_next();
delete temp;
}
else{
while (temp){
if (temp->get_data() == data){
if (prev)
prev->set_next(temp->get_next());
delete temp;
return;
}
prev = temp;
temp = temp->get_next();
}
}
}
This even works for deleting head node
I see a number of problems with your code.
Your Node constructors is not initializing any of the Node members.
Your List class is missing a destructor to free any allocated nodes.
Your print_list() and append_node() implementations are a little more verbose than they need to be.
But, most importantly, regarding your particular question, your list's delete_node() method is not managing its prev variable correctly. prev is always pointing at the current node that is being looked at, not at the previous node that was already looked at. So you are not actually updating your links correctly when removing a node. You are also not updating the list's head member if the node being removed is the head node.
Try something more like this instead:
class Node;
class List {
Node *head;
public:
List();
~List();
void print_list();
void append_node(int data);
void delete_node(int data);
};
class Node {
int data;
Node *next;
public:
Node(int a_data = 0, Node *a_next = NULL);
void set_data(int a_data);
void set_next(Node *a_next);
int get_data();
Node* get_next();
friend class List;
};
Node::Node(int a_data, Node *a_next)
: data(a_data), next(a_next)
{
}
void Node::set_data(int a_data)
{
data = a_data;
}
void Node::set_next(Node *a_next)
{
next = a_next;
}
int Node::get_data()
{
return data;
}
Node* Node::get_next()
{
return next;
}
List::List()
: head(NULL)
{
}
List::~List()
{
Node *temp = head;
while (temp)
{
Node *next = temp->get_next();
delete temp;
temp = next;
}
}
void List::print_list()
{
Node *temp = head;
if (!temp)
{
cout << "empty" << endl;
return;
}
do
{
cout << temp->get_data();
temp = temp->get_next();
if (!temp) break;
cout << "+++>";
}
while (true);
cout << "--->NULL" << endl;
}
void List::append_node(int data)
{
Node **temp = &head;
while (*temp) temp = &((*temp)->next);
*temp = new Node(data);
}
void List::delete_node(int data)
{
Node *temp = head;
Node *prev = NULL;
while (temp)
{
if (temp->get_data() == data)
{
if (prev)
prev->set_next(temp->get_next());
if (temp == head)
head = temp->get_next();
delete temp;
return;
}
prev = temp;
temp = temp->get_next();
}
}
int main()
{
List list;
list.append_node(10);
list.append_node(20);
list.append_node(30);
list.append_node(40);
list.append_node(50);
list.append_node(60);
list.delete_node(30); //
list.print_list();
return 0;
}

Recursive insertion of BST

I have made a function for insertion in BST using loops and it is working perfectly fine.
Now, when iam writing to do it using recursion i don't know why it's not working properly, however the logic is correct according to me. It seems that no newnode is being added to the BST tree and head of the tree after coming out of the insertion function is again becoming NULL.
#include <iostream>
using namespace std;
class node{
public:
int data;
node *right;
node *left;
node(){
data=0;
right=NULL;
left=NULL;
}
};
class tree{
node *head;
int maxheight;
void delete_tree(node *root);
public:
tree(){head=0;maxheight=-1;}
void pre_display(node* root);
node* get_head(){return head;}
void insert(int key,node* current);
};
void tree::insert(int key,node *current){
if(current==NULL)
{
node *newnode=new node;
newnode->data=key;
current=newnode;
}
else{
if(key<current->data)
insert(key,current->left);
else
insert(key,current->right);
}
return;
}
void tree::pre_display(node *root){
if(root!=NULL)
{
cout<<root->data<<" ";
pre_display(root->left);
pre_display(root->right);
}
}
int main(){
tree BST;
int arr[9]={17,9,23,5,11,21,27,20,22},i=0;
for(i=0;i<9;i++)
BST.insert(arr[i],BST.get_head());
BST.pre_display(BST.get_head());
cout<<endl;
system("pause");
return 0;
}
Please tell me what should i change in the algorithm to make it work.
In your insert function
void tree::insert(int key,node *current){
if(current==NULL)
{
node *newnode=new node;
newnode->data=key;
current=newnode;
}
else{
if(key<current->data)
insert(key,current->left);
else
insert(key,current->right);
}
return;
}
you allocate a new node but never set BST::head to newly allocated head. So BST::get_head will always return null.
One way to fix this would be for insert to return a node. This would be root node in your case and set the BST::head to this value.
Your recursion looks fine, but you don't actually add the node anywhere! You just recurse through the tree.
Edit You can change the insert method to take a pointer to a pointer, like this:
void tree::insert(int key, node **current)
{
if(*current == NULL)
{
node *newnode = new node;
newnode->data = key;
*current = newnode;
}
else
{
if(key < (*current)->data)
insert(key, &(*current)->left);
else
insert(key, &(*current)->right);
}
}
And in main call it like this:
BST.insert(arr[i], &BST.get_head()); // Note the ampersand (&)
you should try this
node tree:: insert ( int key , node * current ) {
if ( ! current ) {
node * newnode = new node ;
newnode -> key = key;
current = newnode ;
}
else if ( key < current -> key ) {
current -> left = insert ( key , current ->left
}
else
current -> right = insert ( key , current->right )
return current ;
}
it works fine....jsut update the head node every time whenver a new node is inserted and it will return the updated current node.
Just change your function as
void tree::insert(int key,node*& current){
if(current==NULL)
{
node *newnode=new node;
newnode->data=key;
current=newnode;
}
else{
if(key<current->data)
insert(key,current->left);
else
insert(key,current->right);
}
return;
}
make your input pointer as a reference parameter.
struct node{
node* left;
node* right;
int data;
};
node* root=NULL;
node* create(node* head,int val){
if(head==NULL){
node* nn=new node;
nn->data=val;
nn->left=NULL;
nn->right=NULL;
head=nn;
}
else if(val<head->data)
head->left=create(head->left,val);
else if(val>head->data)
head->right=create(head->right,val);
return head;
}
int main(){
int num=0;
cout<<"Enter value in tree or press -1 to Exit\n";
while(num!=-1){
cin>>num;
if(num==-1){
cout<<"\nTree Created\n";
break;
}
else{
root=create(root,num);
}
}
}
hope this code solves your problem
void insertNode_recursive(int value, TreeNode *current)
{
if (current == NULL)
{
if (current == NULL && isEmpty())
{
TreeNode *new_node = new TreeNode(value);
current = new_node;
root = new_node;
}
else
{
TreeNode *new_node = new TreeNode(value);
current = new_node;
}
}
else
{
if (value < current->getValue())
{
insertNode_recursive(value, current->getLeft());
}
else if (value > current->getValue())
{
insertNode_recursive(value, current->getRight());
}
else
{
cout << "\nDuplicate Value are Not Allowed\n";
}
}
}
This Code is Useful For Recursively Print the Tree Node

How can I create the tree?

I'm trying to make a BST and need to print it inorder, postorder, and preorder.
The thing am not sure about is how to create this tree in my main() function.
struct Tree_Node
{
Tree_Node *right;
Tree_Node *left;
int info;
};
class bTree
{
private:
Tree_Node *root;
public:
bTree();
void bTree::Insert(Tree_Node*& tree, int item);
void bTree::preorderPrint(Tree_Node *root);
};
bTree::bTree()
{
root = NULL;
}
void bTree::Insert(Tree_Node*& tree, int item)
{
if (tree == NULL)
{
tree = new Tree_Node;
tree->right = NULL;
tree->left = NULL;
tree->info = item;
}
else if (item < tree->info)
Insert(tree->left, item);
else
Insert(tree->right, item);
}
void bTree::preorderPrint(Tree_Node *root)
{
if ( root != NULL )
{
cout << root->info << " ";
preorderPrint( root->left );
preorderPrint( root->right );
}
}
void main()
{
// This is where I need help at
// I'm not sure how to insert a new node
bTree Test;
Test.Insert(
}
By the looks of things, you can just write
Test.Insert(Test.root, 3); // Insert 3
Test.Insert(Test.root, 4); // Insert 4
and that should work. Of course, you'll have to make root public.
However, this is a bit awkward, since the first parameter will always be bTree.root - and you don't need to make that public. Remember that the user of your data type (you or anyone else) shouldn't have to care about internals such as nodes - they only care about their data. Instead, I'd recommend making a convenience Insert method which only needs to take an integer (not a tree node) - this is called Overloading.
void bTree::Insert(int item)
{
Insert(root, item);
}
// Keep the other insert method, but make it private.
Then you can just write:
Test.Insert(3);
Test.Insert(4);
void bTree::Insert(int item)
{
Tree_Node * node = new Tree_Node;
node->left = NULL;
node->right = NULL;
node->info = item;
if (root == NULL)
{
root = node;
return;
}
Tree_Node * t = root;
Tree_Node * p = root;
while(1)
{
if (item < t->info)
{
t = t->left;
if(t == NULL)
{
p->left = node;
return;
}
}
else if(item > t->info)
{
t = t->right;
if(t == NULL)
{
p->right = node;
return;
}
}
else //item already exists in the tree
return;
p = t;
}
}
//now you can insert nodes like
Test.Insert(5);
Test.Insert(6);