/******************************************************************************* * 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.redblacktree; import algvis.core.Algorithm; import algvis.core.Node; import algvis.core.NodeColor; import algvis.core.visual.ZDepth; import algvis.ds.dictionaries.bst.BSTFind; import algvis.ds.dictionaries.bst.BSTNode; public class RBDelete extends Algorithm { private final RB T; private final int K; public RBDelete(RB T, int x) { super(T.panel); 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 RBNode d = (RBNode) find.getResult().get("node"); if (d == null) { // notfound addNote("notfound"); addNote("done"); return; } else { setHeader("delete", K); addToScene(d); // d.setColor(NodeColor.DELETE); d.setColor(NodeColor.FOUND); // TODO aj tak je to jedno, lebo // metoda draw zmeni kazdy RBNode // na cerveny alebo cierny RBNode u = d, w = (u.getLeft() != null) ? u.getLeft() : u .getRight2(); T.NULL.setParent(u.getParent2()); if (d.isLeaf()) { // case I - list addStep("bst-delete-case1"); pause(); if (d.isRoot()) { T.setRoot(null); } else if (d.isLeft()) { d.getParent().setLeft(null); } else { d.getParent().setRight(null); } } else if (d.getLeft() == null || d.getRight() == null) { // case IIa - 1 syn addStep("bst-delete-case2"); pause(); final BSTNode s = (d.getLeft() == null) ? d.getRight() : d .getLeft(); if (d.isRoot()) { T.setRoot(s); s.setParent(null); } else { s.setParent(d.getParent()); if (d.isLeft()) { d.getParent().setLeft(s); } else { d.getParent().setRight(s); } } } else { // case III - 2 synovia addStep("bst-delete-case3"); RBNode s = d.getRight(); RBNode v = new RBNode(T, -Node.INF, ZDepth.ACTIONNODE); v.setColor(NodeColor.FIND); addToScene(v); v.goTo(s); pause(); while (s.getLeft() != null) { s = s.getLeft(); v.goTo(s); pause(); } u = s; w = u.getRight2(); T.NULL.setParent(u.getParent() == d ? v : u.getParent()); //removeFromScene(v); v.setKey(s.getKey()); v.setRed(d.isRed()); //addToScene(v); if (s.isLeft()) { s.getParent().linkLeft(u.getRight()); } else { s.getParent().linkRight(u.getRight()); } v.goNextTo(d); pause(); if (d.getParent() == null) { v.setParent(null); T.setRoot(v); } else { if (d.isLeft()) { d.getParent().linkLeft(v); } else { d.getParent().linkRight(v); } } removeFromScene(v); v.linkLeft(d.getLeft()); v.linkRight(d.getRight()); v.goTo(d); v.calc(); } // end case III d.goDown(); removeFromScene(d); T.NULL.setLeft(T.NULL); T.NULL.setRight(T.NULL); if (!u.isRed()) { // bubleme nahor while (w.getParent2() != T.NULL && !w.isRed()) { T.NULL.setRed(false); if (w.getParent2().getLeft2() == w) { final RBNode s = w.getParent2().getRight2(); if (s.isRed()) { addStep("rbdelete1"); pause(); s.setRed(false); w.getParent2().setRed(true); T.rotate(s); } else if (!s.getLeft2().isRed() && !s.getRight2().isRed()) { addStep("rbdelete2"); pause(); s.setRed(true); w = w.getParent2(); } else if (!s.getRight2().isRed()) { addStep("rbdelete3"); pause(); s.getLeft2().setRed(false); s.setRed(true); T.rotate(s.getLeft()); } else { addStep("rbdelete4"); pause(); s.setRed(s.getParent2().isRed()); w.getParent2().setRed(false); s.getRight2().setRed(false); T.rotate(s); w = (RBNode) T.getRoot(); } } else { final RBNode s = w.getParent2().getLeft2(); if (s.isRed()) { addStep("rbdelete1"); pause(); s.setRed(false); w.getParent2().setRed(true); T.rotate(s); } else if (!s.getRight2().isRed() && !s.getLeft2().isRed()) { addStep("rbdelete2"); pause(); s.setRed(true); w = w.getParent2(); } else if (!s.getLeft2().isRed()) { s.getRight2().setRed(false); addStep("rbdelete3"); pause(); s.setRed(true); T.rotate(s.getRight2()); } else { addStep("rbdelete4"); pause(); s.setRed(s.getParent2().isRed()); w.getParent2().setRed(false); s.getLeft2().setRed(false); T.rotate(s); w = (RBNode) T.getRoot(); } } pause(); } w.setRed(false); } T.reposition(); addNote("done"); } assert (T.getRoot() == null || (((RBNode) T.getRoot()).testStructure() && ((RBNode) T.getRoot()).testStructure() && ((RBNode) T.getRoot()).testRedBlack())); } }