You are on page 1of 15

AVL

public class AVLtree {

private Node root;

private static class Node {


private int key;
private int balance;
private int height;
private Node left;
private Node right;
private Node parent;

Node(int key, Node parent) {


this.key = key;
this.parent = parent;
}
}

public boolean insert(int key) {


if (root == null) {
root = new Node(key, null);
return true;
}

Node n = root;
while (true) {
if (n.key == key)
return false;

Node parent = n;

boolean goLeft = n.key > key;


n = goLeft ? n.left : n.right;

if (n == null) {
if (goLeft) {
parent.left = new Node(key, parent);
} else {
parent.right = new Node(key, parent);
}
rebalance(parent);
break;
}
}
return true;
}

private void delete(Node node) {


if (node.left == null && node.right == null) {
if (node.parent == null) {
root = null;
} else {
Node parent = node.parent;
if (parent.left == node) {
parent.left = null;
} else {
parent.right = null;
}
rebalance(parent);
}
return;
}

if (node.left != null) {
Node child = node.left;
while (child.right != null) child = child.right;
node.key = child.key;
delete(child);
} else {
Node child = node.right;
while (child.left != null) child = child.left;
node.key = child.key;
delete(child);
}
}

public void delete(int delKey) {


if (root == null)
return;

Node child = root;


while (child != null) {
Node node = child;
child = delKey >= node.key ? node.right : node.left;
if (delKey == node.key) {
delete(node);
return;
}
}
}

private void rebalance(Node n) {


setBalance(n);

if (n.balance == -2) {
if (height(n.left.left) >= height(n.left.right))
n = rotateRight(n);
else
n = rotateLeftThenRight(n);

} else if (n.balance == 2) {
if (height(n.right.right) >= height(n.right.left))
n = rotateLeft(n);
else
n = rotateRightThenLeft(n);
}

if (n.parent != null) {
rebalance(n.parent);
} else {
root = n;
}
}

private Node rotateLeft(Node a) {

Node b = a.right;
b.parent = a.parent;

a.right = b.left;

if (a.right != null)
a.right.parent = a;

b.left = a;
a.parent = b;

if (b.parent != null) {
if (b.parent.right == a) {
b.parent.right = b;
} else {
b.parent.left = b;
}
}

setBalance(a, b);

return b;
}

private Node rotateRight(Node a) {

Node b = a.left;
b.parent = a.parent;

a.left = b.right;

if (a.left != null)
a.left.parent = a;

b.right = a;
a.parent = b;

if (b.parent != null) {
if (b.parent.right == a) {
b.parent.right = b;
} else {
b.parent.left = b;
}
}

setBalance(a, b);

return b;
}

private Node rotateLeftThenRight(Node n) {


n.left = rotateLeft(n.left);
return rotateRight(n);
}

private Node rotateRightThenLeft(Node n) {


n.right = rotateRight(n.right);
return rotateLeft(n);
}

private int height(Node n) {


if (n == null)
return -1;
return n.height;
}

private void setBalance(Node... nodes) {


for (Node n : nodes) {
reheight(n);
n.balance = height(n.right) - height(n.left);
}
}

public void printBalance() {


printBalance(root);
}

private void printBalance(Node n) {


if (n != null) {
printBalance(n.left);
System.out.printf("%s ", n.balance);
printBalance(n.right);
}
}

private void reheight(Node node) {


if (node != null) {
node.height = 1 + Math.max(height(node.left), height(node.right
));
}
}

public static void main(String[] args) {


AVLtree tree = new AVLtree();

System.out.println("Inserting values 1 to 10");


for (int i = 1; i < 10; i++)
tree.insert(i);

System.out.print("Printing balance: ");


tree.printBalance();
}
}




RN

ublic class RedBlackTree extends BinarySearchTree {

/**
* Constructs an empty RedBlackTree that can only accept
Comparables as
* items.
*/
public RedBlackTree() {
this(null);
}

/**
* Constructs an empty RedBlackTree that orders its items
according to the
* given comparator.
*/
public RedBlackTree(Comparator c) {
super(c);
}

/**
* The nodes in a red-black tree store a color together with
the actual data
* in the node.
*/
class Node extends LinkedBinaryTreeNode {
Color color = Color.black;

public Node(Object data) {


super(data);
}
}

/**
* Adds a single data item to the tree. If there is already
an item in the
* tree that compares equal to the item being inserted, it is
"overwritten"
* by the new item. Overrides BinarySearchTree.add because
the tree needs to
* be adjusted after insertion.
*/
public void add(Object data) {
if (root == null) {
root = new Node(data);
}
BinaryTreeNode n = root;
while (true) {
int comparisonResult = compare(data, n.getData());
if (comparisonResult == 0) {
n.setData(data);
return;
} else if (comparisonResult < 0) {
if (n.getLeft() == null) {
n.setLeft(new Node(data));
adjustAfterInsertion((Node) n.getLeft());
break;
}
n = n.getLeft();
} else { // comparisonResult > 0
if (n.getRight() == null) {
n.setRight(new Node(data));
adjustAfterInsertion((Node) n.getRight());
break;
}
n = n.getRight();
}
}
}

/**
* Removes the node containing the given value. Does nothing
if there is no
* such node.
*/
public void remove(Object data) {
Node node = (Node) nodeContaining(data);
if (node == null) {
// No such object, do nothing.
return;
} else if (node.getLeft() != null && node.getRight() !=
null) {
// Node has two children, Copy predecessor data in.
BinaryTreeNode predecessor = predecessor(node);
node.setData(predecessor.getData());
node = (Node) predecessor;
}
// At this point node has zero or one child
Node pullUp = leftOf(node) == null ? rightOf(node) :
leftOf(node);
if (pullUp != null) {
// Splice out node, and adjust if pullUp is a double
black.
if (node == root) {
setRoot(pullUp);
} else if (node.getParent().getLeft() == node) {
node.getParent().setLeft(pullUp);
} else {
node.getParent().setRight(pullUp);
}
if (isBlack(node)) {
adjustAfterRemoval(pullUp);
}
} else if (node == root) {
// Nothing to pull up when deleting a root means we
emptied the tree
setRoot(null);
} else {
// The node being deleted acts as a double black
sentinel
if (isBlack(node)) {
adjustAfterRemoval(node);
}
node.removeFromParent();
}
}

/**
* Classic algorithm for fixing up a tree after inserting a
node.
*/
private void adjustAfterInsertion(Node n) {
// Step 1: color the node red
setColor(n, Color.red);

// Step 2: Correct double red problems, if they exist


if (n != null && n != root && isRed(parentOf(n))) {

// Step 2a (simplest): Recolor, and move up to see if


more work
// needed
if (isRed(siblingOf(parentOf(n)))) {
setColor(parentOf(n), Color.black);
setColor(siblingOf(parentOf(n)), Color.black);
setColor(grandparentOf(n), Color.red);
adjustAfterInsertion(grandparentOf(n));
}

// Step 2b: Restructure for a parent who is the left


child of the
// grandparent. This will require a single right
rotation if n is
// also
// a left child, or a left-right rotation otherwise.
else if (parentOf(n) == leftOf(grandparentOf(n))) {
if (n == rightOf(parentOf(n))) {
rotateLeft(n = parentOf(n));
}
setColor(parentOf(n), Color.black);
setColor(grandparentOf(n), Color.red);
rotateRight(grandparentOf(n));
}

// Step 2c: Restructure for a parent who is the right


child of the
// grandparent. This will require a single left
rotation if n is
// also
// a right child, or a right-left rotation otherwise.
else if (parentOf(n) == rightOf(grandparentOf(n))) {
if (n == leftOf(parentOf(n))) {
rotateRight(n = parentOf(n));
}
setColor(parentOf(n), Color.black);
setColor(grandparentOf(n), Color.red);
rotateLeft(grandparentOf(n));
}
}

// Step 3: Color the root black


setColor((Node) root, Color.black);
}

/**
* Classic algorithm for fixing up a tree after removing a
node; the
* parameter to this method is the node that was pulled up to
where the
* removed node was.
*/
private void adjustAfterRemoval(Node n) {
while (n != root && isBlack(n)) {
if (n == leftOf(parentOf(n))) {
// Pulled up node is a left child
Node sibling = rightOf(parentOf(n));
if (isRed(sibling)) {
setColor(sibling, Color.black);
setColor(parentOf(n), Color.red);
rotateLeft(parentOf(n));
sibling = rightOf(parentOf(n));
}
if (isBlack(leftOf(sibling)) &&
isBlack(rightOf(sibling))) {
setColor(sibling, Color.red);
n = parentOf(n);
} else {
if (isBlack(rightOf(sibling))) {
setColor(leftOf(sibling), Color.black);
setColor(sibling, Color.red);
rotateRight(sibling);
sibling = rightOf(parentOf(n));
}
setColor(sibling, colorOf(parentOf(n)));
setColor(parentOf(n), Color.black);
setColor(rightOf(sibling), Color.black);
rotateLeft(parentOf(n));
n = (Node) root;
}
} else {
// pulled up node is a right child
Node sibling = leftOf(parentOf(n));
if (isRed(sibling)) {
setColor(sibling, Color.black);
setColor(parentOf(n), Color.red);
rotateRight(parentOf(n));
sibling = leftOf(parentOf(n));
}
if (isBlack(leftOf(sibling)) &&
isBlack(rightOf(sibling))) {
setColor(sibling, Color.red);
n = parentOf(n);
} else {
if (isBlack(leftOf(sibling))) {
setColor(rightOf(sibling), Color.black);
setColor(sibling, Color.red);
rotateLeft(sibling);
sibling = leftOf(parentOf(n));
}
setColor(sibling, colorOf(parentOf(n)));
setColor(parentOf(n), Color.black);
setColor(leftOf(sibling), Color.black);
rotateRight(parentOf(n));
n = (Node) root;
}
}
}
setColor(n, Color.black);
}

// The following helpers dramatically simplify the code by


getting
// all the null pointer checking out of the adjustment
methods.

private Color colorOf(Node n) {


return n == null ? Color.black : n.color;
}

private boolean isRed(Node n) {


return n != null && colorOf(n) == Color.red;
}

private boolean isBlack(Node n) {


return n == null || colorOf(n) == Color.black;
}

private void setColor(Node n, Color c) {


if (n != null)
n.color = c;
}

private Node parentOf(Node n) {


return n == null ? null : (Node) n.getParent();
}

private Node grandparentOf(Node n) {


return (n == null || n.getParent() == null) ? null :
(Node) n
.getParent().getParent();
}

private Node siblingOf(Node n) {


return (n == null || n.getParent() == null) ? null : (n
== n
.getParent().getLeft()) ? (Node)
n.getParent().getRight()
: (Node) n.getParent().getLeft();
}

private Node leftOf(Node n) {


return n == null ? null : (Node) n.getLeft();
}

private Node rightOf(Node n) {


return n == null ? null : (Node) n.getRight();
}


234
public class BTree<Key extends Comparable<Key>, Value> {
// max children per B-tree node = M-1
// (must be even and greater than 2)
private static final int M = 4;

private Node root; // root of the B-tree


private int height; // height of the B-tree
private int n; // number of key-value pairs in the B-tree

// helper B-tree node data type


private static final class Node {
private int m; // number of children
private Entry[] children = new Entry[M]; // the array of children

// create a node with k children


private Node(int k) {
m = k;
}
}

// internal nodes: only use key and next


// external nodes: only use key and value
private static class Entry {
private Comparable key;
private final Object val;
private Node next; // helper field to iterate over array
entries
public Entry(Comparable key, Object val, Node next) {
this.key = key;
this.val = val;
this.next = next;
}
}

/**
* Initializes an empty B-tree.
*/
public BTree() {
root = new Node(0);
}

/**
* Returns true if this symbol table is empty.
* @return {@code true} if this symbol table is empty; {@code false}
otherwise
*/
public boolean isEmpty() {
return size() == 0;
}

/**
* Returns the number of key-value pairs in this symbol table.
* @return the number of key-value pairs in this symbol table
*/
public int size() {
return n;
}

/**
* Returns the height of this B-tree (for debugging).
*
* @return the height of this B-tree
*/
public int height() {
return height;
}

/**
* Returns the value associated with the given key.
*
* @param key the key
* @return the value associated with the given key if the key is in the
symbol table
* and {@code null} if the key is not in the symbol table
* @throws IllegalArgumentException if {@code key} is {@code null}
*/
public Value get(Key key) {
if (key == null) throw new IllegalArgumentException("argument to
get() is null");
return search(root, key, height);
}

private Value search(Node x, Key key, int ht) {


Entry[] children = x.children;

// external node
if (ht == 0) {
for (int j = 0; j < x.m; j++) {
if (eq(key, children[j].key)) return (Value)
children[j].val;
}
}

// internal node
else {
for (int j = 0; j < x.m; j++) {
if (j+1 == x.m || less(key, children[j+1].key))
return search(children[j].next, key, ht-1);
}
}
return null;
}

/**
* Inserts the key-value pair into the symbol table, overwriting the
old value
* with the new value if the key is already in the symbol table.
* If the value is {@code null}, this effectively deletes the key from
the symbol table.
*
* @param key the key
* @param val the value
* @throws IllegalArgumentException if {@code key} is {@code null}
*/
public void put(Key key, Value val) {
if (key == null) throw new IllegalArgumentException("argument key
to put() is null");
Node u = insert(root, key, val, height);
n++;
if (u == null) return;

// need to split root


Node t = new Node(2);
t.children[0] = new Entry(root.children[0].key, null, root);
t.children[1] = new Entry(u.children[0].key, null, u);
root = t;
height++;
}

private Node insert(Node h, Key key, Value val, int ht) {


int j;
Entry t = new Entry(key, val, null);

// external node
if (ht == 0) {
for (j = 0; j < h.m; j++) {
if (less(key, h.children[j].key)) break;
}
}

// internal node
else {
for (j = 0; j < h.m; j++) {
if ((j+1 == h.m) || less(key, h.children[j+1].key)) {
Node u = insert(h.children[j++].next, key, val, ht-1);
if (u == null) return null;
t.key = u.children[0].key;
t.next = u;
break;
}
}
}

for (int i = h.m; i > j; i--)


h.children[i] = h.children[i-1];
h.children[j] = t;
h.m++;
if (h.m < M) return null;
else return split(h);
}

// split node in half


private Node split(Node h) {
Node t = new Node(M/2);
h.m = M/2;
for (int j = 0; j < M/2; j++)
t.children[j] = h.children[M/2+j];
return t;
}

/**
* Returns a string representation of this B-tree (for debugging).
*
* @return a string representation of this B-tree.
*/
public String toString() {
return toString(root, height, "") + "\n";
}

private String toString(Node h, int ht, String indent) {


StringBuilder s = new StringBuilder();
Entry[] children = h.children;

if (ht == 0) {
for (int j = 0; j < h.m; j++) {
s.append(indent + children[j].key + " " + children[j].val +
"\n");
}
}
else {
for (int j = 0; j < h.m; j++) {
if (j > 0) s.append(indent + "(" + children[j].key +
")\n");
s.append(toString(children[j].next, ht-1, indent + "
"));
}
}
return s.toString();
}

// comparison functions - make Comparable instead of Key to avoid casts


private boolean less(Comparable k1, Comparable k2) {
return k1.compareTo(k2) < 0;
}

private boolean eq(Comparable k1, Comparable k2) {


return k1.compareTo(k2) == 0;
}

/**
* Unit tests the {@code BTree} data type.
*
* @param args the command-line arguments
*/
public static void main(String[] args) {
BTree<String, String> st = new BTree<String, String>();

st.put("www.cs.princeton.edu", "128.112.136.12");
st.put("www.cs.princeton.edu", "128.112.136.11");
st.put("www.princeton.edu", "128.112.128.15");
st.put("www.yale.edu", "130.132.143.21");
st.put("www.simpsons.com", "209.052.165.60");
st.put("www.apple.com", "17.112.152.32");
st.put("www.amazon.com", "207.171.182.16");
st.put("www.ebay.com", "66.135.192.87");
st.put("www.cnn.com", "64.236.16.20");
st.put("www.google.com", "216.239.41.99");
st.put("www.nytimes.com", "199.239.136.200");
st.put("www.microsoft.com", "207.126.99.140");
st.put("www.dell.com", "143.166.224.230");
st.put("www.slashdot.org", "66.35.250.151");
st.put("www.espn.com", "199.181.135.201");
st.put("www.weather.com", "63.111.66.11");
st.put("www.yahoo.com", "216.109.118.65");

StdOut.println("cs.princeton.edu: " +
st.get("www.cs.princeton.edu"));
StdOut.println("hardvardsucks.com: " +
st.get("www.harvardsucks.com"));
StdOut.println("simpsons.com: " + st.get("www.simpsons.com"));
StdOut.println("apple.com: " + st.get("www.apple.com"));
StdOut.println("ebay.com: " + st.get("www.ebay.com"));
StdOut.println("dell.com: " + st.get("www.dell.com"));
StdOut.println();

StdOut.println("size: " + st.size());


StdOut.println("height: " + st.height());
StdOut.println(st);
StdOut.println();
}

You might also like