Use of reference in C++ - c++

I am writing code to solve the "Recover Binary Search Tree" problem.
https://oj.leetcode.com/problems/recover-binary-search-tree/
And first I wrote this code to put three pointers out of the recoverTree function like this:
class Solution {
public:
TreeNode *pre;
TreeNode *first;
TreeNode *second;
void recoverTree(TreeNode *root) {
inOrder(root);
int temp = first->val;
first->val = second->val;
second->val = temp;
return;
}
void inOrder(TreeNode *root) {
if (!root) return;
inOrder(root->left);
if (!pre) {
pre = root;
} else {
if (pre->val > root->val) {
if (!first) first = pre;
second = root;
}
pre = root;
}
inOrder(root->right);
}
};
It works fine and past all the tests. And then I was thinking maybe not putting the definitions of three pointers outside the function. So I wrote something like this:
class Solution {
public:
void recoverTree(TreeNode *root) {
TreeNode *pre;
TreeNode *first;
TreeNode *second;
inOrder(root, pre, first, second);
int temp = first->val;
first->val = second->val;
second->val = temp;
return;
}
void inOrder(TreeNode *root, TreeNode *&pre, TreeNode *&first, TreeNode *&second) {
if (!root) return;
inOrder(root->left, pre, first, second);
if (!pre) {
pre = root;
} else {
if (pre->val > root->val) {
if (!first) first = pre;
second = root;
}
pre = root;
}
inOrder(root->right, pre, first, second);
}
};
But this doesn't work. Is there anything wrong with my usage of reference or anything else caused the error?

Related

How to call a function method recursively in classes in c++?

So, I started learning and reading about OOP not so long ago, I've been implementing all the data structures I know using classes and objects just for overall practice and to get comfortable with using OOP in c++.
I'm implementing the tree data structure and I've been wondering how to call a method recursively(I'm aware that I have to pass in an argument) so that when I create an object in main and call a specific method it's written like the following a.inorder(); and not a.inorder(root) since root is a private attribute.
Is this possible ?
My code:
#include<iostream>
using namespace std;
struct node
{
int data;
node* left;
node* right;
};
class tree
{
private:
node* root;
public:
tree();
tree(int val);
void insert(int val);
void preorder();
void postorder();
void inorder();
int count();
};
tree::tree() : root { NULL }
{
}
tree::tree(int val)
{
root = new node;
root->data = val;
root->left = root->right = NULL;
}
void tree::insert(int val)
{
if (!root)
{
root = new node;
root->data = val;
root->left = root->right = NULL;
}
else
{
node* t = root;
node* p = NULL;
while (t)
{
p = t;
if (val > root->data)
t = root->right;
else
t = root->left;
}
t = new node;
t->data = val;
t->left = t->right = NULL;
if (p->data > t->data)
p->left = t;
else
p->right = t;
}
}
void tree::preorder()
{
if (root)
{
}
}
In your design, a node refers to itself. Since it is the node object that is recursive, you could define the recursive method on node:
struct node
{
int data;
node* left;
node* right;
void preorder() {
//...
left->preorder();
right->preorder();
}
};
And then, tree::preorder() would just dispatch a call to root->preorder().
Write a private static recursive function passing to it the pointer to the root node and call the function from the corresponding public non-static member function.
For example
public:
std::ostream & preorder( std::ostream &os = std::cout ) const
{
return preorder( root, os );
}
//...
private:
static std::ostream & preorder( const node *root, std::ostream &os );
//...
This is a comment rather than an actual answer, as it addresses a different issue than you are asking about. However, it is too long for a comment space, that's why I post it here.
I suppose you erroneously refer to root in this part
while (t)
{
p = t;
if (val > root->data)
t = root->right;
else
t = root->left;
}
IMHO it should look like this:
while (t)
{
p = t;
if (val > t->data)
t = t->right;
else
t = t->left;
}
Also compare the code to seek a place for insert with a code that makes an actual insertion:
if (p->data > t->data)
p->left = t;
else
p->right = t;
You've put a comparison subexpressions in reversed order - when seeking, you test whether the new value is greater than that in an existing node, but when inserting, you test whether the existing value is greater than the new one. If they differ, the code will work OK, because you also swapped left and right in the 'then' and 'else' branch.
However, if the values appear equal, the execution control will go to 'else' in both places. As a result the testing code may stop at empty left pointer, but then a new node would get appended to the right, which was not tested for being NULL.
Why would the tree class do intrinsic operations on node? The node class knows best the node's internal structure, so let it initialize itself. This will also help you to stick to the DRY principle and, indirectly, to the KISS principle, as well as the Single-responsibility principle.
struct node
{
int data;
node* left;
node* right;
node(int val) : data(val), left(NULL), right(NULL) {}
};
class tree
{
private:
node* root;
public:
tree();
tree(int val);
void insert(int val);
};
tree::tree() : root { NULL }
{
}
tree::tree(int val) : root(new node(val))
{
}
void tree::insert(int val)
{
if (!root)
{
root = new node(val);
}
else
{
node* t = root;
node* p = NULL;
while (t)
{
p = t;
if (val < t->data)
t = t->left;
else
t = t->right;
}
t = new node(val);
if (t->data < p->data)
p->left = t;
else
p->right = t;
}
}
Additionally, you can make insert recursive, too.
struct node
{
int data;
node* left;
node* right;
node(int val) : data(val), left(NULL), right(NULL) {}
};
class tree
{
private:
node* root;
public:
tree();
tree(int val);
void insert(int val);
protected:
void insertat(node* p, int val);
};
void tree::insert(int val)
{
if (!root)
root = new node(val);
else
insertat(root, val);
}
void tree::insertat(node* t, int val);
{
if (val < t->data)
{
if (t->left)
insertat(t->left, val);
else
t->left = new node(val);
}
else
{
if (t->right)
insertat(t->right, val);
else
t->right = new node(val);
}
}

Inserting into a Binary Tree (geeksforgeeks) recursively

I'm trying to implement the insertion function used on geeksforgeeks.com but am running into some problems trying to work it into my current code.
I have a vector with the data I need to put into the binary tree. I use this function to pass the numbers into the insertion function:
void populateTree(vector<string> dataVec) {
for (int i = 0; i < dataVec.size(); i++) {
insert(stoi(dataVec[i]), root);
}
}
This is the insertion function:
node* insert(int x, node* node) {
if (node == nullptr)
return newNode(x);
if (x < node->data)
node->left = insert(x, node->left);
else
node->right = insert(x, node->right);
return root;
}
New node function:
node* newNode(int num) {
node* temp = new node;
temp->data = num;
temp->left = temp->right = nullptr;
temp->level = 1;
return temp;
}
Root is a private member within the class which is initialized to nullptr. I'm not sure how I should go about making the first node that comes in from the vector as the root and then keep inserting things beginning from there recursively. Thanks!
The problem in your is related to use of pointer.
Instead of using node* insert(int x, node* node) you should use node* insert(int x, node** node) or node* insert(int x, node*& node) and adopt your code accordingly.
Following is corrected sample code. See it in execution here:
#include <iostream>
#include <vector>
using namespace std;
struct Node
{
int val;
Node* left;
Node* right;
Node(int v)
{
val = v;
left = right = nullptr;
}
};
class Tree
{
Node* root;
Tree()
{
root = nullptr;
}
public:
static void insert(int x, Node*& node)
{
if (node == nullptr)
{
node = new Node(x);
}
else
{
if (x < node->val)
insert(x, node->left);
else
insert(x, node->right);
}
}
static Tree* populateTree(vector<string> dataVec)
{
Tree* t= new Tree();
for (int i = 0; i < dataVec.size(); i++)
{
insert(stoi(dataVec[i]), t->root);
}
return t;
}
static void printTree(Node* node, string s)
{
if(node == nullptr) return;
cout<<s<< "+"<<node->val <<endl;
s += "----";
printTree(node->left,s);
printTree(node->right, s);
}
static void printTree(Tree* t)
{
if(t)
{
printTree(t->root, "");
}
}
};
int main() {
Tree* t = Tree::populateTree({"70", "2", "7", "20", "41", "28", "20", "51", "91"});
Tree::printTree(t);
return 0;
}

can not access memory at address 0xc8

I am writing a code to return data of a node in BST based on id.
below is my node class:
struct Node{
int id;
string data;
Node *left;
Node *right;
Node();
};
below is my node constructor: I defined id and data in addNode function
Node :: Node(){
this->left = nullptr;
this->right = nullptr;
}
below is my BST class:
class BST{
private:
Node * root = nullptr;
void setRoot(Node *);
Node* getRoot();
public:
Node *addNode(BST *, int);//helper function
Node *addNode(Node *,int);
string getEntry(BST*,int);//helper function
string getEntry(Node*,int);
}
below is my helper functions:
Node *BST::addNode(BST *bst, int val){
addNode(bst->getRoot(),val);
}
string BST::getEntry(BST* bst,int id){
getEntry(bst->getRoot(),id);
}
below is my addNode class:
Node* BST::addNode(Node* root, int val) {
Node *newNode = new Node();
newNode->id = val;
newNode->data = "Number " + to_string(val);
if (root == nullptr) {
if (getRoot() == nullptr){
setRoot(newNode);
}
setCount(getCount()+1);
return newNode;
}
if (root->id > val) {
root->left = addNode(root->left, val);
} else {
root->right = addNode(root->right, val);
}
return root;
}
below is my getEntry class:
string BST::getEntry(Node *base,int id) {
if (base == nullptr){
return "";
}
if (base->id == id){
cout<<base->data<<endl;
return base->data;
}
getEntry(base->left,id);
getEntry(base->right,id);
}
below are the nodes I passed in from main:
int main(){
BST *newBst = new BST();
newBst->addNode(newBst,1);
newBst->addNode(newBst,2);
newBst->addNode(newBst,3);
newBst->addNode(newBst,2);
newBst->addNode(newBst,3);
newBst->addNode(newBst,5);
newBst->addNode(newBst,7);
newBst->addNode(newBst,10);
cout<<newBst->getEntry(newBst,5)<<endl;
return 0;
}
The code would compile but does not return anything, I tried to debug, at the "return base->data statement", there is an error "can not access memory at address 0xc8". What causes the problem and what can I do about it?
this is the warning I got when I debug the code.
if (base->id != id){
getEntry(base->left,id);
getEntry(base->right,id);
}
As you are using a sorted tree, you know which of the right or left node you need to have a look at. Also, you need to return something:
if (base->id > val){
return getEntry(base->left,id);
}
return getEntry(base->right,id);
But the design with addNode is very bad, you shouldn't have to pass the root twice!

Binary Search Tree Using Classes

I have been trying to implement binary search tree using classes. Every time I try to compile and run the program, the program ends. I have tried many things like making the *root public to access it in main so I can update the root, but somehow it becomes null every time.
Help will be appreciated.
This is for my university project.
#include <iostream>
using namespace std;
class tree;
class Node {
friend class tree;
private:
Node *lchild,*rchild;
int data;
public:
Node (int x) {
data = x;
lchild = rchild = NULL;
}
};
class tree {
protected:
Node* root;
void inorder(const Node* root)const;
public:
tree () {
root = NULL;
}
bool insert(int item);
void inorder() const {inorder(root);};
Node* getroot() {
return root;
}
};
bool tree :: insert(int item) {
if (root == NULL) {
Node *temp = new Node(item);
root = temp;
return (bool) root;
}
if (item < root -> data) {
insert(item);
}
if (item > root -> data) {
insert(item);
}
else if (item == root -> data) {
cout<<"Duplicate";
exit (0);
}
return (bool) root;
}
void tree :: inorder(const Node *root)const {
if (root != NULL) {
inorder(root -> lchild);
cout<<root -> data;
inorder(root -> rchild);
}
}
int main()
{
tree obj1;
obj1.insert(3);
//obj1.insert(4);
obj1.insert(1);
//obj1.insert(5);
obj1.inorder();
}
/* Program to implement Binary Search Tree in c++ using classes and objects */
#include<iostream>
#include<stdlib.h>
#include<cstdlib>
using namespace std;
struct Node {
int data;
Node* left;
Node* right;
};
class BinaryTree {
private:
struct Node* root;
public:
BinaryTree() {
root = NULL;
}
Node* createNode(int);
Node* insertNode(Node*, int);
Node* deleteNode(Node*, int);
void inOrder(Node*);
void preOrder(Node*);
void postOrder(Node*);
Node* findMinimum(Node*);
/* accessor function helps to
get the root node in main function
because root is private data member direct access is not possible */
Node* getRoot() {
return root;
}
/* mutator method helps to update root ptr after insertion
root is not directly updatable in the main because its private data member */
void setRoot(Node* ptr) {
root = ptr;
}
};
/* Helper function to create a new node in each function call of insertNode */
Node* BinaryTree :: createNode(int n) {
Node* newNode = new struct Node();
newNode->data = n;
newNode->left = NULL;
newNode->right = NULL;
return newNode;
}
/* Helps to get inorder predessor to delete the node from tree */
Node* BinaryTree :: findMinimum(Node* rootPtr) {
while(rootPtr->left != NULL) {
rootPtr = rootPtr->left;
}
return rootPtr;
}
/* insertion of the Node */
Node* BinaryTree :: insertNode(Node* rootPtr, int n) {
if(rootPtr == NULL) {
return createNode(n);
}
if(n < rootPtr->data) {
rootPtr->left = insertNode(rootPtr->left, n);
}
if(n > rootPtr->data) {
rootPtr->right = insertNode(rootPtr->right, n);
}
return rootPtr;
}
/* function to delete the Node */
Node* BinaryTree :: deleteNode(Node* rootPtr, int n) {
if(rootPtr == NULL) {
cout<<"Node to be deleted is not present.!"<<endl;
return rootPtr;
}
else if(n < rootPtr->data) {
rootPtr->left = deleteNode(rootPtr->left, n);
} else if(n > rootPtr->data) {
rootPtr->right = deleteNode(rootPtr->right, n);
} else {
if(rootPtr->left == NULL && rootPtr->right == NULL) {
delete rootPtr;
rootPtr = NULL;
}
else if(root->left == NULL) {
struct Node* temp = rootPtr;
rootPtr = rootPtr->right;
delete temp;
}
else if(rootPtr->right == NULL) {
struct Node* temp = rootPtr;
rootPtr = rootPtr->left;
delete temp;
} else {
Node* temp = findMinimum(rootPtr->right);
rootPtr->data = temp->data;
rootPtr->left = deleteNode(rootPtr->right, temp->data);
}
}
return rootPtr;
}
/* all traversal technique */
void BinaryTree :: inOrder(Node* root) {
if(root == NULL) {
return;
}
inOrder(root->left);
cout<<root->data<<"\t";
inOrder(root->right);
}
void BinaryTree :: preOrder(Node* root) {
if(root == NULL) return;
cout<<root->data<<"\t";
preOrder(root->left);
preOrder(root->right);
}
void BinaryTree :: postOrder(Node* root) {
if(root == NULL) return;
postOrder(root->left);
postOrder(root->right);
cout<<root->data<<"\t";
}
int main() {
BinaryTree l1;
int ch, ele, res;
Node* ptr;
do {
cout<<"1 - Insert Node\n";
cout<<"2 - IN-ORDER Traversal\n";
cout<<"3 - PRE-ORDER Traversal\n";
cout<<"4 - POST-ORDER Traversal\n";
cout<<"Enter choice\n";
cin>>ch;
switch(ch) {
case 1:
cout<<"Entre element to insert to the List\n";
cin>>ele;
/* calling insertNode function by passing root ptr to the function,
root ptr can be obtained by accessor function getRoot() */
ptr = l1.insertNode(l1.getRoot(), ele);
/* updating the root ptr*/
l1.setRoot(ptr);
break;
case 2:
cout<<"---IN-ORDER TRAVERSAL---"<<endl;
l1.inOrder(l1.getRoot());
cout<<endl;
break;
case 3:
cout<<"---PRE-ORDER TRAVERSAL---"<<endl;
l1.preOrder(l1.getRoot());
cout<<endl;
break;
case 4:
cout<<"---POST-ORDER TRAVERSAL---"<<endl;
l1.postOrder(l1.getRoot());
cout<<endl;
break;
case 5:
cout<<"Enter node to be deleted."<<endl;
cin>>ele;
ptr = l1.deleteNode(l1.getRoot(), ele);
l1.setRoot(ptr);
default: cout<<"Invalid choice"<<endl;
}
} while(ch >=1 && ch <= 5);
return 0;
}
The reason why root gets NULL again and again is that it actually never changes its value to something else than NULL.
Maybe you have introduced this behaviour in your code in the course of fixing some other issues; yet you assign root=NULL in the constructor; afterwards, you assign only obj.root1 = ..., while you return root in getroot() { return root; }. Further, you pass Node *root as parameter in you insert function; Note that this local variable named root hides data member root, such that root->... in these functions will always address the local variable and not the data member.
Before diving around in code that's interface needs a redesign, I'd suggest to adapt the design and then adapt the code; I'm pretty sure the errors will simply go away. I'd suggest to adapt the interface of class tree as follows and write the code around it.
Member function inorder() should be const to indicate that it does not alter the object's state. Note that const-member functions can - in contrast to other non-static member functions - be called on const-objects.
class Node {
friend class tree;
private:
Node *lchild,*rchild;
int data;
public:
Node (int x) {
data = x;
lchild = rchild = NULL;
}
};
class tree {
public:
tree () { root = NULL; }
bool insert(int item) { return insert(item,root); };
void inorder() const { inorder(root);};
protected:
Node* root;
void inorder(const Node* curr) const;
bool insert(int item, Node* curr);
};
bool tree :: insert(int item, Node *currNode) {
if (root == NULL) {
root = new Node(item);
return true;
}
else if (item < currNode->data) {
if (currNode->lchild == NULL) {
currNode->lchild = new Node(item);
return true;
}
else {
return insert(item, currNode->lchild);
}
}
else if (item > currNode->data) {
if (currNode->rchild == NULL) {
currNode->rchild = new Node(item);
return true;
}
else {
return insert(item, currNode->rchild);
}
}
else // item == currNode->data
return false; // duplicate; do not insert
}
The biggest problem with your code are the following lines:
if (item < root -> data) {
insert(item);
}
if (item > root -> data) {
insert(item);
}
Basically you are saying that if the item is larger or smaller than the root data you will call the function again with the same item, you never changed the item and you will basically do this an infinity amount of times.....

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