/*******************************************************************************
* 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.priorityqueues.binomialheap;
import java.awt.Color;
import java.util.Hashtable;
import algvis.core.DataStructure;
import algvis.core.Node;
import algvis.core.NodeColor;
import algvis.core.history.HashtableStoreSupport;
import algvis.core.visual.ZDepth;
import algvis.ds.priorityqueues.MeldablePQ;
import algvis.ui.Fonts;
import algvis.ui.view.View;
public class BinHeapNode extends Node {
private int leftw;
public int height;
public int rank; // TODO: size -> rank (treba ale
// zmenit aj pomocne upratovacie
// pole....)
public BinHeapNode parent, left, right, child;
public boolean cut; // TODO hm?
private BinHeapNode(DataStructure D, int key, int x, int y, int zDepth) {
super(D, key, x, y, zDepth);
parent = child = null;
left = right = this;
rank = 0;
bgKeyColor();
}
public BinHeapNode(DataStructure D, int key, int zDepth) {
this(D, key, 0, Node.UPY, zDepth);
}
public BinHeapNode(BinHeapNode v) {
this(v.D, v.getKey(), v.tox, v.toy, ZDepth.ACTIONNODE);
}
public boolean isRoot() {
return parent == null;
}
boolean isLeaf() {
return child == null;
}
// vyhodi sa zo zoznamu
public void unlink() {
if (parent != null) {
if (parent.child == this) {
if (right == this) {
parent.child = null;
} else {
parent.child = right;
}
}
parent.rank--;
parent = null;
}
left.right = right;
right.left = left;
left = right = this;
}
// napoji v ako prveho
public void linkChild(BinHeapNode v) {
if (isLeaf()) {
v.left = v.right = v;
} else {
v.left = child.left;
v.right = child;
v.left.right = v;
v.right.left = v;
}
v.parent = this;
child = v;
++height;
++rank;
}
public void linkRight(BinHeapNode v) {
v.parent = null;
right.left = v;
v.left = this;
v.right = right;
right = v;
}
public void linkLeft(BinHeapNode v) {
v.parent = null;
left.right = v;
v.right = this;
v.left = left;
left = v;
}
public void linkAll(BinHeapNode v) {
// ku this-x-x-x-u pripoj v-x-x-x-x-w
// linkLeft prilinkuje len samotne v
final BinHeapNode u = this.left, w = v.left;
u.right = v;
v.left = u;
this.left = w;
w.right = this;
}
void rebox() {
if (isLeaf()) {
leftw = DataStructure.minsepx / 2;
height = 1;
} else {
leftw = child.leftw;
height = child.height + 1;
final BinHeapNode w = child;
BinHeapNode v = child.right;
while (v != w) {
leftw += Node.RADIUS + v.leftw;
v = v.right;
}
}
}
void reboxTree(BinHeapNode first) {
if (!isLeaf()) {
child.reboxTree(child);
}
if (right != first) {
right.reboxTree(first);
}
rebox();
}
private void repos(int x, int y, BinHeapNode first) {
goTo(x + leftw, y);
if (!isLeaf()) {
child.repos(x, y + DataStructure.minsepy, child);
}
if (right != first) {
right.repos(x + leftw + Node.RADIUS, y, first);
}
}
public void _reposition(int x, int y) {
reboxTree(this);
repos(x, y, this);
}
public void drawTree(View v, BinHeapNode first, BinHeapNode parent) {
if (!isLeaf()) {
child.drawTree(v, child, this);
}
if (right != first) {
right.drawTree(v, first, parent);
}
if (parent != null) { // edge to parent
v.setColor(Color.black);
v.drawLine(x, y, parent.x, parent.y);
} else if (this != first) { // edge to left
v.setColor(Color.black);
v.drawLine(x, y, left.x, left.y);
}
draw(v);
}
public void moveTree() {
moveTree(this);
}
void moveTree(BinHeapNode first) {
move();
if (!isLeaf()) {
child.moveTree(child);
}
if (right != first) {
right.moveTree(first);
}
}
void lowlight() {
bgColor(new Color(200, 200 - getKey() / 10, 0));
}
void highlight() {
bgKeyColor();
}
public void lowlightTree() {
lowlightTree(this);
}
void lowlightTree(BinHeapNode first) {
lowlight();
if (!isLeaf()) {
child.lowlightTree(child);
}
if (right != first) {
right.lowlightTree(first);
}
}
public void highlightTree() {
highlightTree(this);
}
public void highlightTree(BinHeapNode first) {
highlight();
if (!isLeaf()) {
child.highlightTree(child);
}
if (right != first) {
right.highlightTree(first);
}
}
public boolean prec(Node v) {
if (((MeldablePQ) D).minHeap) {
return this.getKey() < v.getKey();
} else {
return this.getKey() > v.getKey();
}
}
public boolean preceq(Node v) {
if (((MeldablePQ) D).minHeap) {
return this.getKey() <= v.getKey();
} else {
return this.getKey() >= v.getKey();
}
}
@Override
public void draw(View v) {
if (state == Node.INVISIBLE || getKey() == NULL) {
return;
}
drawBg(v);
drawKey(v);
if (parent == null) {
v.setColor(Color.black);
v.drawString("" + rank, x + Node.RADIUS, y - Node.RADIUS,
Fonts.SMALL);
}
}
public BinHeapNode find(BinHeapNode first, int x, int y) {
if (inside(x, y)) {
return this;
}
if (!isLeaf()) {
final BinHeapNode tmp = child.find(child, x, y);
if (tmp != null) {
return tmp;
}
}
if (right != first) {
return right.find(first, x, y);
}
return null;
}
public void markCut() {
cut = true;
setColor(NodeColor.BLACK);
}
public void unmarkCut() {
cut = false;
bgKeyColor();
fgColor(Color.black);
}
@Override
public void storeState(Hashtable<Object, Object> state) {
super.storeState(state);
HashtableStoreSupport.store(state, hash + "left", left);
HashtableStoreSupport.store(state, hash + "right", right);
HashtableStoreSupport.store(state, hash + "parent", parent);
HashtableStoreSupport.store(state, hash + "child", child);
HashtableStoreSupport.store(state, hash + "leftw", leftw);
HashtableStoreSupport.store(state, hash + "height", height);
HashtableStoreSupport.store(state, hash + "rank", rank);
}
public void storeTreeState(Hashtable<Object, Object> state) {
storeTreeState(state, this);
}
private void storeTreeState(Hashtable<Object, Object> state,
BinHeapNode first) {
storeState(state);
if (child != null) {
child.storeTreeState(state);
}
if (right != first) {
right.storeTreeState(state, first);
}
}
@Override
public void restoreState(Hashtable<?, ?> state) {
super.restoreState(state);
final Object left = state.get(hash + "left");
if (left != null) {
this.left = (BinHeapNode) HashtableStoreSupport.restore(left);
}
final Object right = state.get(hash + "right");
if (right != null) {
this.right = (BinHeapNode) HashtableStoreSupport.restore(right);
}
final Object parent = state.get(hash + "parent");
if (parent != null) {
this.parent = (BinHeapNode) HashtableStoreSupport.restore(parent);
}
final Object child = state.get(hash + "child");
if (child != null) {
this.child = (BinHeapNode) HashtableStoreSupport.restore(child);
}
final Object leftw = state.get(hash + "leftw");
if (leftw != null) {
this.leftw = (Integer) HashtableStoreSupport.restore(leftw);
}
final Object height = state.get(hash + "height");
if (height != null) {
this.height = (Integer) HashtableStoreSupport.restore(height);
}
final Object rank = state.get(hash + "rank");
if (rank != null) {
this.rank = (Integer) HashtableStoreSupport.restore(rank);
}
}
public void restoreTreeState(Hashtable<?, ?> state) {
restoreTreeState(state, this);
}
private void restoreTreeState(Hashtable<?, ?> state, BinHeapNode first) {
restoreState(state);
if (this.child != null) {
this.child.restoreTreeState(state);
}
if (this.right != first) {
this.right.restoreTreeState(state, first);
}
}
// public void debug() {
// System.out.println("NodeKey: " + key);
// System.out.println("left: " + (left == null ? "null" : left.key));
// System.out.println("right: " + (right == null ? "null" : right.key));
// System.out.println("parent: " + (parent == null ? "null" : parent.key));
// System.out.println("child: " + (child == null ? "null" : child.key));
// System.out.println("leftw: " + leftw);
// System.out.println("height: " + height);
// System.out.println("rank: " + rank);
// }
//
// public void debugTree() {
// debugTree(this);
// }
//
// public void debugTree(BinHeapNode first) {
// debug();
// if (child != null) child.debugTree();
// if (right != first) right.debugTree(first);
// }
}