class Zipper { private int value; BinaryTree tree; // Only the root node will bind to the BinaryTree Zipper up; Zipper left; Zipper right; Zipper(int val) { value = val; tree = null; up = null; left = null; right = null; } /** * Get a zipper out of a rose tree, the focus is on the root node */ Zipper fromTree() { Zipper current = this; while (current.up != null) { current = current.up; } return current; } BinaryTree toTree() { Zipper current = this; while (current.up != null) { current = current.up; } return current.tree; } int getValue() { return value; } Zipper setLeft(Zipper leftChild) { left = leftChild; if (leftChild != null) { leftChild.up = this; leftChild.tree = null; } return this; } Zipper setRight(Zipper rightChild) { right = rightChild; if (rightChild != null) { rightChild.up = this; rightChild.tree = null; } return this; } /** * Move the focus to the previous child of the same parent * @return a new Zipper * Conditions: 1. The current Zipper must have a parent, i.e. it is not the root node. * 2. The current Zipper must be the right child of its parent */ Zipper getPrev() { Zipper current = this; try { current = this.up; current = current.left; return current; } catch (Exception e) { System.out.println(e); } return null; } /** * Move the focus to the next child of the same parent * @return a new Zipper * Conditions: 1. The current Zipper must have a parent, i.e. it is not the root node. * 2. The current Zipper must be the left child of its parent */ Zipper getNext() { Zipper current = this; try { current = this.up; current = current.right; return current; } catch (Exception e) { System.out.println(e); } return null; } /** * Move the focus to the parent * @return a new Zipper */ Zipper getUp() { return up; } /** * Set the value of the focus node, returns a new zipper * @param val */ void setValue(int val) { this.value = val; } /** * Insert a new subtree before the focus node, it becomes the prev of the focus node * @return a new Zipper */ Zipper insertBefore(Zipper toTheLeft) { this.left = toTheLeft; return this.left; } /** * Insert a new subtree after the focus node, it becomes the next of the focus node * @return a new Zipper */ Zipper insertAfter(Zipper toTheRight) { this.right = toTheRight; return this.right; } /** * Removes the focus node and all subtrees * Focus moves to the next node if possible otherwise to the prev node if possible, otherwise to the parent node * @return a new zipper */ Zipper delete() { Zipper current = this; if (current.up == null) { current = null; } else { if (current.up.left == current) { current = current.up; current.left = null; if (current.right != null) { current = current.right; } } else { current = current.up; current.right = null; if (current.left != null) { current = current.left; } } } return current; } } class BinaryTree { private Zipper root; BinaryTree(int value) { root = new Zipper(value); root.tree = this; } BinaryTree(Zipper root) { this.root = root; this.root.tree = this; } Zipper getRoot() { return root; } void setRoot(Zipper zipper) { root = zipper; root.tree = this; } String printTree(Zipper zipper) { String str = ""; if (zipper.left == null && zipper.right == null) { str += "value: " + zipper.getValue() + ", left: " + null + ", right: " + null; } else if (zipper.left == null) { str += "value: " + zipper.getValue() + ", left: " + null + ", right: { " + printTree(zipper.right) + " }"; } else if (zipper.right == null) { str += "value: " + zipper.getValue() + ", left: { " + printTree(zipper.left) + " }, right: " + null; } else { str += "value: " + zipper.getValue() + ", left: { " + printTree(zipper.left) + " }, right: { " + printTree(zipper.right) + " }"; } return str; } String printTree() { return printTree(root); } }