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> extends SortedBinaryTree { private boolean balanced(TreeNode node) { // TODO Implement (6.4) return true; } public boolean balanced() { return balanced(root); } @Override protected int calcSize(TreeNode p) { // TODO Implement (6.2) } /** * Return the height of node t, or 0, if null. */ private static > int height(TreeNode 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 balance(TreeNode 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 insertAt(TreeNode 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 rep; private TreeNode findRepAt(TreeNode 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 removeAt(TreeNode 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 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 > TreeNode rotateR(TreeNode k2) { TreeNode 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 > TreeNode rotateL(TreeNode k1) { TreeNode 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 > TreeNode rotateLR(TreeNode 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 > TreeNode rotateRL(TreeNode k1) { k1.right = rotateR(k1.right); return rotateL(k1); } }