I'm confused about how pointers work here. I have a class called PrefixTree and a struct called TreeNode within this class. I have the following code to build a tree with a string, the problem is every time preorder() is called it doesn't return the root character correctly and after that it throws a segmentation fault.
I want to know if I'm correctly setting the root pointer or if I'm misusing it in the others files.
//prefixtree.cpp
PrefixTree::TreeNode* PrefixTree::buildTree(string& input)
{
char c = input[0];
input.erase(0,1);
TreeNode* node = new TreeNode();
node->character = c;
if (!root)
root = node;
if (c == '*')
{
node->left = buildTree(input);
node->right = buildTree(input);
}
return node;
}
void PrefixTree::preorder()
{
traverse(root);
}
void PrefixTree::traverse(TreeNode* node)
{
if (node)
{
cout << node->character << endl;
traverse(node->left);
traverse(node->right);
}
}
and
//prefixtree.h
class PrefixTree
{
private:
struct TreeNode
{
char character;
TreeNode* left;
TreeNode* right;
};
TreeNode* root;
void traverse(TreeNode* node);
public:
TreeNode* buildTree(string& input);
void preorder();
};
and
//main.cpp
PrefixTree tree;
string a = string("*a**!*dc*rb");
cout << tree.buildTree(a)->character << endl;
tree.preorder();
You need to initialize the pointer members, they are not automatically initialized and may contain garbage values instead of nullptr, which leads to your tests if(!root) and if(node) being useless, reporting uninitialized pointers as valid, which you will then dereference.
Add constructors:
class PrefixTree
{
private:
struct TreeNode
{
char character;
TreeNode* left;
TreeNode* right;
TreeNode() : character('a'), left(nullptr), right(nullptr) {};
};
TreeNode* root;
void traverse(TreeNode* node);
public:
PrefixTree() : root(nullptr) {};
TreeNode* buildTree(string& input);
void preorder();
};
Related
Here is a simple c++ class for binary tree. Compiler throws an error:
E0147 declaration is incompatible with "void BinaryTree::getLeftChild(node *n)"
Here node is a struct defined under the private section in the class. I am not sure why it says incompatible declaration.
//------------------------ BinaryTree class-----------------
class BinaryTree
{
public:
BinaryTree();
~BinaryTree();
void createRootNode();
void getChildren();
void getLeftChild(node* n);
void getRightChild(node* n);
private:
typedef struct node
{
node *lchild = nullptr;
int data;
node *rchild = nullptr;
}node;
queue <node*> Q;
node *root;
};
BinaryTree::BinaryTree()
{
createRootNode();
getChildren();
}
void BinaryTree::createRootNode()
{
root = new node();
cout << "Enter value for root node" << endl;
cin >> root->data;
Q.push(root);
}
void BinaryTree::getChildren()
{
while (Q.empty == false)
{
getLeftChild(Q.front());
getRightChild(Q.front());
Q.pop();
}
}
void BinaryTree::getLeftChild(node* n)
{
}
void BinaryTree::getRightChild(node* n)
{
}
Code picture with errors
I got another struct in global scope declared as "node" which created chaos. Secondly, i also need to fix the order of public and private sections.
Here is working code
//------------------------ BinaryTree class-----------------
class BinaryTree
{
private:
typedef struct node
{
node *lchild = nullptr;
int data;
node *rchild = nullptr;
}node;
queue <node*> Q;
node *root;
public:
BinaryTree();
~BinaryTree();
void createRootNode();
void getChildren();
void getLeftChild(node* n);
void getRightChild(node* n);
};
BinaryTree::BinaryTree()
{
createRootNode();
getChildren();
}
void BinaryTree::createRootNode()
{
root = new node();
cout << "Enter value for root node" << endl;
cin >> root->data;
Q.push(root);
}
void BinaryTree::getChildren()
{
while (Q.empty() == false)
{
getLeftChild(Q.front());
getRightChild(Q.front());
Q.pop();
}
}
void BinaryTree::getLeftChild(node* n)
{
}
void BinaryTree::getRightChild(node* n)
{
}
First error, is that you need to forward declare the node.
Second error, is that you are trying to access node which is privately declared inside of BinaryTree.
First answer:
typedef struct node
{
node* lchild = nullptr;
int data;
node* rchild = nullptr;
}node;
class BinaryTree
{
public:
BinaryTree();
~BinaryTree();
void createRootNode();
void getChildren();
void getLeftChild(node* n);
void getRightChild(node* n);
private:
node* root;
};
void BinaryTree::getLeftChild(node* n)
{
}
void BinaryTree::getRightChild(node* n)
{
}
Now code compiles fine.
Or if you want to have the typedef defined as private inside, you need the implementation to be inside the class as well.
Second Answer:
typedef struct node;
class BinaryTree
{
public:
BinaryTree();
~BinaryTree();
void createRootNode();
void getChildren();
void getLeftChild(node* n)
{
}
void getRightChild(node* n)
{
}
private:
typedef struct node
{
node* lchild = nullptr;
int data;
node* rchild = nullptr;
}node;
node* root;
};
I wrote a tree structure and made a basic search function to look for nodes within the tree. The tree itself uses a sentinel node to mark all ends (parent of the root, child of the leaves), and search simply iterates through nodes until it either finds a match or hits the sentinel node. The search function works fine when I call it on an instance of a tree, however it gets stuck when the tree is a data member of another class. In the following code, "t.search(1)" works, but "embedded_tree.t.search(1)" gets stuck in an infinite loop.
I have narrowed it down to the fact that when the call to embedded_tree.t.search() is made, the content of "&sentinel" correctly points to the sentinel node, but seems to be a new pointer, as it is not equivalent to the contents of root, sentinel.parent, and sentinel.child. From here I am stuck and am not sure how to call it so that &sentinel matches the pointers that were created when the tree was constructed.
#include <iostream>
struct NODE {
int key;
NODE* parent;
NODE* child;
NODE() : key(0), parent(NULL), child(NULL) {};
};
struct TREE {
NODE sentinel;
NODE* root;
TREE()
{
sentinel = *new NODE;
sentinel.parent = &sentinel;
sentinel.child = &sentinel;
root = &sentinel;
}
NODE* search(int k)
{
NODE* x = root;
while (x != &sentinel)
{
if (x->key == k) return x;
x = x->child;
}
return &sentinel;
}
};
struct A {
TREE t;
A() : t(*new TREE()) {};
};
int main()
{
TREE t;
t.search(1);
A embedded_tree;
embedded_tree.t.search(1);
}
You're confusing dynamic memory allocation with stack allocation. When you do
sentinel = *new NODE
bad things happen. Memory gets allocated for NODE sentinel on the stack, then for NODE in new operator, then assignment gets done to sentinel variable, and memory created in new operator is lost. You should rewrite your code to use pointers instead, and add destructors, something like this
#include <iostream>
struct NODE {
int key;
NODE* parent;
NODE* child;
NODE() : key(0), parent(NULL), child(NULL) {};
};
struct TREE {
NODE* sentinel;
NODE* root;
TREE()
{
sentinel = new NODE;
sentinel->parent = sentinel;
sentinel->child = sentinel;
root = sentinel;
}
~TREE() {
if (NULL != sentinel) {
delete sentinel;
sentinel = NULL;
root = NULL;
}
}
NODE* search(int k)
{
NODE* x = root;
while (x != sentinel)
{
if (x->key == k) return x;
x = x->child;
}
return sentinel;
}
};
struct A {
TREE* t;
A() : t(new TREE()) {};
~A() {
if (NULL != t) {
delete t;
t = NULL;
}
}
};
int main()
{
TREE t;
t.search(1);
A embedded_tree;
embedded_tree.t->search(1);
}
However, since we're talking about C++, I'd suggest you to look to smart pointers and containers after you get familiar with manual memory management.
#include<iostream>
using namespace std;
struct node{
int data;
node *left;
node *right;
node(int value = 0);
};
node::node(int value){
data = value;
left = NULL;
right = NULL;
}
class LinkedList{
public:
node *root;
LinkedList();
bool isEmpty();
void insertInto(int value, node *key);
};
LinkedList::LinkedList(){
root = NULL;
}
bool LinkedList::isEmpty(){
if(root == NULL) return true;
}
void LinkedList::insertInto(int value, node* root){
if (root == NULL)
{
node *n = new node(value);
root = n;
}
else if(value <= root->data){
insertInto(value, root->left);
}
else if(value > root->data){
insertInto(value,root->right);
}
}
int main() {
cout<<"I am gonna write the insertion of a binary tree"<<"\n";
LinkedList sample;
if(sample.isEmpty()) cout<<"THe tree is empty"<<endl; else cout<<"The tree is NOT empty"<<endl;
sample.insertInto(5,sample.root);
if(sample.isEmpty()) cout<<"THe tree is empty"<<endl; else cout<<"The tree is NOT empty"<<endl;
return 1;
}
I have been working on this for quite some time, I dont seem to understand why the result is showing that the tree is empty even after adding the value 5. ALso please give tips on how I can improve. Thanks
Ignoring the comments that I could make about the style/structure of the code you've posted:
void LinkedList::insertInto(int value, node* root){
if (root == NULL)
{
node *n = new node(value);
root = n;
}
You're not passing the node* root variable by reference here. Instead, you're changing a copy of the node* root to point to the new node object you constructed. If you want this code to actually change the value of the sample.root variable that you passed in from the main, you must pass root by reference.
void LinkedList::insertInto(int value, node* &root){
Since LinkedList::insertInto is a member function anyway, why pass in root at all?
You have access to the member variable root, just use that instead. If you still want to be able to use it recursively, you could make a public function with just the value, and have that call a private version that also takes in a node* is a parameter.
Here are some coding style suggestions, since you asked for them:
Best coding practice dictates that you make member variables of your class private, and use public member functions to manipulate your class instead. This is for a variety of different reasons. One explanation is here:
https://softwareengineering.stackexchange.com/questions/143736/why-do-we-need-private-variables
So your class (and let's call it BinaryTree instead), would look something like this:
class BinaryTree{
public:
/* functions */
private:
node *root;
};
So instead of making the user of the class provide the root of the BinaryTree (which doesn't make sense since we know it anyway), we just ask them for the value to insert, and provide the root ourselves.
class BinaryTree{
public:
/* other functions */
void insertInto(int value);
private:
void insertInto(int value, node* &n);
node *root;
};
// Public version of the insertInto function
void insertInto(int value) {
insertInto(value, root);
}
// Private helper function for insertInto
void insertInto(int value, node* &n) {
if (n == NULL)
{
n = new node(value);
}
else if(value <= root->data){
insertInto(value, root->left);
}
else if(value > root->data){
insertInto(value,root->right);
}
}
int main() {
BinaryTree sample;
sample.insertInto(5);
}
I'm trying to implement BST in c++ using recursion. However, I found myself in dilemma.
In the Insert function, I use reference TreeNode *&nodeto pass the function argument. I don't want make the reference const, because I need change node in Insert function. On the other side, when I call function like tree.Insert(10, tree.Getroot()), it occurs error because function Getroot creates temporary variable which can't not be assigned to non-const reference. And I know I can easily fix it by making the TreeNode *rootpublic, but I don't want do that.
What should I do to fix it or is there any better design? Please help, thanks in advance.
Here's the head file.
#ifndef BINARY_SEARCH_TREE_H
#define BINARY_SEARCH_TREE_H
class TreeNode
{
public:
TreeNode(int x = 0,TreeNode* l = nullptr, TreeNode* r = nullptr)
: element(x), left(l), right(r) { }
int element;
TreeNode* left;
TreeNode* right;
};
class BST
{
public:
BST(TreeNode *t = nullptr) : root(t) {}
void Insert(int x, TreeNode*& node)
{
if (node == nullptr) {
node = new TreeNode(x, nullptr, nullptr);
if (node == nullptr)
std::cout << "Insert Failure" << std::endl;
}
else if (node->element < x) {
Insert(x, node->right); //easy to make a mistake
}
else if (node->element > x) {
Insert(x, node->left);
}
}
TreeNode *Getroot()
{
return root;
}
private:
TreeNode* root;
};
#endif
Implement Insert at a node level as well as tree level. Then the insert logic should either be handled at the root level by the tree or at depth by the node you're inserting at. I have an example tree implemented here. It might not be the best implementation but maybe it will be useful to you.
#ifndef __BINARYTREENODE__
#define __BINARYTREENODE__
class BinaryTreeNode {
public:
BinaryTreeNode(int);
int element;
BinaryTreeNode *left;
BinaryTreeNode *right;
};
#endif /* __BINARYTREENODE__ */
#ifndef __BINARYSEARCHTREE__
#define __BINARYSEARCHTREE__
#include "BinaryTreeNode.h"
using namespace std;
class BinarySearchTree {
public:
BinarySearchTree();
~BinarySearchTree();
void insert(int);
private:
BinaryTreeNode *root;
void insert(int, BinaryTreeNode * & n);
};
#endif /* __BINARYSEARCHTREE__ */
#include "BinarySearchTree.h"
#include <iostream>
using namespace std;
BinarySearchTree::BinarySearchTree(){}
void BinarySearchTree::insert(int element)
{
insert(element, this->root);
}
void BinarySearchTree::insert(int element, BinaryTreeNode* & n)
{
if (n == 0)
{
n = new BinaryTreeNode(element);
}
else if (n->element > element)
{
insert(element, n->left);
}
else if (n->element < element)
{
insert(element, n->right);
}
}
I realize the title isn't too descriptive so here are the details. I'm implementing my own Binary Tree class in C++. I have written a template Node class and template Binary Tree class already, for the most part, and am stuck on something. I created an empty binary tree (root node is null) and when I try to set that node it fails miserably. here is the code and more explanation:
template<class T> class Node
{
T _key;
Node<T> *_leftChild;
Node<T> *_rightChild;
public:
Node();
Node(T key);
Node(T key, Node<T> *leftChild, Node<T> *rightChild);
~Node();
bool hasLeftChild();
bool hasRightChild();
void setKey(T key);
void setLeftChild(Node<T> *node);
void setRightChild(Node<T> *node);
T getKey();
Node<T>* getLeftChild();
Node<T>* getRightChild();
bool compare(Node<T> *compareNode); // return true if this.Node < compareNode
};
Node implementation not really necessary.. ( I dont think ) it's quite long.
#include "Node.cpp"
#include <iostream>
using namespace std;
template<class T> class BinaryTree
{
Node<T> *_root;
public:
BinaryTree();
BinaryTree(Node<T> *root);
~BinaryTree();
Node<T>* getRoot();
void insert(Node<T> **root, Node<T> *node);
};
template<class T>
BinaryTree<T>::BinaryTree()
{
this->_root = NULL;
}
template<class T>
BinaryTree<T>::BinaryTree(Node<T> *root)
{
this->_root = root;
}
template<class T>
BinaryTree<T>::~BinaryTree()
{
// delete stuff
}
template<class T>
Node<T>* BinaryTree<T>::getRoot()
{
return this->_root;
}
template<class T>
void BinaryTree<T>::insert(Node<T> **root, Node<T> *node)
{
if(!*root)
{
*root = node;
}
}
Main:
BinaryTree<int> *tree = new BinaryTree<int>();
Node<int> *root = tree->getRoot();
Node<int> **root1 = &root;
cout << tree->getRoot() << endl;
Node<int> *noChildrenNode = new Node<int>(2);
tree->insert(&root1, noChildrenNode);
cout << tree->getRoot() << endl;
Inserts current functionality is just supposed to replace the NULL root pointer to the node pointer passed in as a parameter. The failing miserably part is since the pointer is a copy it isn't actually setting the root node.. but I can't seem to figure out how to set up a pointer to a pointer to the root node so it can be altered.. I've got to be close and any help will be MUCH appreciated.
Thanks
First, you've got to include the exact text of any error messages. "fails miserably" is not adequate.
I think you want
root = node;
Not
*root = node;
Because if root is null, using *root is a null pointer exception.