Hello I currently both the working and not working solutions below for the problem
Given the root of a BINARY TREE:
Collect all the leaf nodes.
Remove all the leaf nodes.
Repeat until the tree is empty.
HOWEVER it only works when I go set the current->left || current->right to null if they are leaves
In my second example if I try to set current = NULL when it's a leaf node it doesn't update. Please help I will respond to any questions this is based on LEETCODE336
//NEED HELP ON THIS ONE NOT WORKING
class Solution {
public:
vector<vector<int>> findLeaves(TreeNode* root) {
vector<vector<int>> result;
if(root == NULL) return result;
queue<TreeNode*> bfs;
vector<int> leaves;
while(root){
bfs.push(root);
while(!bfs.empty()){
TreeNode* current = bfs.front();
bfs.pop();
if(current->left != nullptr) bfs.push(current->left);
if(current->right != nullptr) bfs.push(current->right);
if(current->left == nullptr && current->right == nullptr){
leaves.push_back(current->val);
// NOT SETTING TO NULL WHEN IT'S A LEAF NODE
current = NULL;
}
}
result.push_back(leaves);
leaves.clear();
}
return result;
}
};
class Solution {
public:
bool isLeaf(TreeNode* current){
if(current->left == NULL && current->right == NULL) return true;
else
return false;
}
vector<vector<int>> findLeaves(TreeNode* root) {
vector<vector<int>> result;
if(root == NULL) return result;
queue<TreeNode*> bfs;
vector<int> leaves;
// bfs.push(root);
while(root != NULL){
if(isLeaf(root)){
leaves.push_back(root->val);
root = nullptr;
}
else {
bfs.push(root);
}
while(!bfs.empty()){
TreeNode* current = bfs.front();
bfs.pop();
if(current->left && isLeaf(current->left)){
leaves.push_back(current->left->val);
current->left = nullptr;
}
else if(current->left){
bfs.push(current->left);
}
if(current->right && isLeaf(current->right)){
leaves.push_back(current->right->val);
current->right = nullptr;
}
else if(current->right){
bfs.push(current->right);
}
}
result.push_back(leaves);
leaves.clear();
}
return result;
}
};
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.
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.
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/)
I coded case #2 in delete_node but am getting a segmentation error. I'm using the predecessor to delete the node. I'm not sure what happens when I am removing the root node with two children. Is it the same as deleting a non-root node with two children except you don't have to connect the predecessor's children? I think that's how I've coded it...
bool delete_node(Node*& root, KType key) {
// find target node to delete
Node* target = find(key, root);
if (!target) return false;
// find parent of target
Node* parent = find_parent(root, target);
// case 1: target is a leaf
if (target->left == NULL && target->right == NULL) {
// set parent's child pointer
if (parent != NULL) {
if ( parent->left == target )
parent->left = NULL;
else
parent->right = NULL;
}
else
root = NULL;
// free target
delete target;
return true;
}
// case 2: target has two children
else if (target->left != NULL && target->right != NULL) {
if (parent != NULL) {
//find predecessor
Node* temp = target->left;
while (temp != NULL) {
temp = temp->right;
}
// find predecessor's parent
Node* predecessorParent = find_parent(root, temp);
target->key = temp->key;
if (predecessorParent->left == temp) {
predecessorParent->left = temp->left;
} else {
predecessorParent->right = temp->left;
}
delete(temp);
return true; // return true when you're done.
} else {
//find predecessor
Node* temp = target->left;
while (temp != NULL) {
temp = temp->right;
}
target->key = temp->key;
delete(temp);
return true; // return true when you're done.
}
}
// case 3: target has only left child
else if (target->left != NULL) {
// set parent's child pointer
if (parent != NULL) {
if ( parent->left == target )
parent->left = target->left;
else
parent->right = target->left;
}
else
root = target->left;
// free target
delete target;
return true;
}
// case 4: target has only right child
else {
// set parent's child pointer
if (parent != NULL) {
if (parent->left == target)
parent->left = target->right;
else
parent->right = target->right;
}
else
root = target->right;
// free target
delete target;
return true;
}
return false;
}
find_parent function:
/**
* Finds the parent of node in the tree rooted at rootNode
*/
Node* find_parent(Node* rootNode, Node* node) {
if ( rootNode == NULL || rootNode == node ) {
return NULL;
}
else if ( rootNode->left == node || rootNode->right == node ) {
return rootNode;
}
else if (node->key < rootNode->key) {
return find_parent(rootNode->left, node);
}
else {
return find_parent(rootNode->right, node);
}
}
Whenever I insert the tree data in, and try to delete them, it works for all except the last remaining node. Or even if I insert only one node and try to delete it, it doesn't, it continues displaying the node. I tried debugging the code, but seems clueless. Please help!
void Remove(node *Current, int key) {
node *prev = new node;
if(Current == NULL)
cout << "List is empty.\n";
else {
while(Current != NULL) {
if(Current->value == key)
break;
else {
prev = Current;
if(Current->value >key)
Current = Current->left;
else
Current = Current->right;
}
}
if(Current->left == NULL && Current->right == NULL) {
if(prev->left == Current)
prev->left = NULL;
else
prev->right = NULL;
delete(Current);
}
else if(Current->left != NULL && Current->right == NULL) {
if(prev->left == Current)
prev->left = Current->left;
else
prev->right = Current->left;
delete(Current);
}
else if(Current->left == NULL && Current->right != NULL) {
if(prev->left == Current)
prev->left = Current->right;
else
prev->right = Current->right;
delete(Current);
}
else if(Current->left != NULL && Current->right != NULL) {
node *temp = Current->right;
if(temp->left == NULL && temp->right == NULL) {
Current->value = temp->value;
delete(temp);
Current->right = NULL;
}
//////////////////////////////////////
else if(Current->right->left != NULL)
{
node *left_current = Current->right;
node *left_current_prev = Current->right->left;
while(left_current->left != NULL)
{
left_current_prev = left_current;
left_current = left_current->left;
}
Current->value = left_current->value;
delete(left_current);
left_current_prev->left = NULL;
}
//////////////////////////////////////
else
{
node *temp;
temp = Current->right;
Current->value = temp->value;
Current->right = temp->right;
delete(temp);
}
//////////////////////////////////////
}
}
}
if I insert only one node and try to delete it, it doesn't, it
continues displaying the node
Every tree has a base, a pointer to the first node of the tree.
tree base --> Current node --> left node ...
--> right node ,,,
This base pointer appears to be available to the caller of function Remove,
... code leading to
Remove (tree base->Current, key)
... subsequent code
but you did not give Remove access to the tree base to modify it.
In other words, Remove() (probably) deletes Current, but tree base still points to where Current was when Remove() returns.
You probably need to review what happens when the key does not match the value in the last node.