Binary Search Tree in C++ - 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.!

Related

so i was just trying to implement a simple linked list in C++ but i dont seem to get past a segmentation fault

I have fixed some of the problems but still can't get past the segmentation fault in while loop of append function where the next of temp is updated.i have seen the segmentation fault in debugger when i stepped into the particular line. also a side note while posting here it gives many errors any way i can fix those
#include <iostream>
using namespace std;
class node{
public:
int data;
node* next;
node()
{
data=0;
next=nullptr;
}
node(int value)
{
data=value;
}
void setnext(node* obj)
{
next=obj;
}
};
class linkedlist{
public:
node* head;
node* tail;
linkedlist()
{
head=nullptr;
tail=nullptr;
}
void prepend(int data)
{
node* temp=new node(data);
temp->setnext(head); //updates the new next pointer
head=temp; //updates the head with new address
}
void append(int data)
{
node* temp=new node(data);
if(head==nullptr)
{
cout<<"the linked list is empty";
head=temp;
tail=temp;
temp=nullptr;
}
else {
while (temp!= nullptr)
{
temp = temp->next; //segmentation fault here
}
tail->setnext(temp);
tail = temp; //updates the tail with new address
}
}
void display()
{
node* temp=head;
while(temp!=nullptr)
{
cout<<temp->data<<"->";
temp=temp->next;
}
cout<<"NULL";
}
};
int main()
{
linkedlist obj;
obj.prepend(1);
obj.append(2);
obj.append(3);
obj.display();
}
After creating a new linkedlist, the default constructor of linkedlist should have initialized node* head and node* tail to nullptr.
Thus, the call obj.prepend(1); after linkedlist obj; does not prepend 1 into obj. As a result, node* head and node* tail are still both nullptr.
After that, if you call obj.append(2);, then tail->setnext(temp); results in a Segmentation Fault as tail is nullptr.
You should have checked whether the linkedlist is empty in linkedlist::prepend and linkedlist::append, if so, node* head and node* tail need to be properly initialized.
In your append() function you're using the 'tail' member before you've assigned a value to it.

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.

cant seem to connect my header file with my cpp file in linked list

Assuming the definition and libs are working, ie. <iostream>, <cassert>, #define__NODE_H__, etc
The question is : how do I insert a node at the head (part 1) and insert data at the head (part 2)?
My header file (part 1):
class Node {
public:
typedef int nodeDatatype;
Node(
const nodeDatatype& initData = nodeDatatype(),
Node* initLink = NULL)
{data = initData; link = initLink;}
void setData(const nodeDatatype& new_data) {data = new_data;}
void setLink(Node* new_link) {link = new_link;}
nodeDatatype getData() const {return data;}
const Node* getLink() const {return link;}
Node* getLink() {return link;}
private:
nodeDatatype data;
Node* link;
};
void insertHead(Node*& head, Node*& entry);
My implementation file function (part 1):
Node* insertHead(Node *head, Node *entry){
Node* newNode = entry;
newNode->setData = setData;
newNode -> next = NULL;
if(head == NULL){
head = newNode;
}
else{
newNode->next = head;
head = newNode;
}
return head;
}
Is this correct? Or am I suppose to add a Node::Node* scope?
For part 2, can I just insert data with the same function as I use for inserting a node at the head? Or does it need to be separate?
The error I get:
not being declared in scope
The requirements seem to me to be in addition to
void insertHead(Node*& head, Node*& entry);
you will need a
void insertHead(Node*& head, const Node::nodeDatatype & data);
the reference to avoid a copy of data (kind of pointless with an int, but the typedef could be changed to something beefier) and const because insertHead has no business modifying the data. The const also allows the function to accept a wider variety of variable types.
This insertHead overload would have to construct a Node to hold the data, and after that the Node accepting insertHead can be called. Eg:
void insertHead(Node*& head, const Node::nodeDatatype & data)
{
Node * newNode = new Node(data);
insertHead(head, newNode);
}
This is all predicated on
void insertHead(Node*& head, Node*& entry);
being implemented correctly and currently it is not. Let's fix that since the fix is really simple.
Node* insertHead(Node *head, Node *entry){
does not match the declaration. Use
void insertHead(Node*& head, Node*& entry){
instead. The rest of the function mostly does what you want, but does it in a very roundabout fashion.
Node* newNode = entry;
is not required. it doesn't do any harm, but let's gut it anyway and use entry all the way through.
newNode->setData = setData;
what is setData? What's wrong with the data already in the node?
newNode-> next = NULL;
if(head == NULL){
head = entry;
}
else{
newNode->next = head;
head = newNode;
}
No need for most of the above. The new node goes in ahead of head, so there's no need to test whether head's null or not, just point the new node's next at the same thing as head. In other words, always do the else case.
return head;
This used to make sense, but now after the matching the definition and the declaration. Don't return a value from a void function.
}
We wind up with
void insertHead(Node*& head, Node*& entry){
entry->next = head;
head = entry;
}
Bundling all this up we get,
class Node {
public:
typedef int nodeDatatype;
Node(
const nodeDatatype& initData = nodeDatatype(),
Node* initLink = NULL)
{data = initData; link = initLink;}
void setData(const nodeDatatype& new_data) {data = new_data;}
void setLink(Node* new_link) {link = new_link;}
nodeDatatype getData() const {return data;}
const Node* getLink() const {return link;}
Node* getLink() {return link;}
private:
nodeDatatype data;
Node* link;
};
void insertHead(Node*& head, Node*& entry);
void insertHead(Node*& head, const Node::nodeDatatype & data);
And then the implementations
void insertHead(Node*& head, Node*& entry){
entry->link = head; // this line is currently impossible due to link being private
// perhaps these functions should be reworked into members
head = entry;
}
void insertHead(Node*& head, const Node::nodeDatatype & data)
{
Node * newNode = new Node(data);
insertHead(head, newNode);
}
Sidenote: Instead of typedef int nodeDatatype;, consider making the class a template.
What version of c++ are you using? Try setting up in wandbox or something. So you can easily copy the exact messages into your question.
Some comments:
Errors
use std::shared_ptr<> not raw pointers. You will get something wrong if you use raw pointers.
insertHead() should be either a member function or a friend function, at the moment is is neither. I assume it should be a member function.
what is ->setData??
what is ->next??
write some tests for insertHead() to cover different situations (each half of the if, etc)
just using int for your data will cover up some errors when you change to using real data. Use a template to help avoid this.
Style
use nullptr not NULL
use using nodeDataType = int or template<T=int> not typedef int nodeDataType

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

Accessing an element within my custom linked list class

I'm building my own linked list class and I'm having some issues figuring out how to write some functions to help me traverse this list. This is my first time building a linked list from scratch, so if my approach is unconventional please let me know what might be more conventional.
I'd like write a function, within the List class that allows me to increment to the next element called getNext() as well as one that getPrev();
I wrote getNext like this:
T* getNext(){return next;}
However it tells me next is not declared within the scope. I'd also like to write a function that lets me access and modify the object within the list. I was considering using the bracket operator, but first I need to write a function to return the data member. Perhaps If I take a similar approach as I did within my pop functions.. thinking about it now. However, I'd still appreciate any advice.
Here is my List class:
#ifndef LIST_H
#define LIST_H
//List Class
template <class T>
class List{
struct Node {
T data;
Node *next;
Node *prev;
//Constructs Node Element
Node(T t, Node* p, Node* n) { data = (t); prev = (p); next = (n); }
// T *getNext() {return next;}
};
Node *head;
Node *tail;
public:
//Constructor
List() { head = NULL; tail=NULL; }
//Destructor
~List() {
while(head){
Node * temp(head);
head = head->next;
delete temp;
}
}
//is empty
bool empty() const {return (!head || !tail ); }
operator bool() const {return !empty(); }
//Push back
void push_back(T data) {
tail = new Node(data, tail, NULL);
if(tail->prev) //if the node in front of tail is initilized
tail->prev->next = tail;
if( empty() )
head = tail;
}
//Push front
void push_front(T data) {
head = new Node(data, NULL, head);
if(head->next)//if the node following head is initilized
head->next->prev = head;
if( empty() )
tail = head;
};
T pop_back() {
if( empty() )
throw("Error in List: List is empty\n");
Node* temp(tail);
T data(tail->data);
tail = tail->prev;
if( tail )
tail->next = NULL;
else
head = NULL;
delete temp;
return data;
}
T pop_front() {
if (empty())
throw("Error in List: List is empty\n");
Node* temp(head);
T data(head->data);
head = head->next;
if(head)
head->prev=NULL;
else
tail = NULL;
delete temp;
return data;
}
T getNext(){return next;}
};
#endif
getNext should be part of the struct Node and return a Node*
Node* getNext() { return next; }
Then from that you can get the value.
If you have to have it part of the list itself, which I would not recommend it will need to take a parameter of what Node you would like the next of:
Node* getNext(Node* n) {return n->next;}
Again, I recommend the first option.
Here is an approximate whole class with both of these:
template<typename T>
class List {
public:
struct Node {
Node* next, prev;
T data;
//some constructor and stuff
Node* Next() {return next;}
}
//some constructors and other functions
Node* getNext(Node* _n) {return _n->Next();}
}
then to use:
int main() {
List<int> l;
//add some stuff to the list
//get the head of the list
List<int>::Node* head = l.head; //or some corresponding function
//then
List<int>::Node* next = head->Next();
//or
List<int>::Node* next2 = l.getNext(head);
}
for starters getNext() should not return a pointer to the template class, it should return a pointer to the Node structure.
So it should be
Node* getNext(){return next;}
Because it's a member of Node struct and getNext is member of List. You should access it from an object of type Node.