189 lines
5.9 KiB
Java
189 lines
5.9 KiB
Java
package com.jwetherell.algorithms.data_structures;
|
|
|
|
/**
|
|
* A splay tree is a self-adjusting binary search tree (BST) with the additional
|
|
* property that recently accessed elements are quick to access again.
|
|
*
|
|
* http://en.wikipedia.org/wiki/Splay_tree
|
|
*
|
|
* @author Justin Wetherell <phishman3579@gmail.com>
|
|
*/
|
|
public class SplayTree<T extends Comparable<T>> extends BinarySearchTree<T> {
|
|
|
|
/**
|
|
* {@inheritDoc}
|
|
*/
|
|
@Override
|
|
protected Node<T> addValue(T id) {
|
|
Node<T> nodeToReturn = super.addValue(id);
|
|
Node<T> nodeAdded = nodeToReturn;
|
|
if (nodeAdded != null) {
|
|
// Splay the new node to the root position
|
|
while (nodeAdded.parent != null) {
|
|
this.splay(nodeAdded);
|
|
}
|
|
}
|
|
return nodeToReturn;
|
|
}
|
|
|
|
/**
|
|
* {@inheritDoc}
|
|
*/
|
|
@Override
|
|
protected Node<T> removeValue(T value) {
|
|
Node<T> nodeToRemove = super.removeValue(value);
|
|
if (nodeToRemove != null && nodeToRemove.parent != null) {
|
|
Node<T> nodeParent = nodeToRemove.parent;
|
|
// Splay the parent node to the root position
|
|
while (nodeParent.parent != null) {
|
|
this.splay(nodeParent);
|
|
}
|
|
}
|
|
return nodeToRemove;
|
|
}
|
|
|
|
/**
|
|
* {@inheritDoc}
|
|
*/
|
|
@Override
|
|
public boolean contains(T value) {
|
|
Node<T> node = getNode(value);
|
|
if (node != null) {
|
|
// Splay the new node to the root position
|
|
while (node.parent != null) {
|
|
this.splay(node);
|
|
}
|
|
return true;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
/**
|
|
* Splay the tree at the node.
|
|
*
|
|
* @param node
|
|
* to splay at.
|
|
*/
|
|
private void splay(Node<T> node) {
|
|
Node<T> parent = node.parent;
|
|
Node<T> grandParent = (parent != null) ? parent.parent : null;
|
|
if (parent == root) {
|
|
grandParent = parent.parent;
|
|
// Zig step
|
|
root = node;
|
|
node.parent = null;
|
|
|
|
if (parent!=null) {
|
|
if (node == parent.lesser) {
|
|
parent.lesser = node.greater;
|
|
if (node.greater != null)
|
|
node.greater.parent = parent;
|
|
|
|
node.greater = parent;
|
|
parent.parent = node;
|
|
} else {
|
|
parent.greater = node.lesser;
|
|
if (node.lesser != null)
|
|
node.lesser.parent = parent;
|
|
|
|
node.lesser = parent;
|
|
parent.parent = node;
|
|
}
|
|
}
|
|
return;
|
|
}
|
|
|
|
if (parent != null && grandParent != null) {
|
|
Node<T> greatGrandParent = grandParent.parent;
|
|
if (greatGrandParent != null && greatGrandParent.lesser == grandParent) {
|
|
greatGrandParent.lesser = node;
|
|
node.parent = greatGrandParent;
|
|
} else if (greatGrandParent != null && greatGrandParent.greater == grandParent) {
|
|
greatGrandParent.greater = node;
|
|
node.parent = greatGrandParent;
|
|
} else {
|
|
// I am now root!
|
|
root = node;
|
|
node.parent = null;
|
|
}
|
|
|
|
if ((node == parent.lesser && parent == grandParent.lesser)
|
|
|| (node == parent.greater && parent == grandParent.greater)) {
|
|
// Zig-zig step
|
|
if (node == parent.lesser) {
|
|
Node<T> nodeGreater = node.greater;
|
|
node.greater = parent;
|
|
parent.parent = node;
|
|
|
|
parent.lesser = nodeGreater;
|
|
if (nodeGreater != null)
|
|
nodeGreater.parent = parent;
|
|
|
|
Node<T> parentGreater = parent.greater;
|
|
parent.greater = grandParent;
|
|
grandParent.parent = parent;
|
|
|
|
grandParent.lesser = parentGreater;
|
|
if (parentGreater != null)
|
|
parentGreater.parent = grandParent;
|
|
} else {
|
|
Node<T> nodeLesser = node.lesser;
|
|
node.lesser = parent;
|
|
parent.parent = node;
|
|
|
|
parent.greater = nodeLesser;
|
|
if (nodeLesser != null)
|
|
nodeLesser.parent = parent;
|
|
|
|
Node<T> parentLesser = parent.lesser;
|
|
parent.lesser = grandParent;
|
|
grandParent.parent = parent;
|
|
|
|
grandParent.greater = parentLesser;
|
|
if (parentLesser != null)
|
|
parentLesser.parent = grandParent;
|
|
}
|
|
return;
|
|
}
|
|
|
|
// Zig-zag step
|
|
if (node == parent.lesser) {
|
|
Node<T> nodeLesser = node.greater;
|
|
Node<T> nodeGreater = node.lesser;
|
|
|
|
node.greater = parent;
|
|
parent.parent = node;
|
|
|
|
node.lesser = grandParent;
|
|
grandParent.parent = node;
|
|
|
|
parent.lesser = nodeLesser;
|
|
if (nodeLesser != null)
|
|
nodeLesser.parent = parent;
|
|
|
|
grandParent.greater = nodeGreater;
|
|
if (nodeGreater != null)
|
|
nodeGreater.parent = grandParent;
|
|
return;
|
|
}
|
|
|
|
Node<T> nodeLesser = node.lesser;
|
|
Node<T> nodeGreater = node.greater;
|
|
|
|
node.lesser = parent;
|
|
parent.parent = node;
|
|
|
|
node.greater = grandParent;
|
|
grandParent.parent = node;
|
|
|
|
parent.greater = nodeLesser;
|
|
if (nodeLesser != null)
|
|
nodeLesser.parent = parent;
|
|
|
|
grandParent.lesser = nodeGreater;
|
|
if (nodeGreater != null)
|
|
nodeGreater.parent = grandParent;
|
|
}
|
|
}
|
|
}
|