Java 实现红黑树:高效数据结构的代码示例
下面是一个使用 Java 编写的红黑树的示例代码:
public class RedBlackTree<Key extends Comparable<Key>, Value> {
private static final boolean RED = true;
private static final boolean BLACK = false;
private Node root;
private class Node {
private Key key;
private Value value;
private Node left, right;
private boolean color;
private int size;
public Node(Key key, Value value, boolean color, int size) {
this.key = key;
this.value = value;
this.color = color;
this.size = size;
}
}
public boolean isRed(Node node) {
if (node == null) {
return false;
}
return node.color == RED;
}
public int size(Node node) {
if (node == null) {
return 0;
}
return node.size;
}
public int size() {
return size(root);
}
public boolean isEmpty() {
return root == null;
}
public Value get(Key key) {
if (key == null) {
throw new IllegalArgumentException('Key cannot be null');
}
return get(root, key);
}
private Value get(Node node, Key key) {
while (node != null) {
int cmp = key.compareTo(node.key);
if (cmp < 0) {
node = node.left;
} else if (cmp > 0) {
node = node.right;
} else {
return node.value;
}
}
return null;
}
public boolean contains(Key key) {
return get(key) != null;
}
public void put(Key key, Value value) {
if (key == null) {
throw new IllegalArgumentException('Key cannot be null');
}
if (value == null) {
delete(key);
return;
}
root = put(root, key, value);
root.color = BLACK;
}
private Node put(Node node, Key key, Value value) {
if (node == null) {
return new Node(key, value, RED, 1);
}
int cmp = key.compareTo(node.key);
if (cmp < 0) {
node.left = put(node.left, key, value);
} else if (cmp > 0) {
node.right = put(node.right, key, value);
} else {
node.value = value;
}
if (isRed(node.right) && !isRed(node.left)) {
node = rotateLeft(node);
}
if (isRed(node.left) && isRed(node.left.left)) {
node = rotateRight(node);
}
if (isRed(node.left) && isRed(node.right)) {
flipColors(node);
}
node.size = size(node.left) + size(node.right) + 1;
return node;
}
public void deleteMin() {
if (isEmpty()) {
throw new NoSuchElementException('Red black tree is empty');
}
if (!isRed(root.left) && !isRed(root.right)) {
root.color = RED;
}
root = deleteMin(root);
if (!isEmpty()) {
root.color = BLACK;
}
}
private Node deleteMin(Node node) {
if (node.left == null) {
return null;
}
if (!isRed(node.left) && !isRed(node.left.left)) {
node = moveRedLeft(node);
}
node.left = deleteMin(node.left);
return balance(node);
}
public void deleteMax() {
if (isEmpty()) {
throw new NoSuchElementException('Red black tree is empty');
}
if (!isRed(root.left) && !isRed(root.right)) {
root.color = RED;
}
root = deleteMax(root);
if (!isEmpty()) {
root.color = BLACK;
}
}
private Node deleteMax(Node node) {
if (isRed(node.left)) {
node = rotateRight(node);
}
if (node.right == null) {
return null;
}
if (!isRed(node.right) && !isRed(node.right.left)) {
node = moveRedRight(node);
}
node.right = deleteMax(node.right);
return balance(node);
}
public void delete(Key key) {
if (key == null) {
throw new IllegalArgumentException('Key cannot be null');
}
if (!contains(key)) {
return;
}
if (!isRed(root.left) && !isRed(root.right)) {
root.color = RED;
}
root = delete(root, key);
if (!isEmpty()) {
root.color = BLACK;
}
}
private Node delete(Node node, Key key) {
if (key.compareTo(node.key) < 0) {
if (!isRed(node.left) && !isRed(node.left.left)) {
node = moveRedLeft(node);
}
node.left = delete(node.left, key);
} else {
if (isRed(node.left)) {
node = rotateRight(node);
}
if (key.compareTo(node.key) == 0 && (node.right == null)) {
return null;
}
if (!isRed(node.right) && !isRed(node.right.left)) {
node = moveRedRight(node);
}
if (key.compareTo(node.key) == 0) {
Node min = min(node.right);
node.key = min.key;
node.value = min.value;
node.right = deleteMin(node.right);
} else {
node.right = delete(node.right, key);
}
}
return balance(node);
}
private Node rotateLeft(Node node) {
Node temp = node.right;
node.right = temp.left;
temp.left = node;
temp.color = node.color;
node.color = RED;
temp.size = node.size;
node.size = size(node.left) + size(node.right) + 1;
return temp;
}
private Node rotateRight(Node node) {
Node temp = node.left;
node.left = temp.right;
temp.right = node;
temp.color = node.color;
node.color = RED;
temp.size = node.size;
node.size = size(node.left) + size(node.right) + 1;
return temp;
}
private void flipColors(Node node) {
node.color = !node.color;
node.left.color = !node.left.color;
node.right.color = !node.right.color;
}
private Node moveRedLeft(Node node) {
flipColors(node);
if (isRed(node.right.left)) {
node.right = rotateRight(node.right);
node = rotateLeft(node);
flipColors(node);
}
return node;
}
private Node moveRedRight(Node node) {
flipColors(node);
if (isRed(node.left.left)) {
node = rotateRight(node);
flipColors(node);
}
return node;
}
private Node balance(Node node) {
if (isRed(node.right)) {
node = rotateLeft(node);
}
if (isRed(node.left) && isRed(node.left.left)) {
node = rotateRight(node);
}
if (isRed(node.left) && isRed(node.right)) {
flipColors(node);
}
node.size = size(node.left) + size(node.right) + 1;
return node;
}
public Key min() {
if (isEmpty()) {
throw new NoSuchElementException('Red black tree is empty');
}
return min(root).key;
}
private Node min(Node node) {
if (node.left == null) {
return node;
}
return min(node.left);
}
public Key max() {
if (isEmpty()) {
throw new NoSuchElementException('Red black tree is empty');
}
return max(root).key;
}
private Node max(Node node) {
if (node.right == null) {
return node;
}
return max(node.right);
}
public Iterable<Key> keys() {
if (isEmpty()) {
return new LinkedList<>();
}
return keys(min(), max());
}
public Iterable<Key> keys(Key low, Key high) {
if (low == null || high == null) {
throw new IllegalArgumentException('Keys cannot be null');
}
Queue<Key> queue = new LinkedList<>();
keys(root, queue, low, high);
return queue;
}
private void keys(Node node, Queue<Key> queue, Key low, Key high) {
if (node == null) {
return;
}
int cmpLow = low.compareTo(node.key);
int cmpHigh = high.compareTo(node.key);
if (cmpLow < 0) {
keys(node.left, queue, low, high);
}
if (cmpLow <= 0 && cmpHigh >= 0) {
queue.offer(node.key);
}
if (cmpHigh > 0) {
keys(node.right, queue, low, high);
}
}
public static void main(String[] args) {
RedBlackTree<Integer, String> tree = new RedBlackTree<>();
tree.put(5, 'Apple');
tree.put(3, 'Banana');
tree.put(7, 'Orange');
tree.put(2, 'Pear');
tree.put(4, 'Grape');
tree.put(6, 'Cherry');
tree.put(8, 'Mango');
System.out.println('Keys in the red-black tree:');
for (Integer key : tree.keys()) {
System.out.println(key + ': ' + tree.get(key));
}
System.out.println('Delete key 4');
tree.delete(4);
System.out.println('Keys in the red-black tree after deletion:');
for (Integer key : tree.keys()) {
System.out.println(key + ': ' + tree.get(key));
}
}
}
上述代码实现了一个红黑树的基本操作,包括插入、删除、查找等。在示例中,我们创建了一个红黑树并插入了一些键值对,然后打印出红黑树中的键值对。最后,我们删除了一个键值对并再次打印红黑树中的键值对。
红黑树是一种自平衡二叉查找树,它通过保持树的平衡来确保最坏情况下插入和删除操作的复杂度为 O(log n),从而保证搜索效率。这使得红黑树在各种应用中都非常有用,例如数据库索引、网络路由器等。
原文地址: http://www.cveoy.top/t/topic/fPF7 著作权归作者所有。请勿转载和采集!