Where is the flaw in my binary tree insertion logic? - c++

My solution is like
/*
Node is defined as
typedef struct node
{
int data;
node * left;
node * right;
}node;
*/
node * insert (node * root, int value)
{
bool inTreeAlready = false;
node * cur = root;
while(cur != NULL)
{
if(cur->data < value)
cur = cur->right;
else if(cur->data > value)
cur = cur->left;
else
{
inTreeAlready = true;
break;
}
}
if(!inTreeAlready)
{
cur = new node;
cur->data = value;
cur->left = NULL;
cur->right = NULL;
}
return root;
}
where the prompt to the problem says you're supposed to return the root of the tree after insertion.
This is evidently wrong as the output is
Wrong Answer!
Some possible errors:
1. You returned a NULL value from the function.
2. There is a problem with your logic
3. You are printing some value from the function
which isn't very descriptive.
I've double-checked my logic and don't know what the deal is.

You didn't add the new node into the tree. Here's a modified version.
node * insert (node * root, int value)
{
bool inTreeAlready = false;
node * cur = root;
node *parent;
bool right;
while(cur != NULL)
{
parent = cur;
if(cur->data < value)
{
cur = cur->right;
right = true;
}
else if(cur->data > value)
{
cur = cur->left;
right = false;
}
else
{
inTreeAlready = true;
break;
}
}
if(!inTreeAlready)
{
cur = new node;
cur->data = value;
cur->left = NULL;
cur->right = NULL;
if(root == NULL) root = cur;
else if(right) parent->right = cur;
else parent->left = cur;
}
return root;
}

Related

What could cause a Cyclical Linked List [closed]

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed yesterday.
Improve this question
I am trying to make a quicksort algorithm for singly-linked lists. I, however, must be somehow creating a cyclical list in the process. In the concatenate function, the while loop gets stuck printing out 2 and 22 continuously. So, I assume that I must somehow be creating a list where Node 2 points to Node 22 and vice versa. Unfortunately, I have no idea how, since I feel like I have added nullptr to the end of every list where it would matter. I have reviewed my partition function so many times I add more bugs than I fix. Is there something I am missing with how linked lists work?
I have been stuck on this for a while so any help would be greatly appreciated.
Here is my quicksort code.
// quick.cpp
#include "volsort.h"
#include <iostream>
#include <string>
using namespace std;
// Prototypes
Node *qsort(Node *head, bool numeric);
void partition(Node *head, Node *pivot, Node *&left, Node *&right, bool numeric);
Node *concatenate(Node *left, Node *right);
// Implementations
void quick_sort(List &l, bool numeric) {
l.head = qsort(l.head, numeric);
}
Node *qsort(Node *head, bool numeric) {
if (head == nullptr || head->next == nullptr) {
return head;
}
Node *l = nullptr;
Node *r = nullptr;
partition(head, head, l, r, numeric);
l = qsort(l, numeric);
r = qsort(r, numeric);
head = concatenate(l, head);
head = concatenate(head, r);
return head;
}
void partition(Node *head, Node *pivot, Node *&left, Node *&right, bool numeric) {
Node *cur = pivot->next;
bool c;
Node *tl=nullptr, *tr=nullptr;
while (cur != pivot && cur != nullptr) {
if (numeric) {
c = node_number_compare(cur, pivot);//compare numeric elements of the Nodes
}
else {
c = node_string_compare(cur, pivot);//compare string elements of the code
}
if (c) {
if (left == nullptr) {
left = cur;
cur = cur->next;
tl = left;
}
else {
tl->next = cur;
cur = cur->next;
tl = tl->next;
tl->next = nullptr;
}
}
else {
if (right == nullptr) {
right = cur;
cur = cur->next;
tr = right;
}
else {
tr->next = cur;
cur = cur->next;
tr = tr->next;
tr->next = nullptr;
}
}
}
}
Node *concatenate(Node *left, Node *right) {
if (right == nullptr && left == nullptr) {
return nullptr;
}
else if (left == nullptr) {
right->next = nullptr;
return right;
}
else if (right == nullptr) {
left->next = nullptr;
return left;
}
Node *t = left;
while (t->next != nullptr) {
cout << t->number << endl;
t = t->next;
}
t->next = right;
while (t->next != nullptr) {
cout << t->number << endl;
t = t->next;
}
t->next = nullptr;
return left;
}
Input:
45
4
9
22
2
Here's the list class functions if it helps.
#include "volsort.h"
#include <string>
#include <iostream>
List::List() {
head = NULL;
size = 0;
}
List::~List() {
if (head != NULL) { // follow the links, destroying as we go
Node *p = head;
while (p != NULL) {
Node *next = p->next; // retrieve this node's "next" before destroy it
delete p;
p = next;
}
}
}
bool node_number_compare(const Node *a, const Node *b) {
if (a->number <= b-> number) {
return true;
}
else {
return false;
}
}
bool node_string_compare(const Node *a, const Node *b) {
return a->string <= b->string;
}
void List::push_front(const std::string &s) {
Node *node = new Node();
node->next = NULL;
node->string = s;
node->number = std::stoi(s);
if (head == NULL) {
head = node;
size = 1;
}
else {
Node *p = head;
while (p->next != NULL) {p = p->next;} // go to end of list
p->next = node;
size++;
}
}
void List::dump_node(Node *n) {
while (n->next != NULL) {
std::cout << n->number << " " << n->string << std::endl;
}
}

BST node deletion loop in C++

I'm building a function for deleting a node in a binary tree; since two of three cases are fairly simple (no children and 1 child) I've built another function to "re-arrange" the nodes beneath the one I'm trying to delete, in case it has two children.
I built the function so that it returns a pointer, which is the re-arranged subtree, but I've also tried making a function that just changes the tree itself, without returning a value, but both seem to create a loop where the tree changes: when I try to print the tree, it's stuck printing between the value I replace and it's left child, back and forth until eventually a segfault 11 pops up. I'm really lost as even the debugger isn't helping me understand where the issue is, can anyone tell me where to look? Thank you in advance for your kind attention and your time
Here is the tree I was thinking of before the deletion:1
And here it is after the deletion:2
'''
if (found the value) // value is head (recursive)
{
Node* to_delete = head;
...
head = subNode (head);
delete to_delete;
}
'''
Node* b_tree :: subNode (Node*&head)
{
Node*curr = head->right;
if (((!curr->right) && (!curr->left)) || (!curr->left)) // if it's a leaf or at least if the left pointer is NULL
{
curr->left = head->left;
head->left = NULL;
Node*to_return = curr;
return to_return;
}else // if there's a lower value...
{
while (curr->left != NULL) // find the lowest in the sub-tree
{
curr = curr->left;
}
if (!curr->right)
{
curr->right = head->right;
curr->left = head->left;
Node* to_return = curr;
curr = NULL;
return to_return;
} else {
Node* temp = curr->right;
curr->right = head->right;
curr->left = head->left;
Node*to_return = curr;
curr = temp;
return to_return;
}
}
};
''' Here's the whole code
'''
#include <iostream>
#include <iomanip>
#include <string>
using namespace std;
struct Node
{
Node ();
Node (string, int);
string name;
int value;
Node* left;
Node* right;
};
Node :: Node ()
{
left = right = NULL;
}
Node :: Node (string nome, int valore)
{
this->name = nome;
this->value = valore;
this->left = NULL;
this->right = NULL;
};
class b_tree
{
private:
Node* head;
void insRic (Node*&, Node);
void stampaRic (Node*);
void deleteRic (Node*&, Node);
Node* subNode (Node*&);
public:
b_tree ();
void inserimento (Node);
void delete (Node);
void stampa ();
};
b_tree :: b_tree ()
{
this->head = NULL;
};
void b_tree :: inserimento (Node temp)
{
insRic(this->head, temp);
};
void b_tree :: insRic (Node*& head, Node temp)
{
if (head != NULL)
{
if (temp.value < head->value)
{
insRic(head->left, temp);
} else if (temp.value > head->value)
{
insRic(head->right, temp);
}
} else
{
head = new Node (temp.name, temp.value);
}
};
void b_tree :: stampa ()
{
stampaRic (this->head);
};
void b_tree :: stampaRic (Node* head)
{
if (head != NULL)
{
if (head->left != NULL)
{
stampaRic (head->left);
}
cout << "Nome: " << head->name << " | Valore: " << head->value << endl;
if (head->right != NULL)
{
stampaRic (head->right);
}
}
};
Node* b_tree :: subNode (Node*&head)
{
Node*curr = head->right;
if (((!curr->right) && (!curr->left)) || (!curr->left)) // if it's a leaf or at least if the leftious pointer is NULL
{
curr->left = head->left;
head->left = NULL;
Node*to_return = curr;
return to_return;
}else // if there's a lower value...
{
while (curr->left != NULL) // find the lowest in the sub-tree
{
curr = curr->left;
}
if (!curr->right)
{
curr->right = head->right;
curr->left = head->left;
Node* to_return = curr;
curr = NULL;
return to_return;
} else {
Node* temp = curr->right;
curr->right = head->right;
curr->left = head->left;
Node*to_return = curr;
curr = temp;
return to_return;
}
}
};
void b_tree :: delete (Node temp)
{
deleteRic (this->head, temp);
};
void b_tree :: deleteRic (Node*& head, Node temp)
{
if (head != NULL) // if head points ot something
{
if (head->value != temp.value) // if the node I'm trying to delete has a different name, jusr call it again until it finds it
{
if (temp.value < head->value)
{
eliminaRic (head->left, temp);
} else if (temp.value > head->value)
{
eliminaRic (head->right, temp);
}
} else // once I've found the value I'm trying to delete;
{
Node*to_delete = head;
if ((head->right == NULL) && (head->left == NULL)) // checking that the node is not a leaf
{
head = NULL;
delete to_delete;
} else if (head->left == NULL) // if leftious pointer is null
{
to_delete = head->right;
delete to_delete;
} else if (head->right == NULL) // if right pointer in null
{
head = head->left;
delete to_delete;
}
else if ((head->right != NULL) && (head->left != NULL)) // if neither pointer is null (2 children);
{
head = subNode (head);
delete to_delete;
}
}
}
}
int main ()
{
b_tree*albero = new b_tree ();
Node temp = Node ();
for (int i = 0; i < 7; i++)
{
cout << "Insert name and value; name: "; cin >> temp.name; cout << " value : "; cin >> temp.value; cout << endl;
albero->inserimento(temp);
}
albero->stampa();
cout << "Insert the value of the node you wish to delete: "; cin >> temp.value;
albero->delete(temp);
albero->stampa();
}
'''
Here are some issues:
The main problem is in the second half of subNode. The following line (that occurs twice) creates a cycle:
curr->next = head->next;
As curr is a descendant of head->next, this closes a cycle. This cycle is not broken by anything that follows.
curr = NULL or curr = temp is useless. It only sets a value of a variable and doesn't mutate the tree (which may be what you thought it did).
to_return should not be set to curr, but to head->next.
Not a problem, but the if condition at the top of subNode is equivalent to just !curr->prev.
Not a problem, but head->prev = NULL is not really needed, as head is going to be deleted anyway.
When these points are taken into account, some code repetition can be avoided, and the code can be reduced to the following:
Node* b_tree :: subNode (Node*&head)
{
Node* curr = head->next;
while (curr->prev != NULL)
{
curr = curr->prev;
}
curr->prev = head->prev;
return head-next;
};
Side note: this algorithm will more quickly increase the gravity with which the tree is unbalanced, as a whole subtree is moved at a lower place in the tree. This may even double the height of the tree with just one delete operation. I would therefor prefer the original, popular algorithm for deletion.

counting the number of vertices in a subtree

I wrote an AVL tree, I'm sure that it works correctly, but my vertex counting does not work for the subtree. Help find a mistake.
I am sure that the error is in this part of the delete function, if this is not enough, I will write its full part.
If I’m fundamentally wrong, then tell me how to implement the algorithm for finding the number of vertices in a subtree for an AVL tree
class Node
{
public:
int key;
Node *left;
Node *right;
int height;
int kol; // number of vertices in the subtree
};
Node* newNode(int key){
Node* node = new Node();
node->key = key;
node->left = nullptr;
node->right = nullptr;
node->height = 1;
node->kol = 1;
return node;
}
Node* minValueNode(Node* node){
Node* current = node;
while (current->left != nullptr)
current = current->left;
return current;
}
Node* deleteNode(Node* root, int key)
{
if (root == NULL)
return root;
if ( key < root->key ){
root->left = deleteNode(root->left, key);
root->kol--;
}
else if( key > root->key ){
root->right = deleteNode(root->right, key);
root->kol--;
}
else
{
if( (root->left == NULL) ||
(root->right == NULL) )
{
Node *temp = root->left ?
root->left :
root->right;
if (temp == NULL)
{
temp = root;
root = NULL;
}
else
{
int t = root->kol;
*root = *temp;
root->kol = t - 1;
}
free(temp);
}
else
{
Node* temp = minValueNode(root->right);
root->key = temp->key;
//root->kol = temp->kol;
root->right = deleteNode(root->right,
temp->key);
}
}
if (root == NULL)
return root;
return root;
}

Finding the deepest level left leaf node in a binary search tree

Given a Binary Tree, find the deepest leaf node that is left child of its parent. For example, consider the following tree. The deepest left leaf node is the node with value 9.
1
/ \
2 3
/ / \
4 5 6
\ \
7 8
/ \
9 10
The answer is 9.
I developed the following code for this:
int maxlevel = 0;
Node *newNode(int data)
{
Node *temp = new Node;
temp->val = data;
temp->left = temp->right = NULL;
return temp;
}
Node * root;
Node * maxi = NULL;
int getlevel (Node * treeroot,int level, Node * foo)
{
if (treeroot == NULL)
return -1;
else if (treeroot->val == foo->val)
return level+1;
else
{
int downlevel = getlevel(treeroot->left,level+1,foo);
if (downlevel != -1)
return downlevel;
else
downlevel = getlevel(treeroot->right,level+1,foo);
return downlevel;
}
}
void foo(Node * temp)
{
// Base case
if (temp == NULL)
return;
Node * prev;
if (temp->left != NULL)
{
prev = temp;
foo(temp->left);
}
if (prev->left != NULL)
{
if (temp->left == NULL && temp->right == NULL && prev->left == temp)
{
int ind = getlevel(root,0,temp);
if (ind > maxlevel)
{
maxlevel = ind;
maxi = temp;
}
}
}
foo(temp->right);
return;
}
Here, foo is the actual function which determines the deepest left leaf in a tree. getlevel is a function which gets the level of a node in a tree. newNode is a function which allocates a new node.
When I try giving this input tree, it says the leaf is not present. Is there something wrong with my logic?
Thanks!
I think you could simplify this a little by passing the current level and a flag indicating whether the current node is a left or right child into each call...
Something like this:
int maxLevel = 0;
Node* maxNode = null;
void findDeepestLeftNode(Node* node, int level, bool isLeftChild) {
bool isLeaf = true;
if (node->left != null) {
isLeaf = false;
findDeepestLeftNode(node->left, level + 1, true);
}
if (node->right != null) {
isLeaf = false;
findDeepestLeftNode(node->right, level + 1, false);
}
if (isLeaf && isLeftChild && level > maxLevel) {
maxLevel = level;
maxNode = node;
}
}
Then just call it with:
findDeepestLeftNode(root, 0, false);
Assumes the root is not null.

Linked list cstring insertion sort

This is my code for an insertion-sort, sorting via the cstring member of the node. The current code only inserts before the head. The code encapsulated in comments is the sorted insertion I am trying to make work. I'm thinking I have to use a predecessor and successor pointer, but maybe it's the comparison that is confusing me. Any help would be appreciated. Thanks!
#include <iostream>
#include "groclist.h"
void insert_item(Grocery_Item_Ptr &head, int quantity, const char name[])
{
bool exists = false;
bool done = false;
Grocery_Item_Ptr temp = NULL;
Grocery_Item_Ptr current = NULL;
Grocery_Item_Ptr pred = NULL;
Grocery_Item_Ptr succ = NULL;
if (head == NULL) {
head = new Grocery_Item;
head->quantity = quantity;
strncpy(head->name, name, MAX_ITEM_NAME_LEN);
head->next = NULL;
return;
}
else {
current = head;
while (current != NULL) {
if (strncmp(current->name, name, MAX_ITEM_NAME_LEN) == 0) {
current->quantity += quantity;
exists = true;
}
current = current->next;
}
if (exists) {
current = NULL;
return;
}
else {
current = head;
}
if (!exists) {
temp = new Grocery_Item;
temp->quantity = quantity;
strncpy(temp->name, name, MAX_ITEM_NAME_LEN);
/*
while (!done || current != NULL) {
if (strncmp(current->name, name, MAX_ITEM_NAME_LEN) < 0) {
pred = current;
succ = current->next;
current->next = temp;
temp->next = succ;
done = true;
}
if (!done) {
current = current->next;
}
}
*/
temp->next = head;
head = temp;
temp = NULL;
}
}
return;
}
One thing you are missing is keeping a reference to the predecessor while searching. This is necessary in order to keep the chain intact.
Here is a draft that should work (currently untested!):
while (!done || current != NULL)
{
//If we found the place to insert
if (strncmp(current->name, name, MAX_ITEM_NAME_LEN) < 0)
{
//If the place to insert was at head
if(pred == NULL)
{
//The new node becomes the head
head = temp;
}
else
{
//Set the previous nodes next to point at this node.
pred->next = temp;
}
//Always set the node to be inserted's next
//pointing to the node we should be inserted before
temp->next = current;
done = true;
}
if (!done)
{
//No match, keep looking but keep an updated pred pointer
pred = current;
current = current->next;
}
}
It's just pseudocode, but maybe it helps:
if(head == NULl)
{
//make newnode as head
}
if(head.name == new name)
{
//update quantity
}
if(head.name <new name)
{
//insert newnode before head
//make newnode as head
}
if (new name > head.name)
{
current = head;
succ = current.next;
while (succ && new name <succ.name)
{
curent = succ;
succ = succ.next
}
if(succ = NULL)
current->next = newnode
else
if new name = succ->name
update quantity
else
curent->next = newnode
newnode->next = succ;
}
I appreciate your input guys, if only for having me think about it in different ways. However my result is quite different, and I must truly thank my whiteboard.
if (strncmp(name, head->name, MAX_ITEM_NAME_LEN) < 0) {
temp->next = head;
head = temp;
temp = NULL;
}
else {
pred = head;
current = head->next;
do {
if (strncmp(name, current->name, MAX_ITEM_NAME_LEN) < 0) {
pred->next = temp;
temp->next = current;
done = true;
}
else if (current->next == NULL) {
current->next = temp;
done = true;
}
else {
pred = current;
current = current->next;
}
if (done) {
pred = NULL;
current = NULL;
}
} while (!done && current != NULL);
}