Binary Search Tree Forgetting Every Node I Add - c++

My problem is seemingly simple, but I can't find its solution. I have a binary tree, and this is my add function:
void collection::addToTree(vendor *& item)
{
Node * curr = root;
while (curr)
{
if (strcmp(item->getName(), root->item->getName()) < 0)
curr = curr->left;
else
curr = curr->right;
}
curr = new Node(item);
}
And this is my Node constructor:
collection::Node::Node(vendor *& item) : left(nullptr), right(nullptr)
{
this->item = item;
}
However, the tree is always empty, no matter what or how many items I try to add to it. The only other piece of code I can think of that will help you guys is my struct for my tree:
struct Node
{
Node();
Node(vendor *& item);
vendor * item;
Node *left, *right;
};
Node * root;
All of the sub-variables of vendor do have values (as I've seen in my debugger). I wish I could give you guys more detail, but this is all I know about the error. Any feedback is greatly appreciated.

In the add function, you're making only curr point to the new item, but that does not change back the previous left/right pointers, which probably is what you were aiming at.

You need to modify the left/right pointers directly, something like this:
void collection::addToTree(vendor *& item)
{
Node * curr = root;
while (curr)
{
if (strcmp(item->getName(), curr->item->getName()) < 0)
{
if (!curr->left)
{
curr->left = new Node(item);
return;
}
curr = curr->left;
}
else
{
if (!curr->right)
{
curr->right = new Node(item);
return;
}
curr = curr->right;
}
}
root = new Node(item);
}
Also, make sure you do Node * root = nullptr, as no initializing it can lead to it containing any arbitrary value.
Notice that I also changed if (strcmp(item->getName(), root->item->getName()) < 0) to if (strcmp(item->getName(), curr->item->getName()) < 0), as the branching is dependent on curr, not root.

I think the problem here is that your curr variable should be declared as Node **curr and receive the root's address in order for the change to be visible outside of the addToTree function.
void collection::addToTree(vendor *& item)
{
Node ** curr = &root;
while (*curr)
{
if (strcmp(item->getName(), (*curr)->item->getName()) < 0)
(*curr) = (*curr)->left;
else
(*curr) = (*curr)->right;
}
*curr = new Node(item);
}

Related

Removing a node from a doubly linked list

I have looked at other threads here on the topic, but have no been able to use them to solve my problem.
this is the main class definition of a node in the linked list:
class node {
public:
// default constructor
node() {name = ""; prev = NULL; next = NULL;};
// default overloaded
node(string s) {name = s; prev = NULL; next = NULL;};
// item in the list
string name;
// links to prev and next node in the list
node * next, * prev;
};
the above is the node class definition, which is used in another class that generates a linked list. the linkedlist code was given to us, which we had to modify, so I know it works. I have gone through and tested the addition of new nodes in the doubly linked list to be working, and I am now working on removing nodes from this same doubly linked list.
The function to remove a node: http://pastebin.com/HAbNRM5W
^ this is the code I need help with, there is too much to retype
I was told by my instructor that the code that is the problem is the line 56, which reads:
tmp->prev = prev;
I am trying to set the link to the previous node to be the correct one. the case I am trying to work from with the similar if/else loops is whether or not the current node is the last item in the list. if it is the last item (aka curr->next = NULL), then don't set a link using curr->next and stop the loop iteration.
any help / ideas / suggestons / feedback will be greatly appreciated!
void linkedList::remove(string s)
{
bool found = false;
node * curr = getTop(), * prev = NULL;
node * tmp = new node();
while(curr != NULL)
{
// match found, delete
if(curr->name == s)
{
found = true;
// found at top
if(prev == NULL)
{
node * temp = getTop();
setTop(curr->next);
getTop()->prev = NULL;
delete(temp);
} // end if
else
{
// determine if last item in the list
if (curr->next = NULL)
{
// prev node points to next node
prev->next = curr->next;
// delete the current node
delete(curr);
} // end if
// if not last item in list, proceed as normal
else
{
// prev node points to next node
prev->next = curr->next;
// set the next node to its own name
tmp = prev->next;
// set prev-link of next node to the previous node (aka node before deleted)
tmp->prev = prev;
// delete the current node
delete(curr);
} // end else
} // end else
} // end if
// not found, advance pointers
if(!found)
{
prev = curr;
curr = curr->next;
} // end if
// found, exit loop
else curr = NULL;
} // end while
if(found)
cout << "Deleted " << s << endl;
else
cout << s << " Not Found "<< endl;
} // end remove
NULL should be replaced with nullptr
if (curr->next = NULL) { ...
That is an assignment, you want:
if (curr->next == nullptr) { ...
On line 47 I think you say: if prev == nullptr and next is not nullptr , but you use
prev->next = curr->next;
Which doesn't work since prev is nullptr.
For your code, I suggest several things. Isolate the code to find the node with the name you are looking for. The remove method SHOULD only remove a doubly linked node, provided that it is given one.
I know that your remove method takes in a string parameter, but pass that to another function and have that function return the node you are looking for.
It should look something like this:
Node *cur = find("abcd");
Node *prev = cur->prev;
prev->next = cur->next;
Node *n = cur->next;
n->next = cur->prev;
cur->next = NULL; //or nullptr
cur->prev = NULL; //or nullptr
delete cur;
Should look like:
prev->next = curr->next;
prev->next->prev = prev;
delete (curr);
I got lost in all your different conditionals. All you need to do is this:
void linkedList::remove(const std::string& s)
{
node* current = getTop(); // get head node
while (current != nullptr) // find the item you are trying to remove
{
if (current->name == s)
{
break; // when you find it, break out of the loop
}
}
if (current != nullptr) // if found, this will be non-null
{
if (current->prev) // if this is not the head node
{
current->prev->next = current->next;
}
else
{
// update head node
}
if (current->next) // if this is not the tail node
{
current->next->prev = current->prev;
}
else
{
// update tail node
}
// at this point, current is completely disconnected from the list
delete current;
}
}

Iterative BST insertion in C++

I am trying to understand BSTs and how to insert elements into it iteratively. My node structure implementation looks like so:
struct Node{
Node *left;
Node *right;
T data; //template class
};
And my insertion implementation looks like so:
template<typename T>
bool BST<T>::Insert(const T value)
{
Node *newNode = new Node;
newNode -> data = value;
newNode -> left = NULL;
newNode -> right = NULL;
if(root == NULL) {root = newNode;} //If the BST is empty
else
{//The BST is not empty
Node *ptr = root; //points to the current Node
Node *ptr_parent; //points to the parent Node
while(ptr != NULL)
{
if((ptr -> data) > value)
{
ptr_parent = ptr;
ptr = ptr -> left;
}
if((ptr -> data) < value)
{
ptr_parent = ptr;
ptr = ptr -> right;
}
}
}
ptr = newNode; //insert the newNode at the spot
if((ptr_parent -> data) < value)
ptr_parent -> right = newNode;
else
ptr_parent -> left = newNode;
return true;
}
The insertion works when adding the first Node into an empty tree but I get a segmentation fault whenever i try to add more Nodes. I understand that there are posts that show how to implement insertions into BSTs but most of them show the recursive method, and those with iterative examples are incomplete or too specific. Thank you.
I think I'd do things a little differently. First, I'd simplify the other code a little by adding a ctor to the Node class:
struct Node{
Node *left;
Node *right;
T data;
Node(T const &data) : left(nullptr), right(nullptr), data(data) {}
};
Then you can use a pointer to a pointer to traverse the tree and insert the item:
bool insert(const T value) {
Node **pos;
for (pos = &root; *pos != nullptr;) {
if (value < (*pos)->value)
pos = &(*pos)->left;
else if ((*pos)->value < value )
pos = &(*pos)->right;
else
return false;
}
*pos = new Node(value);
return true;
}
Note that I've delayed creating the new node until after we've dropped out of the loop. This way, if we have a duplicate element, we can just return (without leaking a node, since we haven't allocated a new node yet).
For what it's worth, if you were going to do this recursively, it would probably be easier to use a reference to a pointer instead of a pointer to a pointer.
I was able to make my original code work last night, I'm sharing the answer here:
template<typename T>
bool BST<T>::Insert(const T value)
{
Node *ptr;
Node *ptr_parent;
if(root == NULL)
{//The BST is Empty...
Node *newNode = new Node;
newNode -> data = value;
newNode -> left = NULL;
newNode -> right = NULL;
root = newNode;
ptr = root;
} else { //traversing the tree to find the insertion point
ptr = root;
while(ptr != NULL)
{
if((ptr -> data) == value) {return false;} //to check for duplicates
if(value < (ptr -> data))
{
ptr_parent = ptr;
ptr = ptr -> left;
} else {
ptr_parent = ptr;
ptr = ptr -> right;
}
}
Node *newNode = new Node;
newNode -> data = value;
newNode -> left = NULL;
newNode -> right = NULL;
//checking for parent value to determine if
//the Node is a left or right child
if(value < (ptr_parent -> data))
ptr_parent -> left = newNode;
else
ptr_parent -> right = newNode;
}
++count;//to keep track of the Node count
return true;
}
For my own sake I wanted to solve this without using double pointers.
You didn't handle the case when ptr->data == value so the loop will be infinite whenever a duplicate is found, and ptr = newNode doesn't do anything, it just makes ptr point to newNode. Try this
//ptr holds the address of pointers to nodes.
Node **ptr = &root;
while(*ptr != NULL){
if((*ptr)->data > T)
ptr = &(*ptr)->right;
else
ptr = &(*ptr)->left;
//Not handling duplicates
}
//Change the value of the pointer to newNode
*ptr = newNode;
Use hard pointers
Node **ptr = &root; //points to the current Node
Node **ptr_parent; //points to the parent Node
When you are trying to do this
ptr = newNode; //insert the newNode at the spot
it doesn't do anyithing because you need to modify the pointer which points to the left or the right subnode
something like this:
template<typename T>
bool BST<T>::Insert(const T value)
{
Node *newNode = new Node;
newNode -> data = value;
newNode -> left = NULL;
newNode -> right = NULL;
if(root == NULL) {root = newNode;} //If the BST is empty
else
{//The BST is not empty
Node **ptr = &root; //points to the current Node
Node **ptr_parent; //points to the parent Node
while((*ptr) != NULL)
{
if(((*ptr) -> data) > value)
{
ptr_parent = ptr;
ptr = &ptr -> left;
}
if(((*ptr) -> data) < value)
{
ptr_parent = ptr;
ptr = &ptr -> right;
}
}
}
(*ptr) = newNode; //insert the newNode at the spot
if(((*ptr_parent) -> data) < value)
(*ptr_parent) -> right = newNode;
else
(*ptr_parent) -> left = newNode;
return true;
}
As I understand, it is failing because of following line:
ptr = newNode; //insert the newNode at the spot
after the while loop your ptr is NULL otherwise you can not exit from the while loop. You are assigning a struct to NULL, which is not right.
Hopefully this helps. Everything else looks normal.
void insert(node* root, int value)
{
if (root == NULL)
{
root = new node;
root->data = value;
return;
}
while(!((root->data < value && root->right == NULL) || (root->data >= value && root->left == NULL)))
{
if (root->data < value)
root = root->right;
else
root = root->left;
}
if (root->data < value)
{
root->right = new node;
root->right->data = value;
} else
{
root->left = new node;
root->left->data = value;
}
}
template <class T>
class TreeNode{
private:
T data;
TreeNode<T>* right,*left;
public:
void setData(T d){
this->data =d;
}
T getData(){
return this->data;
}
void setRight(TreeNode<T>* r){
this->right =r;
}
TreeNode<T>* getRight(){
return this->right;
}
void setLeft(TreeNode<T>* r){
this->left =r;
}
TreeNode<T>* getLeft(){
return this->left;
}
static TreeNode<T>* newNode(T data){
TreeNode<T>* n = new TreeNode<T>();
n->setData(data);
n->setRight(NULL);
n->setLeft(NULL);
return n;
}
};
template <class T>
class BinaryTree{
private:
TreeNode<T>* root;
public:
void insert(T data){
TreeNode<T>* n = TreeNode<T>::newNode(data);
if(root==NULL)
root = n;
else{
TreeNode<T>* t = root;
while(t!=NULL){
if(n->getData() >= t->getData()){
if(t->getRight()==NULL){
t->setRight(n); //newnode attached as right child in tree
t = NULL;
}
else
t = t->getRight();
}
else{
if(t->getLeft()==NULL){
t->setLeft(n); //newnode attached as left child in tree
t=NULL;
}
else
t = t->getLeft();
}
}
}
}
void preorder(){
TreeNode<T>* t = root;
preorderUtil(t);
}
void preorderUtil(TreeNode<T>* node){
if(node==NULL)
return;
preorderUtil(node->getLeft());
cout<<node->getData()<<" ";
preorderUtil(node->getRight());
}
};
I answered a case here Binary Search Tree insertion doesn't work see if it helps
void insert(int val)
{
Node *newNode;
newNode=new Node;
newNode->data=val;
Node *currentNode=root;
Node *parentNode;
if(root==NULL)
{
newNode->left=NULL;
newNode->right=NULL;
}
else
{
while(currentNode!=NULL)
{
if((currentNode->data)>val)
{
parentNode=currentNode;
currentNode=currentNode->left;
}
if((currentNode->data)<val)
{
parentNode=currentNode;
currentNode=currentNode->right;
}
}
}
currentNode=newNode;
if((parentNode->data)<val)
{
parentNode->right=newNode;
}
else
{
parentNode->right=newNode;
}
}

C++ - OOP implementation of linked list, I not sure why adding to end is not working for me, please advise

I am refreshing my knowledge of C++ OOP but not sure why I can get this traversal and adding to end of list up and running. Any advice on this context would be highly appreciated.
#include "stdafx.h"
#include "LinkedList.h"
LinkedList::LinkedList(void)
{
}
LinkedList::~LinkedList(void)
{
}
void LinkedList::add(Node* node)
{
Node* root = this->getRoot();
if(root !=NULL)
{
//with two nodes the commented code worked
//while(root->getNextNode() != NULL){}
//root->setNextNode(node);
//this part is culprit
Node* newNode = root->getNextNode();
while(newNode!=NULL)
{
newNode = newNode->getNextNode();
}
//I was thinking I am reaching to last node using this traversal
newNode = new Node(node->getData(),node->getNextNode());
}else
{
this->setRoot(node);
}
};
void LinkedList::traverseNodes()
{
Node* node = this->getRoot();
printf("\ntraversing the nodes:");
while(node != NULL){
printf("%d", node->getData());
node = node->getNextNode();
}
}
The problem with your code is that once you set the pointer newNode to NULL, pointing it to a new node won't change the previous last node.
Try this:
Node* root = this->getRoot();
if (root != NULL) {
Node* parent = root;
while(true) {
// two variables mean you have access to the previous node,
// which is needed to add the next one.
Node* child = parent->getNextNode();
if (child != NULL) {
parent = child;
} else {
parent->setNextNode(/* new node */);
break; // EDIT
}
}
} else //...
That fault is because you did not append at end, actually, you can fix the code by something like following
Node* previouseNode = this->getRoot();
while(previouseNode->getNextNode() != NULL)
{
previouseNode = previouseNode->getNextNode();
}
//Next node of previouseNode is null so you can assign to it
Node * newNode = new Node(node->getData(), previouseNode); // Maybe your list is bi-directional!
previouseNode->setNextNode(newNode);
When you have reached NULL it is too late, you need to keep track of the node before.
void LinkedList::add(Node* node) {
Node* current = this->getRoot();
if (current != NULL) {
while(current->getNextNode() != NULL) {
current = current->getNextNode();
}
current->setNextNode(node);
} else {
this->setRoot(node);
}
};

Deleting a node in the linklist

Here is my code to delete all the nodes having the value passed in the argument.
typedef struct nodetype
{
int data;
struct nodetype * next;
} node;
typedef node * list;
void Linklist::deleteNode(list * head, int value)
{
list current = *head;
list previous = *head;
while(current != NULL)
{
if(current->data != value)
{
previous = current;
current = current->next;
}
else if (current->data == value)
{
previous->next = current->next;
delete current;
current = previous->next;
}
}
}
But here if all the elements in the linklist is say 2, then it should delete all the elements in the linklist and finally head should also become NULL so that if I pass this head to count the number of nodes in the list it should say that the list is empty and other similar operations.
According to my current implementation the head is not becoming NULL for the above mentioned case.
Please suggest the modification so that head should become NULL if the linklist has all the nodes with the same value passed in the function argument.
I modified my code as follows and its working file now
void Linklist::deleteNode(list *head, int value)
{
list * current = head;
list * previous = head;
bool flag = false;
while(*current != NULL)
{
if((*current)->data != value)
{
*previous = *current;
*current = (*current)->next;
}
else if ((*current)->data == value)
{
flag = true;
(*previous)->next = (*current)->next;
delete *current;
*current = (*previous)->next;
}
}
if(!flag)
cout<<"Element not found in the linklist\n";
cout<<"Count is "<<Linklist::count(*head)<<endl;
}

Implementing push/pop in a linked list (C++)

I'm trying to incorporate push/pop into a linked list and I can't seem to get it to work. When I run my test function, I set my linked list to zero and I try to push on values but the list keeps getting returned with no values in it. Could anyone possibly tell me what I'm doing wrong?
if (top == NULL){
current = top;
current->next = NULL; //NULL->next : will cause segfault
}
if top is NULL, you set current = top [which is NULL], and then you access current->next, which will cause a segfault, you are trying to access NULL..
EDIT: follow up to comments:
your if statement seems redundant, you should probably only need to set: current->next = head; and head = current; [in addition to the current allocation]
Instead of
if (top == NULL){
current = top;
current->next = NULL;
}
you want
if (top == NULL){
top = current;
current->next = NULL;
}
And of course, after this, you have to make sure that you actually set head to top again.
Now that you've made this change, it should be clear that both cases do the same thing -- so no case distinction is actually necessary. So the function can be simplified to
void push(Data * newPushData){
LinkNode * current = new LinkNode(newPushData);
current->next = head;
head = current;
}
The top variable is local variable for push(...) function. You can use head instead, and I'd rather modify the if statement.
I think that function should look like this:
void push(Data * newPushData){
LinkNode * current = new LinkNode(newPushData);
if (head != NULL){
current->next = head;
head = current;
}
else{
head = current;
current->next = NULL; // if you haven't done it in LinkNode constructor
}
}
can you please specify the attributes of the linked list class ? [ is there slightly chance you are doing something wrong]
Instead of you , I'd do :
void push(Data * newPushData){
if (head == NULL)
head->data = newPushData
tail = head ;
else // regular situation
{
Node * node = new Node() ;
tail->next = node;
node->data = newPushData;
node->next = NULL ;
tail = node ;
}
}
In a linked list you have got to maintain the head pointer point on the head of the list , maintain that the tail pointer is point on the tail of the list ,
You must take care of the 2 cases of enlarging the list.
the best way for learning is to illustrate an insertion on a blank linked list.
Take care
S
void push(Data * newPushData)
{
if( head != NULL )
{
LinkNode current = new LinkNode(newPushData);
current->next = head;
head = current;
}
else
{
head = new LinkNode(newPushData);
}
}
Try this code...
void push(data * newpushdata){
if(head !=null){
linkednode current = new linkednode(newpushdata);
current->next = head;
head = current;
}
else {
head = new linkednode(newpushdata);
}
}
that is my working solution for a Stack containing int elements, but maybe it's better to create a void pushStack using Stack **S instead of Stack *S.
in pop(Stack **S) i created a sentinel, so if the stack is empty -1 is returned.:
typedef struct StackT {
int val;
struct StackT *next;
} Stack;
int isStackEmpty (Stack *S) {
if (S == NULL)
return 1;
else
return 0;
}
int *pop(Stack **S) {
Stack *tmp = *S;
int i = -1;
if (isStackEmpty(tmp) == 0) {
i = tmp->val;
*S = tmp->next;
}
return i;
}
Stack *pushStack (Stack *S, int x) {
Stack *node = (Stack *) malloc (sizeof (Stack));
node->val = x;
node->next = S;
return node;
}
you can call pop and stack easly:
Stack *S = NULL;
int x = somevalue;
int y;
S = pushStack(S, x);
y = pop(&S);