This problem is a little more complicated than previous ones I've brought here, so I'll try to be very explicit about what I've narrowed it down to.
I'm writing a Binary Search Tree data class in C++ that functions like a standard BST except that it stores duplicates of Odd numbers using a "count" field in the BST node.
I've written a test driver to test the member functions of the class and have run into an error that I cannot seem to solve. When I attempt to add a set number of random integers to a BST object none of them seem to make it into the tree. To check the contents I use a printInOrder function that I have confirmed works properly so I know the problem isn't there.
For starters, I'll post the addLeaf, printInOrder, and createLeaf functions, and the small block of code where I call them in my driver file.
bool fixedDupBST::addLeaf(int key)
{
if(root == nullptr){
root = createLeaf(key);
assert(root != nullptr);
}
else {
node *prev = nullptr;
node *scanPtr = root;
bool right, dupe = false;
while(scanPtr != nullptr) {
prev = scanPtr;
if(key < scanPtr->key) {
scanPtr = scanPtr->left;
right = false;
}
else if (key == scanPtr->key) {
if (scanPtr->keyCount >= 1)
dupe = true;
else{
dupe = false;
scanPtr = nullptr;
}
}
else {
scanPtr = scanPtr->right;
right = true;
}
}
if (dupe)
prev->keyCount++;
else if (!dupe)
return false;
else if (right) {
prev->right = createLeaf(key);
assert(prev->right != nullptr);
}
else {
prev->left = createLeaf(key);
assert(prev->left != nullptr);
}
}
return true;
}
fixedDupBST::node* fixedDupBST::createLeaf(int key)
{
node* newNode = new node;
assert(newNode != nullptr);
newNode->key = key;
newNode->left = nullptr;
newNode->right = nullptr;
if (key % 2 != 0)
newNode->keyCount = 1;
else
newNode->keyCount = 0;
return newNode;
}
void fixedDupBST::printInOrder()
{
printInOrderPr(root);
}
void fixedDupBST::printInOrderPr(node* Ptr)
{
if(root != nullptr) {
if(Ptr->left != nullptr){
printInOrderPr(Ptr->left);
}
cout << Ptr->key << ' ';
if(Ptr->right != nullptr) {
printInOrderPr(Ptr->right);
}
}
else {
cout << "The tree is empty" << endl;
}
return;
}
void testInsert(fixedDupBST &BST)
{
int temp;
for (int i = 0; i < TEST_PARAM; i++) {
temp = randNum();
BST.addLeaf(temp);
}
BST.printInOrder();
return;
}
The problem I'm getting is that when I call printInOrder() it always gives "The tree is empty". At first I thought it might be a problem with how I was passing parameters in the class member functions (pass by references vs pass by value) but that didn't provide any solutions. If there are any problems at all with the rest of the function it doesn't seem to matter because root never gets assigned to that first node, (hence why print in order just says "the tree is empty".
I need a second set of eyes on this; thanks in advanced for you help, and let me know if I can rephrase my question or provide more information to help make the situation clearer.
EDIT: R Sahu had the error correct, but his answer is a little off. I realized that a bool wouldn't work cleanly for what I was trying to do because there are actually 3 cases:
The number is a duplicate and is odd,
the number is a duplicate and is even
and the number is NOT a duplicate.
The problem stemmed from the fact that the quit condition for the while loop was scanPtr being null, and the if/else-if statement at the end had no way of knowing if it was null because it reached the end of a subtree and was ready to insert, or if I had manually set it to null upon finding a duplicate in order to break the loop appropriately.
Here is the solution I came up with.
bool fixedDupBST::addLeaf(int key)
{
if(root == nullptr){
root = createLeaf(key);
assert(root != nullptr);
}
else {
node *prev = nullptr;
node *scanPtr = root;
bool right;
int dupe = 0; // switch variable
while(scanPtr != nullptr) {
prev = scanPtr;
if(key < scanPtr->key) {
scanPtr = scanPtr->left;
right = false;
}
else if (key == scanPtr->key) {
if (key % 2 != 0) {
dupe = 1;
scanPtr = nullptr;
}
else{
dupe = 2;
scanPtr = nullptr;
}
}
else {
scanPtr = scanPtr->right;
right = true;
}
}
if (dupe == 2)
return false;
if (dupe == 1)
prev->keyCount++;
else if (right) {
prev->right = createLeaf(key);
assert(prev->right != nullptr);
}
else {
prev->left = createLeaf(key);
assert(prev->left != nullptr);
}
}
return true;
}
Everything works appropriately now.
You have a logic error in this block.
if (dupe)
prev->keyCount++;
else if (!dupe) // This is pointless
// dupe is either true or false.
// Your code will never get to the next "else if"
return false;
else if (right) {
prev->right = createLeaf(key);
assert(prev->right != nullptr);
}
else {
prev->left = createLeaf(key);
assert(prev->left != nullptr);
}
What you need is:
if (dupe) {
prev->keyCount++;
return false; // I think you want to return false here but I am not sure
}
else if (right) {
prev->right = createLeaf(key);
assert(prev->right != nullptr);
}
else {
prev->left = createLeaf(key);
assert(prev->left != nullptr);
}
R Sahu had the error correct, but his answer is a little off. I realized that a bool wouldn't work cleanly for what I was trying to do because there are actually 3 cases:
1: The number is a duplicate and is odd.
2: the number is a duplicate and is even.
3: the number is NOT a duplicate.
The problem stemmed from the fact that the quit condition for the while loop was scanPtr being null, and the if/else-if statement at the end had no way of knowing if it was null because it reached the end of a subtree and was ready to insert, or if I had manually set it to null upon finding a duplicate in order to break the loop appropriately.
Here is the solution I came up with.
bool fixedDupBST::addLeaf(int key)
{
if(root == nullptr){
root = createLeaf(key);
assert(root != nullptr);
}
else {
node *prev = nullptr;
node *scanPtr = root;
bool right;
int dupe = 0; // switch variable
while(scanPtr != nullptr) {
prev = scanPtr;
if(key < scanPtr->key) {
scanPtr = scanPtr->left;
right = false;
}
else if (key == scanPtr->key) {
if (key % 2 != 0) {
dupe = 1;
scanPtr = nullptr;
}
else{
dupe = 2;
scanPtr = nullptr;
}
}
else {
scanPtr = scanPtr->right;
right = true;
}
}
if (dupe == 2)
return false;
if (dupe == 1)
prev->keyCount++;
else if (right) {
prev->right = createLeaf(key);
assert(prev->right != nullptr);
}
else {
prev->left = createLeaf(key);
assert(prev->left != nullptr);
}
}
return true;
}
Everything works appropriately now.
Related
I'm having trouble manipulating a doubly linked list. I'm pretty sure I have my addNode(), getCount(), printList(), and getNode() working fine, but when executing, I get to right around my exists() and deleteNode() methods and I get a segmentation fault. exists() checks to see if a specific node exists, and deleteNode() passes in an id, and if the id matches a node id, it deletes that node. I don't know which method is messing up. Here are both of them. This is also my first post so if it's confusing and not thorough I apologize in advance.
bool LinkedList::deleteNode(int id){
bool didDelete = false;
bool hasResult = false;
Node *position;
position = head;
while(position!=NULL && !hasResult){
if(id == position->data.id){
hasResult = true;
} else {
std::cout << "position->next" << std::endl;
position = position->next;
}
}
// Deletes head node
if (position->prev == NULL) {
head = head->next;
head->prev = NULL;
delete (position);
didDelete = true;
}
// Deletes middle node
else if (position->next != NULL) {
position->prev->next = position->next;
position->next->prev = position->prev;
position->next = NULL;
position->prev = NULL;
delete(position);
didDelete = true;
}
// Deletes the tail node
// else if(position->next == NULL){
else{
position->prev->next = NULL;
position->prev = NULL;
delete(position);
didDelete = true;
}
return didDelete;
} // End of deleteNode
bool LinkedList::exists(int id){
Node *position;
position = head;
bool gotNode = false;
while (position != NULL && !gotNode) {
if(id == position->data.id){
gotNode = true;
} else{
position = position->next;
}
}
return gotNode;
} // End of exists
Your exists() is fine, though it can be simplified a little:
bool LinkedList::exists(int id){
for(Node *position = head; position; position = position->next) {
if (id == position->data.id) {
return true;
}
}
return false;
}
Your deleteNode() is broken, though. If the specified id is not found by the while loop, position will end up NULL, and the subsequent access to position->prev will invoke undefined behavior.
It is also needlessly verbose, it can be greatly simplified:
bool LinkedList::deleteNode(int id){
for(Node *position = head; position; position = position->next){
if (id == position->data.id){
if (position->next) position->next->prev = position->prev;
if (position->prev) position->prev->next = position->next;
if (position == head) head = head->next;
/* uncomment this if you ever add such a field...
if (position == tail) tail = tail->prev;
*/
delete position;
return true;
}
}
return false;
}
I'm trying to implement a Red Black Tree using VS 2019 as my IDE. It seems to work in VS but when I try to compile and run using anything else, it results in a seg fault whenever my insert function is called more than once. (I've tried online compilers and sending it to a friend) I'm stuck as I don't know where to start trying to fix my error. I've heard that VS handles dynamic memory differently but I'm not too sure.
Below is my rotate, BST insert and insert functions.
#include <iostream>
#include <vector>
// default constructor
// creates empty tree, root is nullptr
class NodeT
{
public:
// public variables
double key;
double value;
NodeT* left;
NodeT* right;
NodeT* parent;
bool isBlack;
// constructors
NodeT()
{
key = 0;
value = 0;
left = nullptr;
right = nullptr;
parent = nullptr;
isBlack = false;
}
NodeT(double keyset, double valueset, bool isBlackset)
{
key = keyset;
value = valueset;
left = nullptr;
right = nullptr;
parent = nullptr;
isBlack = isBlackset;
}
};
class RedBlackTree
{
public:
// default constructor, sets all to null
RedBlackTree();
// insert
// inserts the first parameter key, and value second parameter into the tree
// returns true if done, false if there are duplicates, dont insert
bool insert(double insert_key, double insert_value);
public:
NodeT* root;
void leftrotate(NodeT* to_rotate);
void rightrotate(NodeT* to_rotate);
bool bstinsert(NodeT* insert);
};
RedBlackTree::RedBlackTree()
{
root = nullptr;
}
void RedBlackTree::leftrotate(NodeT* to_rotate)
{
NodeT* new_parent = nullptr;
new_parent = to_rotate->right;
to_rotate->right = new_parent->left;
if (new_parent->left != nullptr)
{
new_parent->left->parent = to_rotate;
}
new_parent->parent = to_rotate->parent;
if (to_rotate->parent == nullptr)
{
root = new_parent;
}
else if (to_rotate == to_rotate->parent->left)
{
to_rotate->parent->left = new_parent;
}
else
{
to_rotate->parent->right = new_parent;
}
new_parent->left = to_rotate;
to_rotate->parent = new_parent;
}
void RedBlackTree::rightrotate(NodeT* to_rotate)
{
NodeT* new_parent = to_rotate->left;
to_rotate->left = new_parent->right;
if (new_parent->right != nullptr)
{
new_parent->right->parent = to_rotate;
}
new_parent->parent = to_rotate->parent;
if (to_rotate->parent == nullptr)
{
root = new_parent;
}
else if (to_rotate == to_rotate->parent->right)
{
to_rotate->parent->right = new_parent;
}
else
{
to_rotate->parent->left = new_parent;
}
new_parent->right = to_rotate;
to_rotate->parent = new_parent;
}
bool RedBlackTree::bstinsert(NodeT* insert)
{
NodeT* parent = root;
NodeT* search = root;
if (root == nullptr)
{
root = insert;
}
else
{
while (search != nullptr)
{
parent = search;
if (insert->key < parent->key)
{
search = parent->left;
}
else if (insert->key > parent->key)
{
search = parent->right;
}
else
{
return false;
}
}
if (insert->key < parent->key)
{
parent->left = insert;
insert->parent = parent;
return true;
}
else if(insert->key > parent->key)
{
parent->right = insert;
insert->parent = parent;
return true;
}
else
{
return false;
}
}
}
bool RedBlackTree::insert(double insert_key, double insert_value)
{
NodeT* y = nullptr;
NodeT* x = new NodeT(insert_key, insert_value, false);
bool dupe = bstinsert(x);
if (dupe == false)
{
return false;
}
while (x != root && x->parent->isBlack == false)
{
if (x->parent == x->parent->parent->left)
{
y = x->parent->parent->right;
if (y == nullptr || y->isBlack == true)
{
if (x == x->parent->right)
{
x = x->parent;
leftrotate(x);
}
x->parent->isBlack = true;
x->parent->parent->isBlack = false;
rightrotate(x->parent->parent);
}
else if (y->isBlack == false)
{
x->parent->isBlack = true;
y->isBlack = true;
x->parent->parent->isBlack = false;
x = x->parent->parent;
}
}
else
{
y = x->parent->parent->left;
if (y == nullptr || y->isBlack == true)
{
if (x == x->parent->left)
{
x = x->parent;
rightrotate(x);
}
x->parent->isBlack = true;
x->parent->parent->isBlack = false;
leftrotate(x->parent->parent);
}
else if (y->isBlack == false)
{
x->parent->isBlack = true;
y->isBlack = true;
x->parent->parent->isBlack = false;
x = x->parent->parent;
}
}
}
root->isBlack = true;
return true;
}
Calling this in main results in an seg fault except when in VS:
int main()
{
RedBlackTree test;
test.insert(47, 1);
test.insert(32, 2);
}
Thanks for taking the time to read this. Any help is appreciated.
There is at least one error that causes undefined behavior:
The RedBlackTree::bstinsert function fails to return a value when it is supposed to return a bool.
To verify this is the error, a line right before the end of the bstinsert function can be placed to verify that this is an error.
bool RedBlackTree::bstinsert(NodeT* insert)
{
NodeT* parent = root;
NodeT* search = root;
if (root == nullptr)
{
root = insert;
}
else
{
while (search != nullptr)
{
parent = search;
if (insert->key < parent->key)
{
search = parent->left;
}
else if (insert->key > parent->key)
{
search = parent->right;
}
else
{
return false;
}
}
if (insert->key < parent->key)
{
parent->left = insert;
insert->parent = parent;
return true;
}
else if (insert->key > parent->key)
{
parent->right = insert;
insert->parent = parent;
return true;
}
else
{
return false;
}
}
std::cout << "This is undefined behavior\n"; // <-- add this line
}
You will see that the std::cout line will be encountered to confirm that you are returning from bstinsert without returning a value.
Also, the compiler you're using (Visual Studio), would have given a warning to you about this issue. Something similar to this:
warning C4715: 'RedBlackTree::bstinsert': not all control paths return a value
You should not have ignored this warning.
While working on a problem, I have tried the following solution. Somehow my output is stuck into infinite loop and not printing result or updated heap tree.
Given a tree where the left and right subtrees are min heaps, but the root node does not maintain the min heap property. Your code should modify the tree rooted at Node* n so it is a min heap. (This means you need to satisfy the min heap property:
it is okay for a node's value to be equal to one or both of its children, but the node's value must not be greater than either of its children. You do not have to try to balance the tree or make it a complete tree.)
#include <iostream>
#include <string>
You have the following class Node already defined.
You cannot change this class definition, so it is
shown here in a comment for your reference only:
class Node {
public:
int value;
Node *left, *right;
Node(int val = 0) { value = val; left = right = nullptr; }
~Node() {
delete left;
left = nullptr;
delete right;
right = nullptr;
}
};
This function has also previously been defined for you:
void printTreeVertical(const Node* n);
You can use it to print a verbose, vertical diagram of
a tree rooted at n. In this vertical format, a left child
is shown above a right child in the same column. If no
child exists, [null] is displayed.
*/
void downHeap(Node *n) {
Node *curr = new Node();
Node *mino = new Node();
if (n == nullptr ){
return;
} else if (n->left->value > n->value & n->right->value > n->value){
return;
// } else if (n->left== nullptr & n->right== nullptr) {
// return;
// }
} else {
// node* curr = new Node(n)
// n = new Node((std::min(n->left->value, n->right->value));
// if (n->left->value)
while(n->left!= nullptr & n->right!= nullptr){
if (n->left == nullptr){
mino = n->right;
} else if (n->right == nullptr) {
mino = n->left;
} else {
mino = (std::min(n->left, n->right));
}
std::cout << n->value << std::endl;
std::cout << mino->value << std::endl;
if(n->value > mino-> value){
curr->value = n->value;
n->value = mino->value;
mino->value = curr->value;
std::cout << n->value << std::endl;
std::cout << mino->value << std::endl;
downHeap(mino);
}
}
return;
}
}
// Implement downHeap() here.
// You can also use this compact printing function for debugging.
void printTree(Node *n) {
if (!n) return;
std::cout << n->value << "(";
printTree(n->left);
std::cout << ")(";
printTree(n->right);
std::cout << ")";
}
int main() {
Node *n = new Node(100);
n->left = new Node(1);
n->left->left = new Node(3);
n->right = new Node(2);
n->right->left = new Node(3);
n->right->right = new Node(4);
n->right->right->right = new Node(5);
std::cout << std::endl << "BEFORE - Vertical printout:" << std::endl;
printTreeVertical(n);
downHeap(n);
std::cout << "Compact printout:" << std::endl;
printTree(n);
std::cout << std::endl << " AFTER Vertical printout:" << std::endl;
printTreeVertical(n);
delete n;
n = nullptr;
return 0;
}
Please suggest what I am missing. I feel I am making it too complicated. Also, I do not have any other function like swap for converting the binary tree into heap min. I am not using an array or vector as well. So, if you can provide me simple solution I will appreciate it.
Your primary problem is this line of code:
mino = (std::min(n->left, n->right));
Here, you're comparing two pointers when you really want to compare the values in the two objects you're referring to, and return a pointer to the object that has the smaller value. That is:
mino = (n->left->value < n->right->value) ? n->left : n->right;
Also in this line of code:
} else if (n->left->value > n->value & n->right->value > n->value){
You probably want && (logical AND) rather than & (bitwise AND). See https://www.geeksforgeeks.org/what-are-the-differences-between-bitwise-and-logical-and-operators-in-cc/.
Finally, your code formatting is a little off so it's difficult to tell, but it looks like the return statement is outside the while loop in your downHeap function. If it is outside the loop body, then that could lead to an infinite loop.
This is the easiest solution I came up with.
Try this code for complete solution.
void downHeap(Node *n) {
// check if it is a leaf node
if (n->left == NULL && n->right == NULL) {
return;
}
if ((n->left != NULL) && (n->right != NULL)) {
if ((n->value <= n->left->value) && (n->value <= n->right->value)) {
return;
}
}
// Node passed in is not a leaf
// If left is null, we can focus on the right first
// If the right node has a greater value
if (n->right != NULL) {
if ((n->left == NULL) && (n->right->value < n->value)) {
int rightnodevalue = n->right->value;
int nodevalue = n->value;
n->value = rightnodevalue;
n->right->value = nodevalue;
if (n->right != NULL) {
downHeap(n->right);
return;
}
}
}
// Node passed in is not a leaf
// Left is not null
// First check if right is null
// If right is null, we can focus on the left first
// If the left node has a greater value
if (n->left != NULL) {
if ((n->right == NULL) && (n->left->value < n->value)) {
int leftnodevalue = n->left->value;
int nodevalue = n->value;
n->value = leftnodevalue;
n->left->value = nodevalue;
if (n->left != NULL) {
downHeap(n->left);
return;
}
}
}
// Node passed in is not a leaf
// Left is not null
// Right is not null
// If left is less than right
if ((n->left != NULL) && (n->right != NULL)) {
if (n->left->value < n->right->value) {
int leftnodevalue = n->left->value;
int nodevalue = n->value;
n->value = leftnodevalue;
n->left->value = nodevalue;
if (n->left != NULL) {
downHeap(n->left);
return;
}
}
else {
// Proceed to swap the parent and the right node
// Reference pointers for child's pointers
int rightnodevalue = n->right->value;
int nodevalue = n->value;
n->value = rightnodevalue;
n->right->value = nodevalue;
if (n->right != NULL) {
downHeap(n->right);
return;
}
}
}
return;
}
If you define a helper function to swap node values, you can make your code a lot cleaner and implement recursion quite easily. For example:
// DEFINE HELPER FUNCTION
void compareSwap(Node *a, Node *b) {
int temp;
if (a->value > b->value) {
temp = b->value;
b->value = a->value;
a->value = temp;
}
return;
}
void downHeap(Node *n) {
Node *compNode;
// 1. n is a leaf
if (!n->left && !n->right) {
return;
}
// 2. n has one left child
else if (n->left && !n->right) {
if (n->value > n->left->value) {
compareSwap(n, n->left);
downHeap(n->left);
}
return;
}
// 3. n has one right child
else if (!n->left && n->right) {
if (n->value > n->right->value) {
compareSwap(n, n->right);
downHeap(n->right);
}
return;
}
// 4. n has two children ... (n->left && n->right)
else {
// HEAP IS SATISFIED, RETURN NOTHING
if ((n->value <= n->left->value) && (n->value <= n->right->value)) {
return;
}
// RIGHT IS LESS THAN n BUT LEFT IS NOT, SWAP RIGHT
else if (((n->value <= n->left->value) && (n->value > n->right->value))) {
compareSwap(n, n->right);
downHeap(n->right);
return;
}
// LEFT IS LESS THAN n BUT RIGHT IS NOT, SWAP LEFT
else if (((n->value > n->left->value) && (n->value <= n->right->value))) {
compareSwap(n, n->left);
downHeap(n->left);
return;
}
// BOTH ARE LESS THAN, SWAP MIN
else {
compNode = (n->left->value < n->right->value) ? n->left : n->right;
compareSwap(n, compNode);
downHeap(compNode);
return;
}
}
}
This genuinely has me stumped. I have a binary search tree of citys that is ordered by the city name. A city also contains the population and GPS coordinates. I want to be able to remove nodes from the tree by City name or city coordinates. I have the delete by name working fine but the GPS coordinates does not work.
When I remove a node by GPS I get a stack-overflow when I try to print the binary tree. Below is some of my code. I cannot understand how it will work fine if I delete by name but not if I delete by coordinates as I am using the same delete method.
The exact error I get is "Unhandled exception at 0x013214D6 in EXE: 0xC00000FD: Stack overflow (parameters: 0x00000001, 0x00152FFC)." This occurs in my print function after I delete by coordinates but not if I delete by name.
bool BinaryTree::DeleteByName(string city)
{
if (GetRoot() != NULL)
{
return (DeleteByName(GetRoot(), city));
}
return false;
}
TreeNode* BinaryTree::DeleteByName(TreeNode *node, string city)
{
if (node == NULL)
{
return node;
}
else if (city < node->Data.name)
{
node->Left = DeleteByName(node->Left, city);
}
else if (city > node->Data.name)
{
node->Right = DeleteByName(node->Right, city);
}
else
{
if (node->Left == NULL && node->Right == NULL)
{
delete node;
node = NULL;
}
else if (node->Left == NULL)
{
TreeNode* temp = node;
node = node->Right;
delete temp;
}
else if (node->Right == NULL)
{
TreeNode* temp = node;
node = node->Left;
delete temp;
}
else
{
cout << "Else";
TreeNode* temp = MinPtr(node->Right);
node->Data = temp->Data;
node->Right = DeleteByName(node->Right, temp->Data.name);
}
}
return node;
}
bool BinaryTree::DeleteByCoord(pair<double, double> coords)
{
if (GetRoot() == NULL)
{
return false;
}
else
{
return DeleteByCoord(GetRoot(), coords);
}
}
bool BinaryTree::DeleteByCoord(TreeNode* node, pair<double, double> coords)
{
bool result;
if (node == NULL)
{
return false;
}
else
{
if (node->Data.coordinates.first == coords.first && node->Data.coordinates.second == coords.second)
{
return (DeleteByName(node, node->Data.name));
}
result = DeleteByCoord(node->Left, coords);
if (result == true)
{
return result;
}
return DeleteByCoord(node->Right, coords);
}
}
void BinaryTree::Insert(City city)
{
TreeNode* temp = new TreeNode(city);
if (GetRoot() == NULL)
{
root = temp;
}
else
{
Insert(temp, GetRoot());
}
}
void BinaryTree::Insert(TreeNode* toAdd, TreeNode* addHere)
{
if (toAdd->Data < addHere->Data)
{
if (addHere->Left != NULL)
{
Insert(toAdd, addHere->Left);
}
else
{
addHere->Left = toAdd;
}
}
else if (toAdd->Data > addHere->Data)
{
if (addHere->Right != NULL)
{
Insert(toAdd, addHere->Right);
}
else
{
addHere->Right = toAdd;
}
}
}
void BinaryTree::InOrderTraversal(TreeNode* node)
{
if (node != NULL)
{
InOrderTraversal(node->Left);
cout << node->Data << endl;
InOrderTraversal(node->Right);
}
}
void BinaryTree::InOrderTraversal()
{
InOrderTraversal(GetRoot());
}
TreeNode* BinaryTree::GetRoot()
{
return root;
}
TreeNode* BinaryTree::MinPtr(TreeNode* node)
{
while (node->Left != NULL)
{
node = node->Left;
}
return node;
}
When you delete the node you also need to update parent pointer that points to deleted node. Pay attention here:
when you call DeleteByName directly it searches required node and returns NULL pointer which automatically set to parent node pointer:
else if (city < node->Data.name)
{
node->Left = DeleteByName(node->Left, city);
}
else if (city > node->Data.name)
{
node->Right = DeleteByName(node->Right, city);
}
but when you call DeleteByName from coordinates method you do not reset parent's Left/Right pointers:
if (node->Data.coordinates.first == coords.first && node->Data.coordinates.second == coords.second)
{
return (DeleteByName(node, node->Data.name));
}
in its turn as DeleteByName already receives required node, it does not perform recursive call and does not reset parent's pointers either:
else
{
if (node->Left == NULL && node->Right == NULL)
{
delete node;
node = NULL;
}
//... same here
}
NOTE: There are many more problems in your code. Some that strike the eye:
DeleteByName returns pointer, but DeleteByCoord returns bool, you use pointer as a boolean type in DeleteByCoord
Avoid to compare doubles directly, the comparison result can be wrong. See the question and explanation for the details.
Following is a piece of my code for deleting a node from a BST. It is a non-recursive code.
I have applied all the possible conditions.
However when I run my code, it stops as if stuck somewhere in an infinite loop or ending up at a point where my pointer is pointing to NULL.However I am unable to identify it.
Any help would be appreciated.
template <class T>
void bst<T>::delete_node(T key1)
bst_node<T>* delNode = search(key1); //delNode is the node I wish to delete
if(delNode!=root)
{
if((delNode->left == NULL) && (delNode->right == NULL)) // node to be deleted has no children
{
delNode = NULL;
}
else if((delNode->left!=NULL) && (delNode->right == NULL)) //node to be deleted has exactly one child
{
if(delNode->parent->left == delNode)
{
delNode->parent->left = delNode->left;
delNode = NULL;
}
else if(delNode->parent->right == delNode)
{
delNode->parent->right = delNode->left;
delNode = NULL;
}
}
else if((delNode->right!= NULL) && (delNode->left == NULL))
{
if(delNode->parent->left == delNode)
{
delNode->parent->left = delNode->right;
delNode = NULL;
}
else if(delNode->parent->right == delNode)
{
delNode->parent->right = delNode->right;
delNode = NULL;
}
}
else if((delNode->right!=NULL)&&(delNode->left != NULL)) //if has two children
{
bst_node<T>* temp = delNode;
bst_node<T>* trav = delNode->right;
if((trav->right == NULL)&&(trav->left == NULL))
{
delNode->value = trav->value;
delNode->key = trav->key;
trav = NULL;
}
else
{
bst_node<T>* pred = trav;
while(trav!=NULL)
{
pred = trav; //smallest node in right subtree
trav=trav->left;
}
delNode->value = pred->value;
delNode->key = pred->key;
pred = NULL;
}
}
}
else if(delNode==root)//node to be deleted is Root
{
if((delNode->left==NULL)&&(delNode->right==NULL))
root = NULL;
else if((delNode->left!=NULL) && (delNode->right == NULL)) //root has exactly one child
{
root = delNode->left;
delNode = NULL;
}
else if((delNode->right!= NULL) && (delNode->left == NULL))
{
root = delNode->right;
delNode = NULL;
}
else if((delNode->right!=NULL)&&(delNode->left!=NULL)) {
bst_node<T>* temp = delNode;
bst_node<T>* trav = delNode->right;
if((trav->right == NULL)&&(trav->left == NULL))
{
delNode->value = trav->value;
delNode->key = trav->key;
trav = NULL;
}
else
{
bst_node<T>* pred = trav;
while(trav!=NULL)
{
pred = trav; //smallest node in right subtree
trav=trav->left;
}
delNode->value = pred->value;
delNode->key = pred->key;
pred = NULL;
}
}
}
}
In the part:
else if((delNode->right!=NULL)&&(delNode->left != NULL)) //if has two children
when if is taken:
if((trav->right == NULL)&&(trav->left == NULL))
the code copies the values from trav to delNode and sets trav to NULL:
delNode->value = trav->value;
delNode->key = trav->key;
trav = NULL;
but doesn't set delNode->right to NULL, as it should because trav didn't have any children.
the very next else statement which seeks for the most left node commits a similar error, because parent node's member left isn't set to NULL.
The next big part of the code which deals with deletion of only root node, seems to have identical problems, due to apparent copy-pasted (cough!) code.