I am having trouble getting my preView300 function working correctly. I know the algerithm is working correctly because I have seen other examples the exact same way. I believe its with my findMaxNode/removeNodefunctions. I have tried passing different pointer into my findMaxNode function but nothing that is correct.
For example:
I insert these numbers in this order, 8,4,12,2,6,10,14,20 and call me remove function to remove 8. I get this output 6,4,2,12,10,14,20. I know the findMaxNode is trying to do is get rid of the 8 and replace it with 20 and delete the node containing twenty and connect everything back up right.
If I can get some help on this on why this process isn't working please let me know. Also let me know if I have to add anything to this post inorder to help you.
Struct definition:
typedef float Element300;
struct TreeNode300;
typedef TreeNode300 * TreePtr300;
struct TreeNode300
{
Element300 element;
TreePtr300 left;
TreePtr300 right;
};
Remove Function:
void BST300::remove300(const Element300 element, TreePtr300 & root)
{
if(root == NULL)
{
cerr << "Error: Remove Failed!" << endl;
}
else if(element == root->element )
{
removeNode300(root);
}
else if(element < root->element)
{
remove300(element, root->left);
}
else
{
remove300(element, root->right);
}
return;
}
Remove Node function:
void BST300::removeNode300(TreePtr300 & root)
{
TreePtr300 tempPointer = NULL;
if(root->left == NULL && root->right == NULL)
{
delete root;
root = NULL;
}
else if(root->right == NULL)
{
tempPointer = root;
root = root->left;
tempPointer->left = NULL;
delete tempPointer;
}
else if(root->left == NULL)
{
tempPointer = root;
root = root->right;
tempPointer->right = NULL;
delete tempPointer;
}
else
{
findMaxNode300(root->right, tempPointer);
root->element = tempPointer->element;
delete tempPointer;
}
tempPointer = NULL;
return;
}
find Maximum value function:
void BST300::findMaxNode300(TreePtr300 & root, TreePtr300 & tempPointer)
{
if(root->right == NULL)
{
tempPointer = root;
root = root->left;
tempPointer->left = NULL;
}
else
{
findMaxNode300(root->right, tempPointer);
}
return;
}
inView:
void BST300::inView300(const TreePtr300 root)const
{
if(root)
{
inView300(root->left);
cout << root->element << "-> ";
inView300(root->right);
}
return;
}
preView:
void BST300::preView300(const TreePtr300 root) const
{
if(root)
{
cout << root->element << "-> ";
preView300(root->left);
preView300(root->right);
}
return;
}
Results:
PREVIEW
------------------------------------------------------
Begin -> 20-> 4-> 2-> 6-> 12-> 10-> 14-> End
INVIEW
------------------------------------------------------
Begin -> 2-> 4-> 6-> 20-> 10-> 12-> 14-> End
Expected Results:
PREVIEW
------------------------------------------------------
Begin -> 20-> 4-> 2-> 6-> 12-> 10-> 14-> End
INVIEW
------------------------------------------------------
Begin -> 2.0-> 4.0-> 6-> 10-> 12-> 14-> 20 -> End
Binary Search Tree Original:
8
4 12
2 6 10 14
- 20
Expected:
20
4 12
2 6 10 14
The logic in your removeNode300 function is incorrect. When you remove a node with two children, you replace the element to be deleted with the greatest element in that branch, and delete the old-greatest node. Take this conceptual example of a tree:
5
3 7
2 4 6 8
Removing 5 from the tree then makes it look like:
8
3 7
2 4 6 -
Seven is not greater than eight, so things fall apart here.
You can either replace the node you want to delete with the greatest on the left side, or the lowest on the right. You can easily fix this right away by changing the call to findMaxNode300 in removeNode300. Pass it root->left instead:
void BST300::removeNode300(TreePtr300 & root)
{
if(root->left == NULL && root->right == NULL) {}
else
{
findMaxNode300(root->left, tempPointer); //this line
}
}
Obviously keep the rest of the code in, I just removed it to make this less verbose.
Related
void removeIelement(Dlist& d, int i) {
if (d.head == NULL) {
cout << "EMPTY" << endl;
return;
}
else {
int count = 1;
Node* cur = d.head;
while (cur != NULL) {
if (count == i) {
Node* temp = cur->next;
Node* temp2 = temp->next;
cur->next = temp->next;
temp2->prev = cur;
}
count++;
cur = cur->next;
}
}
}
Here is my code to delete Node ith in doubly linked list
My doubly linked list is :
1 2 3 4 5 6 7 8 9 10
But when I run this program if I enter i = 1 it will delete
1 3 4 5 6 7 8 9 10
Same with i = 2 .... it will delete after element i (i+1)
1 2 4 5 6 7 8 9 10
Can you help me to fix this function? Thank you
You are not deleting anything. You are linking around temp, but since it's never actually deleted, you just leak the memory instead. You match against cur, meaning you want to delete cur, but then you assign temp to cur->next. You are linking around cur + 1, which is why you always unlink (not delete) the (i + 1)st node. You don't need any temps, either; the list is doubly linked. Take advantage of that. Erasing is incredibly easy in doubly-linked lists. After the delete command, your function should immediately return as well. Its job is done.
This code does not account for deleting the tail node, since I don't know if you track that or not. If you do, you need to account for that scenario as well.
void removeIelement(Dlist& d, int i) {
if (d.head == NULL) {
cout << "EMPTY" << endl;
return;
}
else {
int count = 1;
Node* cur = d.head;
while (cur != NULL) {
if (count == i) {
cur->next->prev = cur->prev; // Added
cur->prev->next = cur->next; // Changed
if (cur == head) { // Added
head = cur->next; // Added
} // Added
delete cur; // Added
return; // Added
}
count++;
cur = cur->next;
}
}
}
This could have been resolved by just drawing it on a piece of paper. Doing that beforehand would have eliminated this issue altogether. Planning is one of the most important aspects of programming.
A double linked list should have 2 attributes named begin and end, pointing to two "empty" places, head->next should point to the 1st element, and end->pre should point to the last element, your code assumes head as the first element, when it tries to remove the first element, it removes the element right after head, which is the element after the first element. A.K.A the second element.
the correct code may look like this:
void removeElement(Dlist& d, int id){
if(d.head->next==d.tail){
// the list is empty
cout << "empty list" <<endl;
}
else{
int count = 1; Node* cur = d.head->next;
while(cur->next != NULL)
if(count == id){
cur->prev->next=cur->next, cur->next->prev=cur->prev;
delete cur;
return; //removal successful
}
else
count++, cur = cur->next;
cout << "does not exist." << endl;
}
}
note that I didn't test the code. There might be some issues, but you got the idea.
I'm trying to manage a BST in C++ for my academic purpose.
I'm not having problems anywhere except for the DeleteNode function, also
I chose to implement this data structure with a class and not with a struct.
The problem is, that I cant figure it out how to make properly work the delete function, often I got 0xDDDDDDDDD error my debugger say, sometimes I can delete the node, sometimes my program crash.
I think that's a possible problem of pointer, but I just can't figure it out where I'm doing wrong.
Here's my delete node function, the one I'm getting serious trouble about:
EDIT: The no-son delete case works perfectly, the one i'm getting mad about is the one-son-case delete.
//function that delete a selected node
void DeleteNode(TreeNode* root,int key) {
/*we got three case here:*/
//until we find the right node with value in the tree
if (root->getValue() != key && root != nullptr) {
if (root->getValue() > key) {
DeleteNode(root->Left, key);
}
else if (root->getValue() < key) {
DeleteNode(root->Right, key);
}
}
else { //when we found the right node, then operate
/* THIS WORKS PERFECTLY! */
//first case: our node got no right and left son
if (!root->Left && !root->Right) {
TreeNode* tmp = root->Father;
if (tmp->Left == root) { //if the son is a left son
tmp->Left = nullptr;
delete root;
}
else if (tmp->Right == root) { //if the son is a right son
tmp->Right = nullptr;
delete root;
}
}
//second case: our node got a left but no right son
/* THIS ONE DOESN'T WORK. */
else if (!root->Right) {
TreeNode *tmp = root;
root = root->Left; //new root is the left son of the root
root->Father = tmp->Father; //linking the father to the new son
tmp->Father->Left = root; //linking the son to the new father
delete tmp;
std::cout << "Erased!" << std::endl;
}
else if (!root->Left) {
TreeNode *tmp = root;
root = root->Right; //new root is the right son of the root
root->Father = tmp->Father; //linking the father to the new son
tmp->Father->Right = root; //linking the son to the new father
delete tmp;
std::cout << "Erased!" << std::endl;
}
}
}
I tried a lot of combination, but the result are the same every time: it crashes on the first occurrence of the InOrder display function. (and when it does not, the function just delete the first nodes and then crash when i try to delete a new one.)
Here's a simple main where i'm trying to act the delete:
int main()
{
TreeNode root;
root.insertNode(&root,50);
root.insertNode(&root,30);
root.insertNode(&root,20);
root.insertNode(&root,40);
root.insertNode(&root,70);
root.insertNode(&root,60);
root.insertNode(&root,80);
for (int i = 0; i < 5; i++) {
int n;
cin >> n;
root.DeleteNode(&root, n);
cout << "In-Order: "; root.inOrder(&root);
cout << endl;
cout << "Pre-Order: "; root.preOrder(&root);
cout << endl;
cout << "Post-Order: "; root.postOrder(&root);
cout << endl;
}
}
Here's my full BST code (except the delete one that i submitted before, just for being more complete in the understanding of my code)
class TreeNode {
private:
int value;
TreeNode* Left;
TreeNode* Right;
TreeNode* Father;
public:
//constructor
TreeNode() {
this->Right = nullptr;
this->Left = nullptr;
this->Father = nullptr;
}
TreeNode(int value) {
this->value = value;
this->Right = nullptr;
this->Left = nullptr;
this->Father = nullptr;
}
//functions
int getValue() { return value; }
void setValue(int value) { this->value = value; }
//function to create a new node and insert a value into it
TreeNode* insertNode(TreeNode* root, int value) {
if (root->getValue() == NULL) {
root->setValue(value);
root->Father = nullptr;
}
else {
if (value > root->getValue()) {
if (root->Right) {
insertNode(root->Right, value);
}
else
root->Right = new TreeNode(value);
root->Right->Father = root;
}
else if (value < root->getValue()) {
if (root->Left) {
insertNode(root->Left, value);
}
else
root->Left = new TreeNode(value);
root->Left->Father = root;
}
}
return root;
}
//function to search a value into a BST
TreeNode* SearchNode(TreeNode* root, int key) {
if (root->getValue() == key) {
return root;
}
else if (root->getValue() < key) {
if (root->Right) {
SearchNode(root->Right, key);
}
else return nullptr;
}
else if (root->getValue() > key) {
if (root->Left) {
SearchNode(root->Left, key);
}
else return nullptr;
}
}
//function that return the height of the tree
int TreeHeigth(TreeNode* root) {
int heigth;
if (root == nullptr) {
return 0;
}
else {
return heigth = 1 + max(TreeHeigth(root->Left), TreeHeigth(root->Right));
}
}
//function that returns the number of the nodes
int CountTreeNode(TreeNode* root) {
if (root == nullptr) {
return 0;
}
else {
return CountTreeNode(root->Left) + CountTreeNode(root->Right) + 1;
}
}
//function that returns the minimum values into the tree
TreeNode* MinimumNode(TreeNode* root) {
if (root == nullptr) {
return nullptr;
}
while (root->Left != nullptr) {
root = root->Left;
}
return root;
}
//function that returns the maximum value into the tree
TreeNode* MaximumNode(TreeNode* root) {
if (root == nullptr) {
return nullptr;
}
while (root->Right != nullptr) {
root = root->Right;
}
return root;
}
//function that returns a successor of a given nodeb
TreeNode* SuccessorNode(TreeNode* node) {
//first case: our node got a rigth subtree:
if (node->Right != nullptr) {
return MinimumNode(node->Right);
}
//second case: our node doesnt got a right subtree: lets get
//upper in the tree until our node isn't a left child.
TreeNode* Ancestor = node->Father;
while (Ancestor != nullptr && node == Ancestor->Right) {
node = Ancestor;
Ancestor = Ancestor->Father;
}
}
//function tht returns a predecessor of a given node
TreeNode* PredecessorNode(TreeNode* node) {
//first case: (inverse to successor) our node got a left subtree:
if (node->Left != nullptr) {
return MaximumNode(node->Left);
}
TreeNode* Ancestor;
if (node->Father == nullptr)
return nullptr;
else
Ancestor = node->Father;
while (Ancestor != nullptr && node == Ancestor->Left) {
node = Ancestor;
Ancestor = Ancestor->Father;
}
return Ancestor;
}
//function that prints information about nodes
void InfoNode(TreeNode *root) {
root != nullptr ? std::cout << "Nodo corrente: " << root->getValue() << std::endl
: std::cout << "Nodo corrente: " << "NULL" << std::endl;
root->Father != nullptr? std::cout << "Padre: " << root->Father->getValue() << std::endl
: std::cout << "Padre: " << "NULL" << std::endl;
root->Left != nullptr ? std::cout << "Figlio SX: " << root->Left->getValue() << std::endl
: std::cout << "Figlio SX: " << "NULL" << std::endl;
root->Right!= nullptr ? std::cout << "Figlio DX: " << (root->Right)->getValue() << std::endl
: std::cout << "Figlio DX: " << "NULL" << std::endl;
}
//visits of a tree
void preOrder(TreeNode* root) {
if (root != nullptr) {
std::cout << root->getValue() << " ";
preOrder(root->Left);
preOrder(root->Right);
}
}
void inOrder(TreeNode* root) {
if (root != nullptr) {
inOrder(root->Left);
std::cout << root->getValue() << " ";
inOrder(root->Right);
}
}
void postOrder(TreeNode *root) {
if (root != nullptr) {
postOrder(root->Left);
postOrder(root->Right);
std::cout << root->getValue() << " ";
}
}
//max between 2 numbers
int max(int a, int b) {
return a > b ? a : b;
}
};
And there's the representation of the tree I'm trying to work on:
50
/ \
30 70
/ \ / \
20 40 60 80
Where i'm doing it wrong?
Look at this condition: root->getValue() != key && root != nullptr, This first calls getValue and after that checks root has legal value. swap them(root != nullptr && root->getValue() != key).
Finally I think you must change last line to tmp->Father->Left = root; to fix crash problem.
TreeNode *tmp = root;
root = root->Right; //new root is the right son of the root
root->Father = tmp->Father; //linking the father to the new son
tmp->Father->Right = root; //linking the son to the new father
PS: Also do this exchange for other side...
Note: This is true until root is left child of his father otherwise your code is true. Precisely you must check if root is left child if his father do tmp->Father->Left = root; else tmp->Father->Right = root;
Note: As you mentioned your code does not handle deletion of a node with two childern.
As there is already an answer giving you directions to correct the specific errors, I will try to focus on a suggestion that will help you avoid similar error all together:
Try separating your current function into two:
One that searches a node with specific key, for example: Node* search(int key) function that returns either a pointer to the node with wanted key or nullptr, or use the one that your already have.
One that deletes (and re-wires) the node passed as pointer and returns: next, previous, etc: Node* delete(Node* n).
Then call search, test against nulltpr, and if different, pass the returned pointer as an input argument in delete.
In this way you could easily detect on which phase is you problem: searching or deleting.
P.S.: figuring out re-wiring bugs is usually done through diagrams (boxes and arrows). Decide what you should do, separate it into steps and implement it.
Well, once one know that DEBUG version use sentinel value, it become much more trivial to find problems in code.
When and why will an OS initialise memory to 0xCD, 0xDD, etc. on malloc/free/new/delete?
0xDD is for dead memory. That is memory that has been already deleted. So when the debugger stop and it tells you that you have a bad pointer and the data contains a lot of 0xDD, you know the data has already been deleted. At that point, you should inspect class that contain the data to see if they are deleted too so you know which objects were deleted when the are embedded one inside another.
Be aware that sometime you might have some data that has been changed in part of the class if some operations use delete memory. Looking at memory pattern also help finding uninitialized memory and other similar problem.
Some other links:
Why does the not allocated memory is marked like 0xCC?
https://msdn.microsoft.com/en-us/library/974tc9t1.aspx
https://www.codeguru.com/cpp/w-p/win32/tutorials/article.php/c9535/Inside-CRT-Debug-Heap-Management.htm
http://www.nobugs.org/developer/win32/debug_crt_heap.html
In a case like yours, if you follow the good practice of writing unit tests, then it would even be more trivial to find the problem. In fact, if you do proper testing, then you will test all possible cases so you will know which cases fail and it would help you find where you might do something wrong.
I would like to add something to the answer of #Bonje Fir.
Sure it is a correct answer, but partially: I'll explain why.
He suggested to swap the last piece of code i wrote:
Case: we're in the right subtree, and we would like to erase 70 (because we don't have anymore the leaf node 60):
50
/ \
30 70
/ \ \
20 40 80
now, with the code that #Bonje Fir suggested us, we would got a problem here:
TreeNode *tmp = root;
root = root->Right; //new root is the right son of the root
root->Father = tmp->Father; //linking the father to the new son
tmp->Father->Left (instead of Right) = root; //linking the son to the new father
Because the code is saying, that once you updated the new root with his son, link the father of the previous root (that we saved in a tmp variable) with his left son. Then we would assist to something like this:
50
/ x
80 80
/ \
20 40
and that's inconsistent.
Now take a look on the other side, with the same code and without leaf node 20:
50
/ \
30 70
\ / \
40 60 80
the code fit here, because we're in the right subtree.
so once update 30 with 40 (root = root -> right) the situation would be this:
50
x \
40 70
/ \
60 80
then the piece of code #Bonje Fir wrote us, would fit perfectly:
tmp->Father->Left = root
because for sure, we're assigning 40 to the left son of the father of the original root. (because we're in the left subtree.)
50
/ \
40 70
/ \
60 80
So i made a little change to correct this logic problem, and make it work both in the right and left subtree.
else if (!root->Left) {
TreeNode *tmp = root;
root = tmp->Right;
root->Father = tmp->Father; //linking the father to the new son
//we need also to connect the son with the father, but first
//we need to know in which subtree we're in.
if (root->Father->Right == tmp) //if we're in the right subtree
tmp->Father->Right = root;
else ////if we're in the left subtree
tmp->Father->Left = root;
delete tmp;
std::cout << "Erased!" << std::endl;
}
i took advantage of the fact i didnt erase my root, once assigned the new one, so the father of the root still points to the old root.
(same speech for the opposite case.)
I am not sure if this is doing what it is supposed to do.
My goal is to generate a balanced binary tree, from a set of values.
Please let me know if this is correct.
NOTE: NOT a balanced binary search tree, just balanced binary tree.
int heightPrivate(nodePtr node)
{
if (node == NULL)
return -1;
return 1 + std::max(heightPrivate(node->left), heightPrivate(node->right));
}
void addNodePrivate(nodePtr node, int val)
{
if (root == NULL)
{
root = new BTNode;
root->data = val;
root->left = root->right = NULL;
}
else
{
if (node->left == NULL)
{
node->left = new BTNode;
node->left->data = val;
node->left->left = node->left->right = NULL;
}
else if (node->right == NULL)
{
node->right = new BTNode;
node->right->data = val;
node->right->left = node->right->right = NULL;
}
else
{
int lheight = heightPrivate(node->left);
int rheight = heightPrivate(node->right);
if (lheight < rheight)
addNodePrivate(node->left, val);
else if (rheight < lheight)
addNodePrivate(node->right, val);
else
addNodePrivate(node->left, val);
}
}
}
void printPostorderPrivate(nodePtr p, int indent=0)
{
if(p != NULL) {
if(p->left) printPostorderPrivate(p->left, indent+4);
if(p->right) printPostorderPrivate(p->right, indent+4);
if (indent) {
std::cout << std::setw(indent) << ' ';
}
std::cout<< p->data << " \n ";
}
}
In main...
int main()
{
BTree tree;
tree.addNode(1);
tree.addNode(2);
tree.addNode(3);
tree.addNode(4);
tree.addNode(5);
tree.addNode(6);
tree.addNode(7);
tree.printPostorder();
The result I get is this:
7
4
6
2
5
3
1
The children of 2 are 4 and 5. The question is why is it 7 going on the next level.
The reason that 7 appears where it does is because in the addNodePrivate method checks the heights of the two child branches, and if they are equal it goes left.
So as you insert 7, when the program is at the root (node 1) it sees that the height of the left branch and height of the right branch are both equal to 1 (node 2 had children 5 and 4 but no grandchildren, and node 3 has child 6 and also no grandchildren), and so it goes left - down the branch with node 2.
To achieve what you want, you need to choose the branch which has the shortest path, so comparing the height of two branches is not enough.
Hope that helps, best of luck.
Here is a c++ function to create a BST tree from an array of integers?
It's simple.
Take first element ,make root.
Take next array element and insert it into the tree.
Why is the loop starting from i=2 and not i=1??
node* buildtree(int a[], int len)
{
node* root=new node(a[0]);
node* temp=root;
for(int i=1;i<len;i++)
{
while(!(root->left==NULL && root->right==NULL))
{
cout<<"here"<<i<<" "<<a[i]<<" " << root->val<<"\n";
if(root->val>a[i])
root=root->left;
else
root=root->right;
}
node* currnode=new node(a[i]);
if(root->val>a[i])
root->left=currnode;
else
root->right=currnode;
if(root==NULL)
cout<<"error...never.here";
root=temp;
}
return root;
}
Thanks a lot for explaining it.I tried it another way but it only finds the root.What's the problem in it?
node* buildtree(int a[],int len)
{ node* root=new node(a[0]);
node* curr;
for(int i=1;i<len;i++)
{ curr=root;
while(curr!=NULL)
{
if(curr->val>a[i])
curr=curr->left;
else
curr=curr->right;
}
curr=new node(a[i]);
}
return root;
}
Because in the first iteration of the loop the while condition is not true because the root node has no child nodes.
while(!(root->left==NULL && root->right==NULL)
for i=1 the left and the right node are NULL and the left node is populated at the end of the first iteration.
When trying to find the point of insertion,
while(!(root->left==NULL && root->right==NULL))
{
cout<<"here"<<i<<" "<<a[i]<<" " << root->val<<"\n";
if(root->val>a[i])
root=root->left;
else
root=root->right;
}
you only stop if both children are NULL, so at some point or other, you will set root to NULL. Consider the array begins with [5, 3, 6, ... ]. You start with
NULL <- node(5) -> NULL
node(3) <- node(5) ->NULL
and then try to insert the 3. Since not both children are NULL, the while loop runs
if (5 > 7) // false
root = root->left;
else
root = root->right; // now root == NULL, oops
and the controlling condition is checked anew
while(!(NULL->left == NULL && NULL->right == NULL))
segfault likely here, undefined behaviour invoked.
You should do something like
while(true) {
if (root->val > a[i]) {
if (root->left == NULL) {
root->left = new node(a[i]);
break;
} else {
root = root->left;
}
} else {
if (root->right == NULL) {
root->right = new node(a[i]);
break;
} else {
root = root->right;
}
}
}
I have a BinarySearchTree that consists of nodes which are both a template class of dataType student, where student is a class with private variables of name and grade.
At the moment I can print the tree, find names and or grades in the tree but I am having trouble deleting nodes from the tree.
I am trying to delete all students who had a grade < 50 (so failed).
Once a node is deleted one of the following needs to occur:
Left child is empty: Replace the node by its right child.
Left child is not empty: Replace the node by the highest element in the left
branch.
My understanding of this is, if this was the tree:
1
/ \
2 3
/ \ /\
4 5 6 7
If 2 failed i.e. had a grade < 50
You would end up with
1
/ \
4 3
\ / \
5 6 7
4 being the highest element in the left branch.
If this was the tree:
1
/ \
2 3
\ / \
5 6 7
and 2 failed
you would end up with
1
/ \
5 3
/ \
6 7
If this was the tree:
1
/ \
2 3
/ \ / \
4 5 6 7
and 1 failed
you would end up with
5
/ \
2 3
/ / \
4 6 7
I have been having a lot of trouble trying to create functions to do this, at the moment I have:
void checkBranch() //called from main - used to pass the root node to checkBranch()
{
checkBranch(studentTree.getRoot());
}
bool checkBranch(BTNode<Student>* currentNode)
{
if (currentNode != NULL)
{
if (checkBranch(currentNode -> getLeft()))
{
deleteNode(currentNode, true);
}
if (checkBranch(currentNode -> getRight()))
{
deleteNode(currentNode, false);
}
return (currentNode -> getData().getGrade() < 50.0);
}
else
{
return false;
}
}
Now I am trying to add the deleteNode function where I am just stuck on what to do / handle what needs to occur:
void deleteNode(BTNode<Student> *parentNode, bool left)
{
BTNode<Student>* nodeToDelete;
if (left)
{
nodeToDelete = parentNode->getLeft();
}
}
I managed to achieve it with this:
template <typename dataType>
void BTree<dataType>::deleteNode(BTNode<dataType> *parentNode, bool left)
{
BTNode<dataType> *nodeToDelete;
BTNode<dataType> *currentNode;
if (left)
{
nodeToDelete = parentNode->getLeft();
}
else
{
nodeToDelete = parentNode->getRight();
}
if (nodeToDelete->getLeft() == NULL)
{
currentNode = nodeToDelete;
if (left)
{
parentNode->setLeft(nodeToDelete->getRight());
}
else
{
parentNode->setRight(nodeToDelete->getRight());
}
delete nodeToDelete;
}
else
{
BTNode<dataType>* greatestNode = nodeToDelete->getLeft();
if (greatestNode->getRight() == NULL)
{
nodeToDelete->getLeft()->setRight(nodeToDelete->getRight());
if (left)
{
parentNode->setLeft(nodeToDelete->getLeft());
}
else
{
parentNode->setRight(nodeToDelete->getLeft());
}
}
else
{
while (greatestNode->getRight()->getRight())
{
greatestNode = greatestNode->getRight();
}
nodeToDelete->setData(greatestNode->getRight()->getData());
BTNode<dataType> *nodeToDelete2 = greatestNode->getRight();
greatestNode->setRight(greatestNode->getRight()->getLeft());
delete nodeToDelete2;
}
}
}
First, your checkBranch is kind of wrong. What happens if the root node is invalid? It will not be deleted. I suggest a more elegant way here using a callback approach that could like this:
int deleteNodesOnCondition(BTNode<Student>* node, bool(* condition)(BTNode<Student>*))
{
int deleteCount = -1;
if(condition != NULL)
{
deleteCount = 0;
if(node != NULL)
{
deleteCount += deleteNodesOnCondition(node->getLeft(), condition);
deleteCount += deleteNodesOnCondition(node->getRight(), condition);
bool satisfied = condition(node);
if(satified)
{
deleteNode(node);
deleteCount += 1;
}
}
}
return deleteCount;
}
bool checkValidGrade(BTNode<Student> *node)
{
return node != NULL && node->getData().getGrade() >= 50.0;
}
void checkBranch()
{
deleteNodesOnCondition(studentTree.getRoot(), checkValidGrade);
}
For the delete implementation check here where found == true. Note: this code is not tested.