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;
}
Related
I have written a code for insertion in Binary Search Tree and its traversal.
class node
{
public:
int data;
node *left;
node *right;
};
node* createNode(int value)
{
node *temp = new node;
temp->data = value;
temp->left = NULL;
temp->right = NULL;
return temp;
}
node *start = NULL;
void insertNode(int val)
{
if (start == NULL)
{
start = createNode(val);
return;
}
node *temp = start;
while ((temp->left != NULL) && (temp->right != NULL))
{
if (val < temp->data)
{
temp = temp->left;
}
else if (val > temp->data)
{
temp = temp->right;
}
else
{
cout << "Already exists in tree\n";
return;
}
}
if (val < temp->data)
{
temp->left = createNode(val);
return;
}
else
{
temp->right = createNode(val);
return;
}
}
void inorder(node *root)
{
if (root != NULL)
{
inorder(root->left);
printf("%d \n", root->data);
inorder(root->right);
}
}
It does not work fine on some test cases.
For example, if insert 15, 25 and then 35, and then traverse the tree, it only prints 15 and 25.
I am not able to find out the problem in the code. What is the issue with my insertion logic?
Let's go through the behavior -
you insert the 15. if (start == NULL)
this check creates the start node. Now there is a start node with value 15 and left and right as NULL.
you insert 25. (temp->left != NULL) && (temp->right != NULL)
this turns out to be false.
(val < temp->data) this check creates a right node.
you insert 35. (temp->left != NULL) && (temp->right != NULL)
still turns out to be false.
(val < temp->data) this check creates a right node (replacing the current right node). Which is not right.
You need to correct the while loop condition here.
I have a recRemove function that recursively removes the given node. I also have a findMin function that finds the smallest node in the BST. I'm having trouble merging the two so that I can remove the smallest(or largest) node. This is what I tried doing but it just returned garbage: Full code: https://pastebin.com/HCVsUZ4S
//remove min node in BST
node * extractMin()
{
return recRemove(root, findMin(root));
}
//delete node from tree
node * recRemove(node * root, double data)
{
//3 cases: no children, one child, 2 children
if (root == NULL)
{
return NULL;
}
else if (data < root->data)
{
root->left = recRemove(root->left, data);
}
else if(data > root->data)
{
root->right = recRemove(root->right, data);
}
else
{
if (root->right == NULL && root->left == NULL) //no children
{
delete root;
root = NULL;
return root;
}
else if(root->left == NULL) //only right child
{
temp = root;
root = root->right;
delete temp;
return root;
}
else if(root->right == NULL) //only left child
{
temp = root;
root = root->left;
delete temp;
return root;
}
else //2 children
{
temp->data = findMin(root->right);
root->data = temp->data;
root->right = recRemove(root->right, temp->data);
}
}
return root;
}
//find min node in BST
double findMin(node * p)
{
if(p == NULL)
{
return -1;
}
else
{
//in a balanced BST the minimum node is the leftmost node so,
//we traverse the left subtree until we get to the leftmost node and return and remove it.
temp = p;
while(temp->left != NULL)
{
temp = temp->left;
}
return temp->data;
}
}
sorry , can't write comments yet (will delete this later)
Where is temp defined? If it is a global variable than this is probably the issue...
Edit:
Have now seen the pasebin.....
temp is a member variable. Change it to a local variable.
Make sure to delete it before leaving the function. (best use std::unique_ptr<>)
This class's purpose is to emulate the functions of a Binary Search Tree. In the below code, I am trying to adapt it from a struct and a bunch of functions, into a wrapper class, called BST. One thing I am not sure of however, is how to access 'root' from within the node struct. Root is currently declared within the BST class.
class bst
{
public:
struct Node
{
public:
int data;
struct Node *left;
struct Node *right;
Node* FindMin(Node* root)
{
while(root->left != NULL) root = root->left;
return root;
}
Node* Insert(Node *root,int data)
{
if(root == NULL) {
root = new Node();
root->data = data;
root->left = root->right = NULL;
//Update Height & Size
bstHeight = 0;
bstSize = 0;
}
else if(data <= root->data)
root->left = Insert(root->left,data);
else
root->right = Insert(root->right,data);
return root;
}
Node* Delete(struct Node *root, int data)
{
if(root == NULL) return root;
else if(data < root->data) root->left = Delete(root->left,data);
else if (data > root->data) root->right = Delete(root->right,data);
//Value found
else {
// Case 1: No child
if(root->left == NULL && root->right == NULL)
{
delete root;
root = NULL;
//Update Height & Size
bstHeight = 0;
bstSize = 0;
}
//Case 2: One child
else if(root->left == NULL)
{
struct Node *temp = root;
root = root->right;
delete temp;
//Update Height & Size
bstHeight = 0;
bstSize = 0;
}
else if(root->right == NULL)
{
struct Node *temp = root;
root = root->left;
delete temp;
//Update Height & Size
bstHeight = 0;
bstSize = 0;
}
// case 3: 2 children
else
{
struct Node *temp = FindMin(root->right);
root->data = temp->data;
root->right = Delete(root->right,temp->data);
//Update Height & Size
bstHeight = 0;
bstSize = 0;
}
}
return root;
}
//# of Nodes in tree
void size(Node *root)
{
//Check if end
if(root == NULL) return;
//Not end
else
{
bstSize = bstSize + 1;
size(root->left); //Visit left subtree
size(root->right); // Visit right subtree
}
}
void height(Node *root, int temp)
{
//Check if end
if(root == NULL)
{
if(temp > bstHeight)
{
bstHeight = temp;
}
return;
}
//Not end
else
{
temp = temp + 1;
height(root->left, temp); //Visit left subtree
height(root->right, temp); // Visit right subtree
}
}
//Function to visit nodes in Inorder
void show()
{
if(root == NULL) return;
show(root->left); //Visit left subtree
printf("%d ",root->data); //Print data
show(root->right); // Visit right subtree
}
void check(Node *root)
{
//End of a 'branch'
if(root == NULL) return;
int value = 0;
value = root->data;
//Checking left subtree
if(value < root->left->data)
{
//Tree is NOT valid
valid = 0;
}
//Checking right subtree
if(value > root->right->data)
{
//Tree is NOT valid
valid = 0;
}
check(root->left); //Visit left subtree
printf("%d ",root->data); //Print data
//check(root->right); // Visit right subtree
}
};
Node* root = NULL;
};
Specifically, in the show function. It's not as simple as putting it into Node with the rest of the functions, as root needs to be unique, and new Node is called at least once. Show will not compile in the current state, and I'm not sure where to proceed from here.
Though the comment says everything, let me give an additional hint:
When you want to keep your code as similar as possible to what you have now, try to add a constructor to the Node class that expects a pointer or reference (preferable) to the root and check, that each time you create a Node, you give the root to the constructor.
By the way, it might even be a better approach to look at some simple Node-based data structure implementations in C++, for example in the thread
Simple linked list in C++
I am implementing Binary search tree in C++. I have written the following code but for some reason I get an error message that says:
expected a ;
I get above message when compiling the code.
Also I am new to C++ and I would appreciate a lot if I get some help on this one.
Some context to Binary Search Tree:
Binary search trees keep their keys in sorted order, so that lookup
and other operations can use the principle of binary search: when
looking for a key in a tree (or a place to insert a new key), they
traverse the tree from root to leaf, making comparisons to keys stored
in the nodes of the tree and deciding, on the basis of the comparison,
to continue searching in the left or right subtrees. On average, this
means that each comparison allows the operations to skip about half of
the tree, so that each lookup, insertion or deletion takes time
proportional to the logarithm of the number of items stored in the
tree. This is much better than the linear time required to find items
by key in an (unsorted) array, but slower than the corresponding
operations on hash tables.
#include<iostream>
using namespace std;
struct Node
{
int data;
Node *left, *right, *parent;
};
Node* DeleteNode(Node *root, int data);
void find_min(Node *root);
void inorder(Node *x);
void Insert(Node *root, int data);
//delete a node
//search_tree
//insert a node
//temp->parent = NULL;
int main()
{
Node *root, *temp;
//node with 20
temp = new Node;
temp->data = 20;
temp->left = NULL;
temp->right = NULL;
root = temp;
//node with 10
temp = new Node;
temp->data = 10;
temp->left = NULL;
temp->right = NULL;
temp->parent = NULL;
root->left = temp;
temp->parent = root;
//node with 30
temp = new Node;
temp->data = 30;
temp->left = NULL;
temp->right = NULL;
temp->parent = NULL;
root->right = temp;
temp->parent = root;
//node with 25
temp = new Node;
temp->data = 25;
temp->left = NULL;
temp->right = NULL;
temp->parent = NULL;
root->right->left = temp;
temp->parent = root->right;
//node with 40
temp = new Node;
temp->data = 40;
temp->left = NULL;
temp->right = NULL;
temp->parent = NULL;
root->right->right = temp;
temp->parent = root->right;
//node with 2
temp = new Node;
temp->data = 2;
temp->left = NULL;
temp->right = NULL;
temp->parent = NULL;
root->left->left = temp;
temp->parent = root->left;
//node with 15
temp = new Node;
temp->data = 15;
temp->left = NULL;
temp->right = NULL;
temp->parent = NULL;
root->left->right = temp;
temp->parent = root->left;
find_min(root);
cout << "Printing numbers in order" << endl;
inorder(root);
cout << "printing in-order of the given root" << endl;
delete(root);
}
void find_min(Node *root)
{
Node *temp;
temp = root;
while (temp->left != NULL)
temp = temp->left;
cout << "min number is " << temp->data << endl;
}
void inorder(Node *x)
{
if (x != NULL)
{
inorder(x->left);
cout << x->data << endl;
inorder(x->right);
}
}
Node* DeleteNode(Node *root, int data)
{
if (root->data == NULL) {
return root;
}
// If the key to be deleted is smaller than the root's key,
// then it lies in left subtree
else if (data < root->data)
root->left = DeleteNode(root->left, data);
// If the key to be deleted is greater than the root's key,
// then it lies in right subtree
else if (data > root->data)
root->right = DeleteNode(root->right, data);
// case 1: No child
else if (root->left == NULL & root->right == NULL)
delete root;
return root;
//data < root->data struct Node *temp = root;
// case 2: one child
if (root->left == NULL){
Node *temp = root;
root = root->right;
delete temp;
return root;
}
//
else if (root->right == NULL) {
Node *temp = root;
root = root->left;
delete temp;
return root;
}
// case 3: two child
else (root == root->right){
root->data = temp->data;
root->right = DeleteNode(root->right, temp->data);
return root;
}
}
This is your issue: else (root == root->right){. If you want to make that a condition, you'll need to use else if(root == root->right)
Note that per Godbolt, you have more errors even with that fix (they look simple to fix).
I'm having trouble implementing a binary search tree deletion algorithm on C++. If I try deleting the root, or direct children of the root, it works correctly. But it does not work for deeper levels (just outputs the same tree without any deletion). What is wrong with my code?
typedef struct Node {
int key;
Node *left = NULL;
Node *right = NULL;
} Node;
...
/*
* Delete <key> from BST rooted at <node> and return modified <node>.
*/
Node* BST::pop(Node *node, int key) {
// If <node> is a null pointer, return.
// If <node> doesn't contain the key, traverse down the tree.
// If <node> contains the key, perform deletion.
if (node == NULL) {
} else if (key < node->key) {
node->left = pop(node->left, key);
} else if (key > root->key) {
node->right = pop(node->right, key);
} else {
// If <node> is a leaf, just delete it
if (node->left == NULL && node->right == NULL) {
delete node; // deallocate memory (note: node still points to a memory address!)
node = NULL; // node points to null
}
// If <node> has a single child, replace <node> with its child
else if (node->left == NULL && node->right != NULL) {
Node *tmp = node;
node = node->right;
delete tmp;
tmp = NULL;
} else if (node->right == NULL && node->left != NULL) {
Node *tmp = node;
node = node->left;
delete tmp;
tmp = NULL;
} else {
node->key = findMax(node->left);
node->left = pop(node->left, node->key);
}
}
return node;
}
int BST::findMax(Node *root) {
if (root->left == NULL && root->right == NULL) {
return root->key;
} else {
int max = root->key;
if (root->left != NULL) {
int leftMax = findMax(root->left);
if (leftMax > max) {
max = leftMax;
}
}
if (root->right != NULL) {
int rightMax = findMax(root->right);
if (rightMax > max) {
max = rightMax;
}
}
return max;
}
}
A couple of things:
Second else if should be else if (key > node->key)
Your findMax function is exceptionally complex. The max in a BST from some root is really just traversing right children until there are no more right children (because anything in the left subtree must be less than the key you are currently evaluating, so leftMax can never be > max). Therefore it could be
int BST::findMax(Node *root) {
int max = root->key;
while (root->right != NULL) {
root = root->right;
max = root->key;
}
return max;
}
As long as the tree does not need to remain balanced, your general algorithm of just removing in case of a leaf, swapping the lone child if there is only one, and in the case of two children finding an inorder neighbor, swapping and deleting that node should be sound (not sure if you found this link, but: http://quiz.geeksforgeeks.org/binary-search-tree-set-2-delete/)