/******************************************************************************* * 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.btree; import algvis.core.Algorithm; import algvis.core.Node; import algvis.core.NodeColor; public class BDelete extends Algorithm { private final BTree T; private final int K; public BDelete(BTree T, int x) { super(T.panel); this.T = T; K = x; } @Override public void runAlgorithm() { BNode v = new BNode(T, K); v.setColor(NodeColor.DELETE); addToScene(v); setHeader("delete", K); if (T.getRoot() == null) { v.goToRoot(); addStep("empty"); pause(); v.goDown(); v.setColor(NodeColor.NOTFOUND); addStep("notfound"); } else { BNode d = T.getRoot(); v.goAbove(d); addStep("bstdeletestart"); pause(); while (true) { if (d.isIn(K)) { break; } final int p = d.search(K); if (p == 0) { addStep("bfind0", K, d.keys[0]); } else if (p == d.numKeys) { addStep("bfindn", d.keys[d.numKeys - 1], K, d.numKeys + 1); } else { addStep("bfind", d.keys[p - 1], K, d.keys[p], p + 1); } d = d.c[p]; if (d == null) { break; } v.goAbove(d); pause(); } if (d == null) { // notfound addStep("notfound"); v.goDown(); removeFromScene(v); return; } d.setColor(NodeColor.FOUND); pause(); d.setColor(NodeColor.NORMAL); removeFromScene(v); if (d.isLeaf()) { addStep("bdelete1"); if (d.isRoot() && d.numKeys == 1) { v = d; T.setRoot(null); addToScene(v); v.goDown(); } else { v = d.del(K); addToScene(v); T.reposition(); v.goDown(); pause(); } removeFromScene(v); } else { addStep("bdelete2"); BNode s = d.way(K + 1); v = new BNode(T, -Node.INF, d.tox, d.toy); v.setColor(NodeColor.FIND); addToScene(v); v.goAbove(s); pause(); while (!s.isLeaf()) { s = s.c[0]; v.goAbove(s); pause(); } removeFromScene(v); v = s.delMin(); addToScene(v); v.goTo(d); pause(); d.replace(K, v.keys[0]); removeFromScene(v); pause(); d.setColor(NodeColor.NORMAL); d = s; } while (!d.isRoot() && d.numKeys < (T.order - 1) / 2) { d.setColor(NodeColor.NOTFOUND); BNode s, s1 = null, s2 = null; final BNode p = d.parent; boolean lefts = true; int k = d.order(), n1 = 0, n2 = 0; if (k > 0) { s1 = p.c[k - 1]; n1 = s1.numKeys; } if (k + 1 < p.numChildren) { s2 = p.c[k + 1]; n2 = s2.numKeys; } if (n1 >= n2) { s = s1; --k; } else { s = s2; lefts = false; } if (s.numKeys > (T.order - 1) / 2) { // treba zobrat prvok z s, nahradit nim p.keys[k] // a p.keys[k] pridat do d // tiez treba prehodit pointer z s ku d if (lefts) { addStep("bleft"); } else { addStep("bright"); } v = lefts ? s.delMax() : s.delMin(); addToScene(v); v.goTo(p); pause(); final int pkey = p.keys[k]; p.keys[k] = v.keys[0]; removeFromScene(v); v = new BNode(T, pkey, p.tox, p.toy); addToScene(v); v.goTo(d); pause(); if (lefts) { d.insMin(pkey); if (!d.isLeaf()) { d.insMinCh(s.delMaxCh()); d.c[0].parent = d; } } else { d.insMax(pkey); if (!d.isLeaf()) { d.insMaxCh(s.delMinCh()); d.c[d.numChildren - 1].parent = d; } } d.setColor(NodeColor.NORMAL); break; } else { // treba spojit vrchol d + p.keys[k] + s // zmenit p.c[k] na novy vrchol a posunut to addStep("bmerge"); if (p.isRoot() && p.numKeys == 1) { v = new BNode(T.getRoot()); addToScene(v); T.getRoot().keys[0] = Node.NOKEY; v.goTo((d.tox + s.tox) / 2, d.y); pause(); if (lefts) { T.setRoot(new BNode(s, v, d)); } else { T.setRoot(new BNode(d, v, s)); } break; } else { v = p.del(p.keys[k]); addToScene(v); v.goTo((d.tox + s.tox) / 2, d.y); pause(); if (lefts) { p.c[k] = new BNode(s, v, d); } else { p.c[k] = new BNode(d, v, s); } p.c[k].parent = p; --p.numChildren; System.arraycopy(p.c, k + 1 + 1, p.c, k + 1, p.numChildren - (k + 1)); d = p; } } } T.reposition(); } removeFromScene(v); addNote("done"); } }