no-stack-dub-sack / cs-playground-react

In-Browser Algorithm and Data Structures Practice
http://cs-playground-react.surge.sh/
MIT License
520 stars 91 forks source link

BST algo remove has small glitch #80

Closed mansisce closed 4 years ago

mansisce commented 6 years ago

We are not handling the both left and right pointers when we delete the node. Update will be as mentioned below

// node only has right child else if (!node.left) { node.value = node.right.value node.right = node.right.right node.left = node.right.left; } // node only has left child else if (!node.right) { node.value = node.left.value node.left = node.left.left node.right = node.left.right }

no-stack-dub-sack commented 6 years ago

Hi @mansisce, disregard my last message if you saw it before I deleted it. I forgot I already had made changes to the BST solution a while back :-)

You are quite right, nice catch! Really, the better solution would just be node = node.right and node = node.left, respectively, but for some reason I can't figure out, this messes up trying to remove the root node of a tree with only two nodes, e.g.

image

if the solution is:

// node only has right child
else if (!node.left) {
  node = node.right;
}
// node only has left child
else if (!node.right) {
  node = node.left;
}

and then you run tree.remove(15), the tree is unchanged, when really the root node should be 27. Which, frankly, does not make sense to me!

Anyway, to keep this working, I think you need to make the assignments that you have in bold in your comment in the opposite order, e.g.:

// node only has right child
else if (!node.left) {
    node.value = node.right.value;
    node.left = node.right.left; // above the node.right assignment
    node.right = node.right.right;
}
// node only has left child
else if (!node.right) {
    node.value = node.left.value;
    node.right = node.left.right; // above the node.left assignment
    node.left = node.left.left;
}

Otherwise, an example like this wouldn't work if you tried to delete 17 image

because if the code was like this:

else if (!node.left) {
    node.value = node.right.value;
    node.right = node.right.right;
    // now, node.right is null after the above line executes

    node.left = node.right.left; // TypeError: Cannot read property 'left' of null 
}

the node.left = node.right.left assignment would fail. To protect against this, you need to assign the node on the side that we're not replacing first.

Do you want to go ahead and make this change? Thanks again for catching this pretty serious bug, if there was a lot of data in the other pointer, it would all get lost in a real world implementation!

mansisce commented 6 years ago

Let me raise the PR if that is not already done.

mansisce commented 6 years ago

Why do you have base64.js file. For divider you could have used css properties and classes. Why are you using VERTICAL_GRIP and HORIZONTAL_GRIP

no-stack-dub-sack commented 6 years ago

@mansisce I forget exactly why now.... but I think I borrowed those base64 images from a library called Split.JS and just liked the way they looked. I believe I played around with some styling for the grips using only CSS, but didn't really like the way they came out. Using the background image instead of other styling worked fine and looked good.

If you're able to improve on it, though, I'm all for it :smile:

mansisce commented 6 years ago

@no-stack-dub-sack Not able to push to a branch which I've created and hence not able to raise a PR for the same.

no-stack-dub-sack commented 6 years ago

@mansisce what's the issue with pushing the branch?