ADS_Praktikum_6/src/ch/zhaw/ads/AVLSearchTree.java

200 lines
5.8 KiB
Java

package ch.zhaw.ads;
/**
* Implements an AVL tree.
* Note that all "matching" is based on the compareTo method.
* @author Mark Allen Weiss
* Generic K.Rege
*/
public class AVLSearchTree<T extends Comparable<T>> extends SortedBinaryTree<T> {
private boolean balanced(TreeNode<T> node) {
// TODO Implement (6.4)
return true;
}
public boolean balanced() {
return balanced(root);
}
@Override
protected int calcSize(TreeNode<T> p) {
// TODO Implement (6.2)
}
/**
* Return the height of node t, or 0, if null.
*/
private static <T extends Comparable<T>> int height(TreeNode<T> t) {
return t == null ? 0 : t.height;
}
/**
* Insert into the tree; duplicates are ignored.
* @param element the item to insert.
*/
public void add(T element) {
root = insertAt(root, element);
}
private TreeNode<T> balance(TreeNode<T> p) {
if (p == null) {
return null;
} else if (height(p.left) - height(p.right) == 2) {
if (height(p.left.left) >= height(p.left.right)) {
// TODO Implement (6.2)
} else {
// TODO Implement (6.2)
}
} else if (height(p.right) - height(p.left) == 2) {
if (height(p.right.right) >= height(p.right.left)) {
// TODO Implement (6.2)
} else {
// TODO Implement (6.2)
}
}
p.height = Math.max(height(p.left), height(p.right)) + 1;
return p;
}
/**
* Internal method to insert into a subtree.
* @param element the item to insert.
* @param p the node that roots the tree.
* @return the new root.
*/
private TreeNode<T> insertAt(TreeNode<T> p, T element) {
if (p == null) {
p = new TreeNode<>(element);
p.height = 1;
return p;
} else {
int c = element.compareTo(p.getValue());
if (c == 0) {
p.values.add(element);
} else if (c < 0) {
p.left = insertAt(p.left, element);
} else {
p.right = insertAt(p.right, element);
}
}
p = balance(p);
return p;
}
// find node to replace
private TreeNode<T> rep;
private TreeNode<T> findRepAt(TreeNode<T> node) {
if (node.right != null) {
node.right = findRepAt(node.right);
node = balance(node);
} else {
rep = node;
node = node.left;
}
return node;
}
private T removed;
// remove node
private TreeNode<T> removeAt(TreeNode<T> node, T x) {
if (node == null) {
return null;
} else {
if (x.compareTo(node.getValue()) == 0) {
// found
removed = node.getValue();
if (node.values.size() > 1) {
node.values.remove(0);
return node;
} else if (node.left == null) {
node = node.right;
} else if (node.right == null) {
node = node.left;
} else {
node.left = findRepAt(node.left);
rep.left = node.left;
rep.right = node.right;
node = rep;
}
} else if (x.compareTo(node.getValue()) <= 0) {
// search left
node.left = removeAt(node.left, x);
} else {
// search right
node.right = removeAt(node.right, x);
}
// TODO Implement (6.5)
return node;
}
}
/**
* Remove from the tree. Nothing is done if x is not found.
* @param x the item to remove.
*/
public T remove(T x) {
removed = null;
root = removeAt(root, x);
return removed;
}
public Traversal<T> traversal() {
return new AVLTreeTraversal<>(root);
}
public T removeLast() {
throw new UnsupportedOperationException();
}
/**
* Rotate binary tree node with left child.
* For AVL trees, this is a single rotation for case 1.
* Update heights, then return new root.
*/
private static <T extends Comparable<T>> TreeNode<T> rotateR(TreeNode<T> k2) {
TreeNode<T> k1 = k2.left;
k2.left = k1.right;
k1.right = k2;
k2.height = Math.max(height(k2.left), height(k2.right)) + 1;
k1.height = Math.max(height(k1.left), k2.height) + 1;
return k1;
}
/**
* Rotate binary tree node with right child.
* For AVL trees, this is a single rotation for case 4.
* Update heights, then return new root.
*/
private static <T extends Comparable<T>> TreeNode<T> rotateL(TreeNode<T> k1) {
TreeNode<T> k2 = k1.right;
k1.right = k2.left;
k2.left = k1;
k1.height = Math.max(height(k1.left), height(k1.right)) + 1;
k2.height = Math.max(height(k2.right), k1.height) + 1;
return k2;
}
/**
* Double rotate binary tree node: first left child
* with its right child; then node k3 with new left child.
* For AVL trees, this is a double rotation for case 2.
* Update heights, then return new root.
*/
private static <T extends Comparable<T>> TreeNode<T> rotateLR(TreeNode<T> k3) {
k3.left = rotateL(k3.left);
return rotateR(k3);
}
/**
* Double rotate binary tree node: first right child
* with its left child; then node k1 with new right child.
* For AVL trees, this is a double rotation for case 3.
* Update heights, then return new root.
*/
private static <T extends Comparable<T>> TreeNode<T> rotateRL(TreeNode<T> k1) {
k1.right = rotateR(k1.right);
return rotateL(k1);
}
}