| marp | theme | paginate |
|---|---|---|
true |
cs253-theme |
true |
- Balanced Binary Search Trees
- AVL (Adelson-Velskii and Landis) Tree
- Red-Black tree
- References
| Search | Insert | Delete | |
|---|---|---|---|
| Unbalanced | |||
| Balanced |
- Keep the tree perfectly balanced by comparing heights of the subtrees.
- Keep the tree balanced by matchings colors of the nodes.
Source: AbstractBalancedBinarySearchTree.java.
public abstract class AbstractBalancedBinarySearchTree
<T extends Comparable<T>, N extends AbstractBinaryNode<T, N>>
extends AbstractBinarySearchTree<T, N> {
@Override
public N add(T key) {
N node = super.add(key);
balance(node);
return node;
}
@Override
public N remove(T key) {
N node = findNode(root, key);
if (node != null) {
N lowest = node.hasBothChildren() ? removeHibbard(node) : removeSelf(node);
if (lowest != null && lowest != node) balance(lowest);
}
return node;
}
/** Preserves the balance of the specific node and its ancestors. */
protected abstract void balance(N node);- Abstract method:
balance().
protected void rotateLeft(N node) {
N child = node.getRightChild();
node.setRightChild(child.getLeftChild());
if (node.hasParent())
node.getParent().replaceChild(node, child);
else
setRoot(child);
child.setLeftChild(node);
}
protected void rotateRight(N node) {
N child = node.getLeftChild();
node.setLeftChild(child.getRightChild());
if (node.hasParent())
node.getParent().replaceChild(node, child);
else
setRoot(child);
child.setRightChild(node);
}Source: AVLNode.java.
public class AVLNode<T extends Comparable<T>>
extends AbstractBinaryNode<T, AVLNode<T>> {
private int height;
public AVLNode(T key) {
super(key);
height = 1;
}
@Override
public void setLeftChild(AVLNode<T> node) {
super.setLeftChild(node);
resetHeights();
}
@Override
public void setRightChild(AVLNode<T> node) {
super.setRightChild(node);
resetHeights();
}public void resetHeights() { resetHeightsAux(this); }
private void resetHeightsAux(AVLNode<T> node) {
if (node != null) {
int lh = node.hasLeftChild() ? node.getLeftChild().getHeight() : 0;
int rh = node.hasRightChild() ? node.getRightChild().getHeight() : 0;
int height = Math.max(lh, rh) + 1;
if (height != node.getHeight()) {
node.setHeight(height);
resetHeightsAux(node.getParent());
}
}
}public int getBalanceFactor() {
if (hasBothChildren())
return left_child.getHeight() - right_child.getHeight();
else if (hasLeftChild())
return left_child.getHeight();
else if (hasRightChild())
return -right_child.getHeight();
else
return 0;
}Source: AVLTree.java.
public class AVLTree<T extends Comparable<T>>
extends AbstractBalancedBinarySearchTree<T, AVLNode<T>> {
@Override
public AVLNode<T> createNode(T key) {
return new AVLNode<T>(key);
}
@Override
protected void rotateLeft(AVLNode<T> node) {
super.rotateLeft(node);
node.resetHeights();
}
@Override
protected void rotateRight(AVLNode<T> node) {
super.rotateRight(node);
node.resetHeights();
}@Override
protected void balance(AVLNode<T> node) {
if (node == null) return;
int bf = node.getBalanceFactor();
if (bf == 2) {
AVLNode<T> child = node.getLeftChild();
if (child.getBalanceFactor() == -1) // case 1
rotateLeft(child);
rotateRight(node); // case 2
} else if (bf == -2) {
AVLNode<T> child = node.getRightChild();
if (child.getBalanceFactor() == 1) // case 3
rotateRight(child);
rotateLeft(node); // case 4
} else
balance(node.getParent());
}- What are the cases 1 - 4?
- Every node is either red or black.
- The root and all leaves (null) are black.
- Every red node must have two black child nodes.
- Every path from a node to any of its leaves must contain the same number of black nodes.
- Is the right tree a red-black tree?
- Is the right tree a red-black tree?
- Is the right tree a red-black tree?
Source: RedBlackTree.java.
public class RedBlackTree<T extends Comparable<T>>
extends AbstractBalancedBinarySearchTree<T, RedBlackNode<T>> {
public RedBlackNode<T> createNode(T key) {
return new RedBlackNode<T>(key);
}
protected void balance(RedBlackNode<T> node) {
if (isRoot(node))
node.setToBlack();
else if (node.getParent().isRed()) {
RedBlackNode<T> uncle = node.getUncle();
if (uncle != null && uncle.isRed())
balanceWithRedUncle(node, uncle);
else
balanceWithBlackUncle(node);
}
}private void balanceWithRedUncle(RedBlackNode<T> node, RedBlackNode<T> uncle) {
node.getParent().setToBlack();
uncle.setToBlack();
RedBlackNode<T> grandParent = node.getGrandParent();
grandParent.setToRed();
balance(grandParent);
}private void balanceWithBlackUncle(RedBlackNode<T> node) {
RedBlackNode<T> grandParent = node.getGrandParent();
if (grandParent != null) {
RedBlackNode<T> parent = node.getParent();
if (grandParent.isLeftChild(parent) && parent.isRightChild(node)) { // case 1
rotateLeft(parent);
node = parent;
}
else if (grandParent.isRightChild(parent) && parent.isLeftChild(node)) { // case 2
rotateRight(parent);
node = parent;
}
node.getParent().setToBlack();
grandParent.setToRed();
if (node.getParent().isLeftChild(node)) // case 3
rotateRight(grandParent);
else
rotateLeft(grandParent); // case 4
}
}- What are the cases 1 - 4?






