diff --git a/binarytree/BTNode.java b/binarytree/BTNode.java new file mode 100644 index 0000000..4fa15be --- /dev/null +++ b/binarytree/BTNode.java @@ -0,0 +1,35 @@ +package binarytree; + +public class BTNode implements BTPosition { + + private E element = null; + private BTPosition left = null; + private BTPosition right = null; + private BTPosition parent = null; + + public BTNode() { } + + + public BTNode(E element, BTPosition parent, BTPosition left, BTPosition right) { + setElement(element); + setParent(parent); + setLeft(left); + setRight(right); + } + + public E element() { return element; } + + public void setElement(E o) { element=o; } + + public BTPosition getLeft() { return left; } + + public void setLeft(BTPosition v) { left=v; } + + public BTPosition getRight() { return right; } + + public void setRight(BTPosition v) { right=v; } + + public BTPosition getParent() { return parent; } + + public void setParent(BTPosition v) { parent=v; } +} diff --git a/binarytree/BTPosition.java b/binarytree/BTPosition.java new file mode 100644 index 0000000..a951bfe --- /dev/null +++ b/binarytree/BTPosition.java @@ -0,0 +1,14 @@ +package binarytree; + + +import position.Position; + +public interface BTPosition extends Position { // inherits element() + public void setElement(E o); + public BTPosition getLeft(); + public void setLeft(BTPosition v); + public BTPosition getRight(); + public void setRight(BTPosition v); + public BTPosition getParent(); + public void setParent(BTPosition v); +} diff --git a/binarytree/BinaryTree.java b/binarytree/BinaryTree.java new file mode 100644 index 0000000..50f7e57 --- /dev/null +++ b/binarytree/BinaryTree.java @@ -0,0 +1,20 @@ +package binarytree; + + +import exceptions.BoundaryViolationException; +import exceptions.InvalidPositionException; +import position.Position; +import tree.Tree; + +public interface BinaryTree extends Tree { + + public Position left(Position v) throws InvalidPositionException, BoundaryViolationException; + + public Position right(Position v) throws InvalidPositionException, BoundaryViolationException; + + public boolean hasLeft(Position v) throws InvalidPositionException; + + public boolean hasRight(Position v) throws InvalidPositionException; + +} + diff --git a/binarytree/LinkedBinaryTree.java b/binarytree/LinkedBinaryTree.java new file mode 100644 index 0000000..13e0381 --- /dev/null +++ b/binarytree/LinkedBinaryTree.java @@ -0,0 +1,315 @@ +package binarytree; +import exceptions.BoundaryViolationException; +import exceptions.EmptyTreeException; +import exceptions.InvalidPositionException; +import exceptions.NonEmptyTreeException; +import position.NodePositionList; +import position.Position; +import position.PositionList; + +import java.util.Iterator; + + +public class LinkedBinaryTree implements BinaryTree { + protected BTPosition root; + protected int size; + + public LinkedBinaryTree() { + root = null; + size = 0; + } + + + public int size() { + return size; + } + + public boolean isEmpty() { + return (size == 0); + } + + + public boolean isInternal(Position v) throws InvalidPositionException { + checkPosition(v); + return (hasLeft(v) || hasRight(v)); + } + + public boolean isExternal(Position v) throws InvalidPositionException { + return !isInternal(v); + } + + public boolean isRoot(Position v) throws InvalidPositionException { + checkPosition(v); + return (v == root()); + } + + public boolean hasLeft(Position v) throws InvalidPositionException { + BTPosition vv = checkPosition(v); + return (vv.getLeft() != null); + } + + public boolean hasRight(Position v) throws InvalidPositionException { + BTPosition vv = checkPosition(v); + return (vv.getRight() != null); + } + + + public Position root() throws EmptyTreeException { + if (root == null) + throw new EmptyTreeException("The tree is empty"); + return root; + } + + + public Position left(Position v) throws InvalidPositionException, BoundaryViolationException { + BTPosition vv = checkPosition(v); + Position leftPos = vv.getLeft(); + if (leftPos == null) + throw new BoundaryViolationException("No left child"); + return leftPos; + } + + + public Position right(Position v) + throws InvalidPositionException, BoundaryViolationException { + BTPosition vv = checkPosition(v); + Position rightPos = vv.getRight(); + if (rightPos == null) + throw new BoundaryViolationException("No right child"); + return rightPos; + } + + + public Position parent(Position v) throws InvalidPositionException, BoundaryViolationException { + BTPosition vv = checkPosition(v); + Position parentPos = vv.getParent(); + if (parentPos == null) + throw new BoundaryViolationException("No parent"); + return parentPos; + } + + + public Iterable> children(Position v) throws InvalidPositionException { + PositionList> children = new NodePositionList>(); + if (hasLeft(v)) + children.addLast(left(v)); + if (hasRight(v)) + children.addLast(right(v)); + return children; + } + + public Iterable> positions() { + PositionList> positions = new NodePositionList>(); + if(size != 0) + preorderPositions(root(), positions); + return positions; + } + + public Iterator iterator() { + Iterable> positions = positions(); + PositionList elements = new NodePositionList(); + for (Position pos: positions) + elements.addLast(pos.element()); + return elements.iterator(); + } + + public E replace(Position v, E o) throws InvalidPositionException { + BTPosition vv = checkPosition(v); + E temp = v.element(); + vv.setElement(o); + return temp; + } + + + public Position sibling(Position v) throws InvalidPositionException, BoundaryViolationException { + BTPosition vv = checkPosition(v); + BTPosition parentPos = vv.getParent(); + if (parentPos != null) { + BTPosition sibPos; + BTPosition leftPos = parentPos.getLeft(); + if (leftPos == vv) + sibPos = parentPos.getRight(); + else + sibPos = parentPos.getLeft(); + if (sibPos != null) + return sibPos; + } + throw new BoundaryViolationException("No sibling"); + } + + + public Position addRoot(E e) throws NonEmptyTreeException { + if(!isEmpty()) + throw new NonEmptyTreeException("Tree already has a root"); + size = 1; + root = createNode(e,null,null,null); + return root; + } + + + public Position insertLeft(Position v, E e) throws InvalidPositionException { + BTPosition vv = checkPosition(v); + Position leftPos = vv.getLeft(); + if (leftPos != null) + throw new InvalidPositionException("Node already has a left child"); + BTPosition ww = createNode(e, vv, null, null); + vv.setLeft(ww); + size++; + return ww; + } + + public Position insertRight(Position v, E e) throws InvalidPositionException { + BTPosition vv = checkPosition(v); + Position rightPos = vv.getRight(); + if (rightPos != null) + throw new InvalidPositionException("Node already has a right child"); + BTPosition w = createNode(e, vv, null, null); + vv.setRight(w); + size++; + return w; + } + + public E remove(Position v) throws InvalidPositionException { + BTPosition vv = checkPosition(v); + BTPosition leftPos = vv.getLeft(); + BTPosition rightPos = vv.getRight(); + if (leftPos != null && rightPos != null) + throw new InvalidPositionException("Cannot remove node with two children"); + BTPosition ww; + if (leftPos != null) + ww = leftPos; + else if (rightPos != null) + ww = rightPos; + else + ww = null; + if (vv == root) { + if (ww != null) + ww.setParent(null); + root = ww; + } + else { + BTPosition uu = vv.getParent(); + if (vv == uu.getLeft()) + uu.setLeft(ww); + else + uu.setRight(ww); + if(ww != null) + ww.setParent(uu); + } + size--; + return v.element(); + } + + + /** Attaches two trees to be subtrees of an external node. */ + public void attach(Position v, BinaryTree T1, BinaryTree T2) throws InvalidPositionException { + BTPosition vv = checkPosition(v); + if (isInternal(v)) + throw new InvalidPositionException("Cannot attach from internal node"); + int newSize = size + T1.size() + T2.size(); + if (!T1.isEmpty()) { + BTPosition r1 = checkPosition(T1.root()); + vv.setLeft(r1); + r1.setParent(vv); + } + if (!T2.isEmpty()) { + BTPosition r2 = checkPosition(T2.root()); + vv.setRight(r2); + r2.setParent(vv); + } + size = newSize; + } + + public void swapElements(Position v, Position w) throws InvalidPositionException { + BTPosition vv = checkPosition(v); + BTPosition ww = checkPosition(w); + E temp = w.element(); + ww.setElement(v.element()); + vv.setElement(temp); + } + + public void expandExternal(Position v, E l, E r) throws InvalidPositionException { + checkPosition(v); + if (!isExternal(v)) + throw new InvalidPositionException("Node is not external"); + insertLeft(v, l); + insertRight(v, r); + } + + public void removeAboveExternal(Position v) throws InvalidPositionException { + checkPosition(v); + if (!isExternal(v)) + throw new InvalidPositionException("Node is not external"); + if (isRoot(v)) + remove(v); + else { + Position u = parent(v); + remove(v); + remove(u); + } + } + + + public void attachLeaves (PositionList L) { + if (!isEmpty()) + attachLeaves_r(root(),L); + } + + + + protected void attachLeaves_r(Position v, PositionList L) throws InvalidPositionException { + BTPositionvv = checkPosition(v); + + + if (hasLeft(v)) + attachLeaves_r(left(v), L); + if (hasRight(v)) + attachLeaves_r(right(v), L); + + if (isExternal(v)){ + BTPosition a = createNode( L.remove(L.first()) ,vv,null,null); + BTPosition b = createNode( L.remove(L.first()) ,vv,null,null); + vv.setLeft(a); + vv.setRight(b); + size+=2; + } + + } + + + // Other methods + + protected BTPosition checkPosition(Position v) throws InvalidPositionException { + if (v == null || !(v instanceof BTPosition) || isEmpty() ) + throw new InvalidPositionException("The position is invalid"); + return (BTPosition) v; + } + + protected BTPosition createNode(E element, BTPosition parent, BTPosition left, BTPosition right) { + return new BTNode(element,parent,left,right); } + + + + protected void preorderPositions(Position v, PositionList> pos) throws InvalidPositionException { + pos.addLast(v); + if (hasLeft(v)) + preorderPositions(left(v), pos); + if (hasRight(v)) + preorderPositions(right(v), pos); + } + + + protected void inorderPositions(Position v, PositionList> pos) throws InvalidPositionException { + if (hasLeft(v)) + inorderPositions(left(v), pos); + pos.addLast(v); + if (hasRight(v)) + inorderPositions(right(v), pos); + } + + + @Override + public String toString() { + return super.toString(); + } +} diff --git a/com/xgiovio/LinkedTreeTest.java b/com/xgiovio/LinkedTreeTest.java index 63ec56b..2ae543d 100644 --- a/com/xgiovio/LinkedTreeTest.java +++ b/com/xgiovio/LinkedTreeTest.java @@ -30,13 +30,14 @@ public class LinkedTreeTest { System.out.println(a.isEmpty()); System.out.println(a); - a.addChild(100,a.children(a.root()).iterator().next()); + + System.out.println(a.height()); + + a.remove(a.children(a.root()).iterator().next()); System.out.println(a.size()); System.out.println(a.isEmpty()); System.out.println(a); - System.out.println(a.height()); - diff --git a/tree/LinkedTree.java b/tree/LinkedTree.java index 6a14524..0608ca0 100644 --- a/tree/LinkedTree.java +++ b/tree/LinkedTree.java @@ -173,6 +173,31 @@ public class LinkedTree implements Tree { } + + + public E remove (Position v) { + TreePosition a = checkPosition(v); + if (isInternal(a)) + throw new InvalidPositionException(); + if (size() == 1) + return removeRoot(); + + PositionList> list = a.getParent().getChildren(); + Iterable>> it = list.positions(); + + for (Position> w : it){ + if (w.element() == v){ + size--; + return (list.remove(w)).element(); + } + } + + return null; + } + + + + public int depth ( Position v) throws InvalidPositionException{ TreePosition a = checkPosition(v); if (a.getParent() == null)