/*******************************************************************************
* Copyright (c) 2012-present Jakub Kováč, Jozef Brandýs, Katarína Kotrlová,
* Pavol Lukča, Ladislav Pápay, Viktor Tomkovič, Tatiana Tóthová
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
******************************************************************************/
package algvis.ds.dictionaries.bst;
import java.util.HashMap;
import algvis.core.Algorithm;
import algvis.core.Node;
import algvis.core.NodeColor;
import algvis.core.visual.Edge;
import algvis.core.visual.ZDepth;
import algvis.ui.view.REL;
public class BSTDelete extends Algorithm {
private final BST T;
private final int K;
private final HashMap<String, Object> result = new HashMap<String, Object>(); // "deleted"
public BSTDelete(BST T, int x) {
this(T, x, null);
}
public BSTDelete(BST T, int x, Algorithm a) {
super(T.panel, a);
this.T = T;
K = x;
}
@Override
public void runAlgorithm() {
setHeader("delete", K);
addNote("bstdeletestart");
final BSTFind find = new BSTFind(T, K, this);
find.runAlgorithm();
final BSTNode toDelete = (BSTNode) find.getResult().get("node");
if (toDelete != null) {
BSTNode parent = toDelete.getParent();
result.put("deleted", true);
addToScene(toDelete);
toDelete.setColor(NodeColor.DELETE);
if (toDelete.isLeaf()) { // case I - leaf
addStep(toDelete, REL.TOP, "bst-delete-case1");
addStep(toDelete, REL.BOTTOM, "bst-delete-unlink");
if (toDelete.isRoot()) {
T.setRoot(null);
} else if (toDelete.isLeft()) {
toDelete.getParent().unlinkLeft();
} else {
toDelete.getParent().unlinkRight();
}
pause();
} else if (toDelete.getLeft() == null
|| toDelete.getRight() == null) {
// case II - 1 child
BSTNode son;
if (toDelete.getLeft() == null) {
son = toDelete.getRight();
addStep(toDelete, REL.LEFT, "bst-delete-case2");
} else {
son = toDelete.getLeft();
addStep(toDelete, REL.RIGHT, "bst-delete-case2");
}
if (toDelete.isRoot()) {
addStep(son, REL.BOTTOM, "bst-delete-newroot", K,
son.getKey());
} else {
if (son.isLeft() == toDelete.isLeft()) {
addToSceneUntilNext(new Edge(toDelete.getParent(),
toDelete, son));
} else {
addToSceneUntilNext(new Edge(toDelete.getParent(), son));
}
addStep(son, REL.BOTTOM, "bst-delete-linkpar", K,
son.getKey(), toDelete.getParent().getKey());
}
pause();
if (toDelete.getLeft() == null) {
toDelete.unlinkRight();
} else {
toDelete.unlinkLeft();
}
if (toDelete.isRoot()) {
T.setRoot(son);
} else {
if (toDelete.isLeft()) {
toDelete.getParent().linkLeft(son);
} else {
toDelete.getParent().linkRight(son);
}
}
} else { // case III - 2 children
addStep(toDelete, REL.TOP, "bst-delete-case3", K);
BSTNode son = toDelete.getRight();
toDelete.setColor(NodeColor.DELETE);
BSTNode v = new BSTNode(T, -Node.INF, ZDepth.ACTIONNODE);
v.setColor(NodeColor.FIND);
addToScene(v);
v.goAbove(son);
addStep(v, REL.RIGHT, "bst-delete-succ-start");
pause();
while (son.getLeft() != null) {
addStep(v, REL.RIGHT, "bst-delete-go-left");
v.pointAbove(son.getLeft());
pause();
v.noArrow();
son = son.getLeft();
v.goAbove(son);
}
v.goTo(son);
parent = son.getParent();
if (parent == toDelete) {
parent = son;
}
final BSTNode p = son.getParent(), r = son.getRight();
v.setColor(NodeColor.FOUND);
addStep(v, REL.RIGHT, "bst-delete-succ", K, son.getKey());
pause();
if (r == null) {
addStep(v, REL.BOTTOMLEFT, "bst-delete-succ-unlink");
} else {
addStep(r, REL.BOTTOM, "bst-delete-succ-link", r.getKey(),
p.getKey());
if (son.isLeft()) {
addToSceneUntilNext(new Edge(p, son, r));
} else {
addToSceneUntilNext(new Edge(p, r));
}
}
pause();
removeFromScene(v);
v = son;
addToScene(v);
if (son.isLeft()) {
p.linkLeft(r);
} else {
p.linkRight(r);
}
v.goNextTo(toDelete);
pause();
addStep(v, REL.RIGHT, "bst-delete-replace", K, son.getKey());
pause();
if (toDelete.getParent() == null) {
T.setRoot(v);
} else {
if (toDelete.isLeft()) {
toDelete.getParent().linkLeft(v);
} else {
toDelete.getParent().linkRight(v);
}
}
v.setColor(NodeColor.NORMAL);
v.linkLeft(toDelete.getLeft());
v.linkRight(toDelete.getRight());
v.goTo(toDelete);
removeFromScene(v);
} // end case III
toDelete.goDown();
removeFromScene(toDelete);
T.reposition();
addNote("done");
result.put("parent", parent);
} else {
result.put("deleted", false);
}
assert (T.getRoot() == null || (T.getRoot().testStructure() && T.getRoot().testStructure()));
}
@Override
public HashMap<String, Object> getResult() {
return result;
}
}