Simplest binary tree insertion is not working - c++

#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);
}

Related

Recursive length function implementation in a linked-list

I am implementing a linked-list, and one of the function asks for the number of nodes in the linked list. However, as the requirement says it needs to be done recursively.
Here is my implementation so far.
class LList {
public:
bool isEmpty() const;
void cons(int x);
int length() const;
private:
struct Node {
int item;
Node* next;
};
Node* head;
}
bool LList::isEmpty() const{
if(head == nullptr)
return true;
else
return false;
}
void LList::cons(int x){
Node* temp = new Node;
temp->item = x;
temp->next = head;
head = temp;
}
I can only do this iteratively, but couldn't make the recursion work.
int LList::length(Node* head) const{
Node* temp = head;
if (temp == nullptr) {
return 0;
}
return 1 + length(temp->next);
}
int LList::length() const {
return length(head);
}
I tried to use a helper function to do the job, but it's saying declaration is incompatible with int LList::length() const
Can anyone help me with this problem?
You are recursing the wrong place: You only have a single LList, so there is nothing to recurse on there. What you want to do instead is to recurse on the Node objects.
Keep your int LList::length() const function, but all it has to do is check if head is nullptr and then call the new recursive function that you are going to make: int LList::Node::length() const. This one then recurses through the next pointers of your Node objects and counts them.

Class member function works normally, but gets stuck in an infinite loop when called as a data member of another class

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.

C++: no matching function call

I am getting the above error and its pointing to my call for add(root, node). What does this error mean? I have tried moving the private add to the top but that doesnt work either. Also, it cant be because its private because its in the same class, right?
class Tree{
public:
Node *root;
Tree(Node *r){
root = r;
}
void add(Node node){
add(root, node);//error here
}
private:
void add(Node parent, Node node){
if(parent == root && root == nullptr){
root = node;
}
if(parent == nullptr){
parent(node->value, nullptr, nullptr);
}
else if(node > parent){
add(parent->right, node);
}
else {
add(parent->left, node);
}
Your function needs the signature
void add(Node* parent, Node* node)
Note that these are Node* instead of Node. The same goes for the public overload of that function
void add(Node* node)
This is apparent because 1) you are doing comparisons to nullptr and 2) you keep dereferencing your variables with -> instead of .
CoryKramer has spotted some errors, I'll add this also.
you can't compare pointers so it should be data:
else if(node->value > parent->value){
add(parent->right, node);

Binary Search Tree in C++

I have the following code to insert in the bst however, it fails to insert all the nodes except for the root. Any idea what I am doing wrong?
class Node
{
public:
int data;
Node* right;
Node* left;
Node(int data)
{
this->data = data;
}
Node() {}
};
class BST
{
public:
Node* head;
void insert(int data)
{
if (head == nullptr)
{
head = new Node(data);
head->data = data;
}
else
{
// head = new Node(data);
insertNode(data, head);
}
}
void insertNode(int data, Node* head)
{
if (head == nullptr)
{
head = new Node(data);
return;
}
if (head)
{
Node* temp = head;
if (temp->data > data)
{
insertNode(data, temp->left);
}
else if (temp->data <= data)
insertNode(data, temp->right);
}
}
};
The parameter head in insertNode shadows the member variable named head.
However, while that's a really bad practice, the other answer is the true reason for your error, so please select his answer instead (once you get it working, of course).
I'd recommend changing the signature of insertNode to
void insertNode(int data, Node*& node)
Also, you don't need to check for head == nullptr in insert. You have a duplicate check in insertNode
So insert could look like this:
void insert(data) {
insertNode(data, head);
}
Finally, you're not initializing head within the constructor. It's possible that head will be initialized to something other than nullptr, especially if you compile this in release mode. Add a constructor like this:
BST() : head(nullptr) {
// Other init stuff here if necessary
}
You'll also want to make Node* head a private data member instead of public.
insertNode() takes a copy of the pointer, so changes made inside the function have no effect on the actual pointer in the tree. What you want to do is take a reference to the pointer:
void insertNode(int data, Node*& head)
In your function " insertNode" you are using if(head) , this if will work only if head == 1 , and head is never equals to 1 because its a pointer , so this "if" is not working.!

Binary Search Tree: Issue with Insert Function

I've been researching how to create binary search trees and i have run into a problem when trying to create my own. I have to use the following private structure to create the tree. Every example that i have looked at uses left and right pointers pointing to the structure and i have to use left and right pointers pointing to my template class. I have been trying to figure out how to write the insert function for adding a new node into my tree but i keep running into problems because of the way these two pointers are setup. Does anyone have a clue on how to make it work with these two pointers below?
private:
struct BinaryNode
{
Comparable element;
BinarySearchTree<Comparable> *left;
BinarySearchTree<Comparable> *right;
};
BinaryNode *root;
};
This is my constructor
BinarySearchTree<Comparable>::BinarySearchTree() {
BinaryNode *temp;
temp = new BinaryNode;
temp->left= NULL;
temp->right= NULL;
root = temp;
}
Try the following:
public:
template <typename Comparable>
void insert(const Comparable& key)
{
root = insert(root, key);
}
private:
template <typename Comparable>
BinaryNode* insert(BinaryNode*& current_node, const Comparable& key)
{
if (current_node == nullptr)
{
// Create a leaf node and return it, thus attaching
// it to the node we last called the function with
return new BinaryNode{key, nullptr, nullptr};
}
if (key == current_node->element)
// duplicate element, take some action
else if (key < current_node->element)
current_node->left = insert(current_node->left, key);
else
current_node->right = insert(current_node->right, key);
return current_node;
}