I'm currently working on a C++ project and part of it is to traverse the binary tree using inorder, preorder, and postorder.
class TNode
{
public:
int val;
TNode() {}
TNode(int v) { val = v; }
TNode * left;
TNode * right;
TNode * parent;
};
class BTree
{
void print_pre_order(TNode *r);// print the node as you traverse according to the order.
void print_in_order();
void print_post_order();
}
BTree::BTree()
{
root = new TNode(1);
root->parent = 0;
root->left = new TNode(2);
root->right = new TNode(3);
root->left->left = new TNode(4);
root->left->right = new TNode (5);
root->right->left = new TNode(6);
}
void BTree::print_pre_order(TNode *r)
{
if (r == 0)
{
return;
}
cout << r->val;
print_pre_order(r->left);
print_pre_order(r->right);
}
int main()
{
BTree y;
y.print_pre_order(y.root);
return 0;
}
In my default constructor, I've initialized values for some nodes, but when I run the code, the output I'm getting is "124" and gets an error. I don't know where I did wrong, can someone help?
I see no signs that the program ever sets any any pointers to zero, so if (r == 0) is unlikely to ever trigger an exit.
Give this a try:
class TNode
{
public:
int val;
TNode(): val(0), left(nullptr), right(nullptr), parent(nullptr) {}
TNode(int v): val(v), left(nullptr), right(nullptr), parent(nullptr) {}
TNode * left;
TNode * right;
TNode * parent;
};
The : tells the compiler that a member initializer list is coming. After that the code initializes all of the pointer members to point at null.
Change the
if (r == 0)
to
if (r == nullptr)
to better convey intent and you should be good to go.
Related
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);
}
}
I am solving leetcode question : Cousins in Binary Tree
Link for problem statement: https://leetcode.com/problems/cousins-in-binary-tree/
Logic:
Implementing bfs from root node and storing the distance of each child node from the root node in a "dis" vector and storing each node's parent node in a vector "pred" .
If parent node is not same and distance of x and y in function isCousin is same , then return true else false.
MY CODE:
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
vector<int> dis={0};
vector<int> pred={-1};
// vector<bool> vis={false};
struct TreeNode *temproot,*curr;
void bfs(TreeNode *root){
queue<TreeNode*> q;
int initDis=0;
q.push(root);
// vis.push_back(true);
dis.push_back(0);
pred.push_back(-1);
while(!q.empty()){
curr=q.front();
q.pop();
initDis += 1;
if(curr->left != NULL){
pred.push_back(curr->val);
temproot=curr->left;
// vis.push_back(true);
dis.push_back(initDis);
q.push(temproot);
}
else continue;
if(curr->right != NULL){
pred.push_back(curr->val);
temproot=curr->right;
// vis.push_back(true);
dis.push_back(initDis);
q.push(temproot);
}
else continue;
}
}
bool isCousins(TreeNode* root, int x, int y) {
if(root==NULL) return false;
bfs(root);
if(pred.at(x-1) == pred.at(y-1)) return false;
else
if(dis.at(x-1) == dis.at(y-1)) return true;
else return false;
}
};
ERROR MESSAGE:
Runtime Error Message:
terminate called after throwing an instance of 'std::out_of_range'
Last executed input:
[1,2,3,null,4,null,5]
5
4
So it's very hard to explain so I'll just show it to you. I'm trying to implement a Red-Black tree in C++. Below is the code relevant to the question (complete code at this link)
I'm fairly new so please forgive me if I don't use the right terminology.
My question is about creating the root node. When a new value is added using addValue, it's assigning the new node to the root but at the same time is passing the root in as the parameter. I don't get any errors but it feels like this is not a good way to go about it.
enum colour {RED, BLACK, DOUBLEBLACK};
struct Node{
int data;
int colour;
Node *left, *right, *parent;
explicit Node(int);
};
class Tree{
public:
Tree();
virtual ~Tree(){};
void addValue(int);
Node* insertNode(Node *, Node*);
private:
Node* root;
};
Node::Node(int data) {
this->data = data;
colour = RED;
left = right = parent = nullptr;
}
Tree::Tree() {
root = nullptr;
}
void Tree::addValue(int n) {
Node *node = new Node(n);
root = insertNode(root, node); //*********** this line here
insertFix(node);
}
Node* Tree::insertNode(Node* root, Node* node) {
if (root == nullptr)
return node;
if(node->data < root->data) {
root->left = insertNode(root->left, node);
root->left->parent = root;
} else if (node->data > root->data) {
root->right = insertNode(root->right, node);
root->right->parent = root;
}
return root;
}
I have the following code that takes in a sorted array of integers and converts it into a balanced binary tree :
class node
{
friend class bst;
public:
node():data(0), left(NULL), right(NULL){}
node(int val): data(val), left(NULL), right(NULL){}
private:
int data;
node* left;
node* right;
};
class bst{
public:
bst():root(NULL){}
bst(node* root):root(root){}
node* sorted_array_to_bst(int arr[], int start, int end)
{
if(start > end) return NULL;
int mid = (start + end)/2;
root = new node(arr[mid]);
root->left = sorted_array_to_bst(arr, start, mid-1);
root->right = sorted_array_to_bst(arr, mid+1, end);
return root;
}
void levelorder(node* root)
{
if(root == NULL) return;
std::queue<node*> Q;
Q.push(root);
while(!Q.empty())
{
node* current = Q.front();
std::cout<<current->data<<" ";
if(current->left) Q.push(current->left);
if(current->right) Q.push(current->right);
Q.pop();
}
}
private:
node* root;
};
int main()
{
int arr[10] = {2,6,7,9,13,15,18,21, 23, 29};
bst* b;
node* r = b->sorted_array_to_bst(arr, 0, 9);
b->levelorder(r);
return 0;
}
The issue is, when I run the program, 29 gets printed infinitely. I think there is something not right with my main function. Any help would be appreciated.
You did not initialized your bst instance b. You just created it without initialization, so when you call:
node* r = b->sorted_array_to_bst(arr, 0, 9);
your code will crash. You should something like this:
bst* b = new b( /* pass a node */ );
I am trying to create a n-ary tree with a vector of the children.
This is what I have gotten so far.
In the node.h file I have this:
#include <vector>
#include <string>
using namespace std;
class Node{
private:
Node *parent;
vector <Node*> children;
int data;
public:
Node();
Node(Node parent, vector<Node> children);
Node(Node parent, vector<Node> children, int data);
Node * GetParent();
void SetChildren(vector<Node> children);
vector<Node>* GetChildren();
void AddChildren(Node children);
void SetData(int data);
int GetData();
bool IsLeaf();
bool IsInternalNode();
bool IsRoot();
};
And this is my node.cpp file.
#include "node.h"
Node::Node(){
this->parent = NULL;
this->children = NULL;
this->data = 0;
}
Node::Node(Node parent, vector<Node> children){
this->parent = &parent;
this->children = &children;
}
Node::Node(Node parent, vector<Node> children, int data){
this->parent = &parent;
this->children = &children;
this->data = data;
}
Node* Node:: GetParent(){
return this->parent;
}
void Node::SetChildren(vector<Node> children){
this->children = &children;
}
vector<Node> * Node::GetChildren(){
return this->children;
}
void Node::AddChildren(Node children){
this->children.push_back(children);
}
void Node::SetData(int data){
this->data = data;
}
This obviously doesn't work. My main problem is that I am not quite sure how to handle the vector for the children. I wrote this following some tutorials online, but as you can see I am super confused.
The main (and possibly only) problem in your code is that you defined your Node class to manipulate nodes by pointers (Node*) :
class Node{
private:
Node *parent;
vector <Node*> children;
But your methods are manipulating nodes by values (Node).
As instance, in the constructors :
Node::Node(Node parent, vector<Node> children){
this->parent = &parent;
Storing the address of the parent parameter won't work, it's a temporary object, you'll need to pass a Node* parent to your constructor or to create a new Node object.
this->children = &children;
This doesn't make any sense since this->children is a vector of Node* and the children parameter is a vector of Node. Again, you'll need to either pass a vector of Node* to your constructor or to create new node objects.
You have the same issues in SetChildren and AddChildren.
Also, since you're manipulating your nodes as pointers, be very careful about the memory management. There's no garbage collector in C++, you'll have to delete every thing you new and at the proper time.
Check if below code helps you to create n-array tree creation.
struct TreeNode
{
vector<TreeNode*> children;
char value;
};
class TreeDictionary
{
TreeNode *root;
public:
TreeDictionary()
{
root = new TreeNode();
root->value = 0;
}
TreeNode *CreateNode(char data)
{
TreeNode *parent_node = new TreeNode;
if (parent_node)
parent_node->value = data;
return parent_node;
}
TreeNode* SearchElement(TreeNode *NextNode, char *data, int& val)
{
bool bVal = false;
for (vector<TreeNode*>::iterator it = NextNode->children.begin(); it != NextNode->children.end(); it++)
{
if ((*it)->value == *(data))
return SearchElement((*it), ++data, ++val);
}
return NextNode;
}
TreeNode *InsertNode(TreeNode *parent, TreeNode *ChildNode, char data)
{
if (parent == NULL)
ChildNode = CreateNode(data);
else
{
TreeNode *childNode = CreateNode(data);
parent->children.push_back(childNode);
return childNode;
}
return ChildNode;
}
void InsertMyString(string str)
{
TreeNode *NextNode = root;
for (int i = 0; i < str.size(); i++)
{
if (str[i] == '\0')
return;
cout << str[i] << endl;
if (NextNode->value == 0)
{
NextNode->value = str[i];
continue;
}
else if (NextNode->value != str[i])
{
NextNode = InsertNode(NextNode, NULL, str[i]);
}
else
{
TreeNode *node;
node = SearchElement(NextNode, &str[++i], i);
NextNode = InsertNode(node, NULL, str[i]);
}
}
}
};
int main()
{
TreeDictionary td;
td.InsertMyString("Monster");
td.InsertMyString("Maid");
td.InsertMyString("Monday");
td.InsertMyString("Malli");
td.InsertMyString("Moid");
return 0;
}
This implementation of SearchElement (without recursion) also works:
TreeNode* SearchElement(TreeNode *NextNode, char *data, int& val)
{
bool bVal = false;
for (vector<TreeNode*>::iterator it = NextNode->children.begin(); it != NextNode->children.end(); it++)
{
if ((*it)->value == *(data))
return (*it);
}
return NextNode;
}
TreeNode* res = SearchElement(root, data, value);
I checked this out, not understandable, why - it works for any node you want to find in the tree, no matter the depth and the level of the node in the tree, And that's unclear why, Because the loop iterates only over the children at the second level of the tree (children of the root node), Despite this - it even will find nodes with depth of 10 levels in the tree.