1. 程式人生 > >《演算法導論》紅黑樹詳解(二):Java實現Demo

《演算法導論》紅黑樹詳解(二):Java實現Demo

使用Java簡單地實現紅黑樹,程式碼如下:

/**
 * 紅黑樹實現demo
 */
public class RedBlackTree<Key extends Comparable<Key>> {

    private static final boolean RED   = false;

    private static final boolean BLACK = true;

    /**
     * 葉結點
     */
    private final Node nil = new Node();

    /**
     * 根結點初始化為nil
     */
private Node root = nil; /** * 結點類 */ private class Node { private Key key; private Node left; private Node right; private Node parent; private boolean color = BLACK; public Node() { } public Node(Key key) { this
.key = key; } @Override public String toString() { String nodeColor = color ? "BLACK" : "RED"; return " " + key + "-" + nodeColor + " "; } } /** * 左旋 * @param x */ private void leftRotate(Node x){ Node y = x.right;
x.right = y.left; if (y.left != nil) { y.left.parent = x; } y.parent = x.parent; if (x.parent == nil) { root = y; } else if (x == x.parent.left) { x.parent.left = y; } else { x.parent.right = y; } y.left = x; x.parent = y; } /** * 右旋 * @param x */ private void rightRotate(Node x) { Node y = x.left; x.left = y.right; if (y.right != nil) { y.right.parent = x; } y.parent = x.parent; if (x.parent == nil) { root = y; } else if (x == x.parent.left) { x.parent.left = y; } else { x.parent.right = y; } y.right = x; x.parent = y; } /** * 插入 * @param key */ public void insert(Key key) { if (key == null) { return; } Node y = nil; Node x = root; while (x != nil) { y = x; if (key.compareTo(x.key) < 0) { x = x.left; } else if (key.compareTo(x.key) > 0) { x = x.right; } else { //重複結點不插入 return; } } Node z = new Node(key); z.parent = y; if (y == nil) { root = z; } else if (z.key.compareTo(y.key) < 0) { y.left = z; } else { y.right = z; } z.left = nil; z.right = nil; z.color = RED; insertFixup(z); } /** * 插入修復 * @param z */ private void insertFixup(Node z) { while (z.parent.color == RED) { if (z.parent == z.parent.parent.left) { Node y = z.parent.parent.right; if (y.color == RED) { z.parent.color = BLACK; y.color = BLACK; z.parent.parent.color = RED; z = z.parent.parent; } else { if (z == z.parent.right) { z = z.parent; leftRotate(z); } z.parent.color = BLACK; z.parent.parent.color = RED; rightRotate(z.parent.parent); } } else { Node y = z.parent.parent.left; if (y.color == RED) { z.parent.color = BLACK; y.color = BLACK; z.parent.parent.color = RED; z = z.parent.parent; } else { if (z == z.parent.left) { z = z.parent; rightRotate(z); } z.parent.color = BLACK; z.parent.parent.color = RED; leftRotate(z.parent.parent); } } } root.color = BLACK; } /** * 用v子樹替換u子樹 * @param u * @param v */ private void transplant(Node u, Node v) { if (u.parent == nil) { root = v; } else if (u == u.parent.left) { u.parent.left = v; } else { u.parent.right = v; } v.parent = u.parent; } /** * 查詢以x為根的最小結點 * @param x * @return */ private Node minimum(Node x) { while (x.left != nil) { x = x.left; } return x; } /** * 查詢結點的key值為key的結點 * @param key * @return */ private Node search(Key key) { Node x = root; while (x != nil && key.compareTo(x.key) != 0) { if (key.compareTo(x.key) < 0) { x = x.left; } else { x = x.right; } } return x; } /** * 刪除結點的key值為key的結點 * @param key */ public void delete(Key key) { if (key == null) { return; } Node z = search(key); if (z == nil) { return; } Node y = z; Node x; boolean yOriginalColor = y.color; if (z.left == nil) { x = z.right; transplant(z, z.right); } else if (z.right == nil) { x = z.left; transplant(z, z.left); } else { y = minimum(z.right); yOriginalColor = y.color; x = y.right; if (y.parent == z) { x.parent = y; } else { transplant(y, y.right); y.right = z.right; y.right.parent = y; } transplant(z, y); y.left = z.left; y.left.parent = y; y.color = z.color; } if (yOriginalColor == BLACK) { deleteFixup(x); } } /** * 刪除修復 * @param x */ private void deleteFixup(Node x) { while (x != root && x.color == BLACK) { if (x == x.parent.left) { Node w = x.parent.right; if (w.color == RED) { w.color = BLACK; x.parent.color = RED; leftRotate(x.parent); w = x.parent.right; } if (w.left.color == BLACK && w.right.color == BLACK) { w.color = RED; x = x.parent; } else { if (w.right.color == BLACK) { w.left.color = BLACK; w.color = RED; rightRotate(w); w = x.parent.right; } w.color = x.parent.color; x.parent.color = BLACK; w.right.color = BLACK; leftRotate(x.parent); x = root; } } else { Node w = x.parent.left; if (w.color == RED) { w.color = BLACK; x.parent.color = RED; leftRotate(x.parent); w = x.parent.left; } if (w.left.color == BLACK && w.right.color == BLACK) { w.color = RED; x = x.parent; } else { if (w.left.color == BLACK) { w.right.color = BLACK; w.color = RED; leftRotate(w); w = x.parent.left; } w.color = x.parent.color; x.parent.color = BLACK; w.left.color = BLACK; rightRotate(x.parent); x = root; } } } x.color = BLACK; } /** * 先序遍歷 */ public void preOrder() { preOrder(root); } /** * 對以x為根的子樹進行先序遍歷 * @param x */ private void preOrder(Node x) { if (x != nil) { System.out.print(x); preOrder(x.left); preOrder(x.right); } } /** * 中序遍歷 */ public void inOrder() { inOrder(root); } /** * 對以x為根的子樹進行中序遍歷 * @param x */ private void inOrder(Node x) { if (x != nil) { inOrder(x.left); System.out.print(x); inOrder(x.right); } } /** * 後序遍歷 */ public void postOrder() { postOrder(root); } /** * 對以x為根的子樹進行後序遍歷 * @param x */ private void postOrder(Node x) { if (x != nil) { postOrder(x.left); postOrder(x.right); System.out.print(x); } } public static void main(String[] args) { RedBlackTree<Integer> redBlackTree = new RedBlackTree<>(); //構造一顆紅黑樹 可參考上一篇中完整的插入修復圖例 redBlackTree.insert(11); redBlackTree.insert(2); redBlackTree.insert(14); redBlackTree.insert(15); redBlackTree.insert(1); redBlackTree.insert(7); redBlackTree.insert(5); redBlackTree.insert(8); System.out.println("原紅黑樹:"); System.out.print("先序遍歷:"); redBlackTree.preOrder(); System.out.print("\n中序遍歷:"); redBlackTree.inOrder(); System.out.print("\n後序遍歷:"); redBlackTree.postOrder(); System.out.println(); //插入元素4 redBlackTree.insert(4); System.out.println("插入元素4後:"); System.out.print("先序遍歷:"); redBlackTree.preOrder(); System.out.print("\n中序遍歷:"); redBlackTree.inOrder(); System.out.print("\n後序遍歷:"); redBlackTree.postOrder(); System.out.println(); //刪除元素5 redBlackTree.delete(5); System.out.println("刪除元素5後:"); System.out.print("先序遍歷:"); redBlackTree.preOrder(); System.out.print("\n中序遍歷:"); redBlackTree.inOrder(); System.out.print("\n後序遍歷:"); redBlackTree.postOrder(); System.out.println(); } }

執行結果:

原紅黑樹:
先序遍歷: 11-BLACK  2-RED  1-BLACK  7-BLACK  5-RED  8-RED  14-BLACK  15-RED 
中序遍歷: 1-BLACK  2-RED  5-RED  7-BLACK  8-RED  11-BLACK  14-BLACK  15-RED 
後序遍歷: 1-BLACK  5-RED  8-RED  7-BLACK  2-RED  15-RED  14-BLACK  11-BLACK 
插入元素4後:
先序遍歷: 7-BLACK  2-RED  1-BLACK  5-BLACK  4-RED  11-RED  8-BLACK  14-BLACK  15-RED 
中序遍歷: 1-BLACK  2-RED  4-RED  5-BLACK  7-BLACK  8-BLACK  11-RED  14-BLACK  15-RED 
後序遍歷: 1-BLACK  4-RED  5-BLACK  2-RED  8-BLACK  15-RED  14-BLACK  11-RED  7-BLACK 
刪除元素5後:
先序遍歷: 7-BLACK  2-RED  1-BLACK  4-BLACK  11-RED  8-BLACK  14-BLACK  15-RED 
中序遍歷: 1-BLACK  2-RED  4-BLACK  7-BLACK  8-BLACK  11-RED  14-BLACK  15-RED 
後序遍歷: 1-BLACK  4-BLACK  2-RED  8-BLACK  15-RED  14-BLACK  11-RED  7-BLACK