二叉樹的java實現
public class BinaryTree { /** * 根節點 */ private static Node root; static class Node { int key; Node left, right, parent; public Node(int key) { this.key = key; } } public BinaryTree(int key) { root = new Node(key); } /** * 中序遍歷 * * @param node 根節點 */ public void inOrderTreeWalk(Node node) { if (node != null) { inOrderTreeWalk(node.left); System.out.print(node.key + ","); inOrderTreeWalk(node.right); } } /** * 查找 * * @param node 根節點 * @param key 查找值 * @return */ public Node treeSearch(Node node, int key) { while (node != null && key != node.key) { if (key < node.key) { node = node.left; } else { node = node.right; } } return node; } /** * 最小值 * * @param node 根節點 * @return */ public Node treeMinimum(Node node) { while (node.left != null) { node = node.left; } return node; } /** * 最大值 * * @param node 根節點 * @return */ public Node treeMaximum(Node node) { while (node.right != null) { node = node.right; } return node; } /** * 前驅 * * @param node 根節點 * @return */ public Node treePredecessor(Node node) { // 如果存在左子樹,返回左子樹的最大值 if (node.left != null) { return treeMaximum(node.left); } Node y = node.parent; // 當不存在左子樹時,返回最低祖先節點 while (y != null && node == y.left) { node = y; y = y.parent; } return y; } /** * 后繼 * * @param node 根節點 * @return */ public Node treeSuccessor(Node node) { // 如果存在右子樹,返回右子樹的最小值 if (node.right != null) { return treeMinimum(node.right); } Node y = node.parent; // 當不存在右子樹時,返回最低祖先節點 while (y != null && node == y.right) { node = y; y = y.parent; } return y; } /** * 插入 * * @param key 插入節點的關鍵值 */ public void treeInsert(int key) { // 創建插入節點 Node node = new Node(key); // 定義插入節點的父節點變量 Node y = null; // 定義臨時變量存根節點 Node x = root; // 在根節點的左、右子樹中查找插入位置 while (x != null) { y = x; if (key < x.key) { x = x.left; } else { x = x.right; } } node.parent = y; if (y == null) { root = node; } else if (key < y.key) { y.left = node; } else { y.right = node; } } /** * 刪除 * * @param node 刪除節點 * @return */ public Node treeDelete(Node node) { // 定義臨時變量存刪除節點或后繼節點 Node y; // 當刪除節點至多有一個孩子時 if (node.left == null || node.right == null) { y = node; } else {// 當刪除節點有兩個孩子時,y存后繼節點 y = treeSuccessor(node); } // 定義臨時變量存刪除節點的孩子節點 Node x; if (y.left != null) { x = y.left; } else { x = y.right; } if (x != null) { x.parent = y.parent; } if (y.parent == null) { root = x; } else if (y == y.parent.left) { y.parent.left = x; } else { y.parent.right = x; } // 當y為后繼節點時,將y的關鍵值賦給刪除節點 if (y != node) { node.key = y.key; } return y; } }
紅黑樹的java實現(備注:中序遍歷、查找、最大、最小、前驅、后繼與二叉樹基本一致)
public class RBTree { /** * 根節點 */ private static Node root; /** * nil節點是紅黑樹的葉子節點不同於二叉樹的葉子節點 * 顏色為黑色,key、left、right、parent可以是任意允許的值 * 這里key設置為0,left、right、parent為null */ private Node nil = new Node(true); static class Node { int key; Node left, right, parent; boolean color;// true黑,false紅 public Node(int key) { this.key = key; } public Node(boolean color) { this.color = color; } public boolean equals(Node node) { return this.key == node.key; } } public RBTree(int key) { root = new Node(key); } /** * 中序遍歷 * * @param node 根節點 */ public void inOrderTreeWalk(Node node) { if (node != null && !node.equals(nil)) { inOrderTreeWalk(node.left); System.out.print((node.color == true ? "黑" : "紅") + node.key + ","); inOrderTreeWalk(node.right); } } /** * 查找 * * @param node 根節點 * @param key 查找值 * @return */ public Node treeSearch(Node node, int key) { while (node != null && key != node.key) { if (key < node.key) { node = node.left; } else { node = node.right; } } return node; } /** * 最小值 * * @param node 根節點 * @return */ public Node treeMinimum(Node node) { while (node.left != null) { node = node.left; } return node; } /** * 最大值 * * @param node 根節點 * @return */ public Node treeMaximum(Node node) { while (node.right != null) { node = node.right; } return node; } /** * 前驅 * * @param node 根節點 * @return */ public Node treePredecessor(Node node) { // 如果存在左子樹,返回左子樹的最大值 if (node.left != null) { return treeMaximum(node.left); } Node y = node.parent; // 當不存在左子樹時,返回最低祖先節點 while (y != null && node == y.left) { node = y; y = y.parent; } return y; } /** * 后繼 * * @param node 根節點 * @return */ public Node treeSuccessor(Node node) { // 如果存在右子樹,返回右子樹的最小值 if (node.right != null) { return treeMinimum(node.right); } Node y = node.parent; // 當不存在右子樹時,返回最低祖先節點 while (y != null && node == y.right) { node = y; y = y.parent; } return y; } /** * 左旋(node節點必有右孩子) * * @param node */ public void leftTotate(Node node) { Node y = node.right; node.right = y.left; if (y.left != null) y.left.parent = node; y.parent = node.parent; if (node.parent == null) { root = y; } else if (node == node.parent.left) { node.parent.left = y; } else { node.parent.right = y; } node.parent = y; y.left = node; } /** * 右旋(node節點必有左孩子) * * @param node */ public void rightTotate(Node node) { Node y = node.left; node.left = y.right; if (y.right != null) y.right.parent = node; y.parent = node.parent; if (node.parent == null) { root = y; } else if (node == node.parent.left) { node.parent.left = y; } else { node.parent.right = y; } node.parent = y; y.right = node; } /** * 插入 * * @param key 插入節點的關鍵值 */ public void RBTreeInsert(int key) { // 創建插入節點 Node node = new Node(key); // 定義插入節點的父節點變量 Node y = null; // 定義臨時變量存根節點 Node x = root; // 在根節點的左、右子樹中查找插入位置 while (x != null) { y = x; if (key < x.key) { x = x.left; } else { x = x.right; } } node.parent = y; if (y == null) { root = node; } else if (key < y.key) { y.left = node; } else { y.right = node; } RBTreeInsertFixup(node); } /** * 插入后修復 * * @param node 插入節點 */ public void RBTreeInsertFixup(Node node) { // 當插入節點的父節點為紅色時,執行循環 while (node.parent != null && !node.parent.color && node.parent.parent != null) { // 當插入節點的父節點為其爺爺節點的左孩子時 if (node.parent == node.parent.parent.left) { // 定義y存叔叔節點 Node y = node.parent.parent.right; // 如果叔叔節點為紅色,將父節點與叔叔節點變成黑色,爺爺節點變成紅色,將插入節點升級為爺爺節點 if (y != null && !y.color) { node.parent.color = true; y.color = true; node.parent.parent.color = false; node = node.parent.parent; } else if (node == node.parent.right) {//如果叔叔節點為黑色,插入節點是父節點的右孩子,將插入節點升級為父節點,左旋插入節點 node = node.parent; leftTotate(node); } else {//如果叔叔節點為黑色,插入節點是父節點的左孩子,將父節點變成黑色,爺爺節點變成紅色,右旋爺爺節點 node.parent.color = true; node.parent.parent.color = false; rightTotate(node.parent.parent); } } else {// 當插入節點的父節點為其爺爺節點的右孩子時 // 定義y存叔叔節點 Node y = node.parent.parent.left; // 如果叔叔節點為紅色,將父節點與叔叔節點變成黑色,爺爺節點變成紅色,將插入節點升級為爺爺節點 if (y != null && !y.color) { node.parent.color = true; y.color = true; node.parent.parent.color = false; node = node.parent.parent; } else if (node == node.parent.left) {//如果叔叔節點為黑色,插入節點是父節點的左孩子,將插入節點升級為父節點,右旋插入節點 node = node.parent; rightTotate(node); } else {//如果叔叔節點為黑色,插入節點是父節點的右孩子,將父節點變成黑色,爺爺節點變成紅色,左旋爺爺節點 node.parent.color = true; node.parent.parent.color = false; leftTotate(node.parent.parent); } } } // 將根節點變成黑色 if (root.parent != null) { root = root.parent; } root.color = true; } /** * 刪除 * * @param node 刪除節點 * @return */ public Node RBTreeDelete(Node node) { // 定義臨時變量存刪除節點或后繼節點 Node y; // 當刪除節點至多有一個孩子時 if (node.left == null || node.right == null) { y = node; } else {// 當刪除節點有兩個孩子時,y存后繼節點 y = treeSuccessor(node); } // 定義臨時變量存刪除節點的孩子節點 Node x; if (y.left != null) { x = y.left; } else { x = y.right; } if (x != null) { x.parent = y.parent; } else { x = nil; x.parent = y.parent; } if (y.parent == null) { root = x; } else if (y == y.parent.left) { y.parent.left = x; } else { y.parent.right = x; } // 當y為后繼節點時,將y的關鍵值賦給刪除節點 if (y != node) { node.key = y.key; } // 當y為黑色時,需要修復紅黑樹 if (y.color) { RBTreeDeleteFixup(x); } return y; } /** * 刪除后修復 * * @param node 刪除節點的孩子節點 */ public void RBTreeDeleteFixup(Node node) { // 當node不等於根節點並且為黑色時,執行循環 while (node != root && (node == nil || node.color)) { // 如果node節點為父節點的左孩子 if (node == node.parent.left) { // 定義w存兄弟節點 Node w = node.parent.right; // 當兄弟節點為紅色時,將兄弟節點變成黑色,父節點變成紅色,左旋父節點,更新兄弟節點 if (!w.color) { w.color = true; node.parent.color = false; leftTotate(node.parent); w = node.parent.right; } else if (w.left.color && w.right.color) {//當兄弟節點為黑色且其兩個孩子都為黑色時,將兄弟節點變成紅色,將node節點升級為父節點 w.color = false; node = node.parent; } else if (w.right.color) {//當兄弟節點為黑色且其左孩子為紅色、其右孩子為黑色時,將其左孩子變成黑色、兄弟節點變成紅色,右旋兄弟節點,更新兄弟節點 w.left.color = true; w.color = false; rightTotate(w); w = node.parent.right; } else {//當兄弟節點為黑色且其右孩子為紅色時,將父節點的顏色賦給兄弟節點,父節點變成黑色,兄弟節點的右孩子變成黑色,左旋父節點 w.color = node.parent.color; node.parent.color = true; w.right.color = true; leftTotate(node.parent); // 將根節點賦給node if (root.parent != null) { root = root.parent; } node = root; } } else {// 如果node節點為父節點的右孩子 // 定義w存兄弟節點 Node w = node.parent.left; // 當兄弟節點為紅色時,將兄弟節點變成黑色,父節點變成紅色,右旋父節點,更新兄弟節點 if (!w.color) { w.color = true; node.parent.color = false; rightTotate(node.parent); w = node.parent.left; } else if (w.left.color && w.right.color) {//當兄弟節點為黑色且其兩個孩子都為黑色時,將兄弟節點變成紅色,將node節點升級為父節點 w.color = false; node = node.parent; } else if (w.left.color) {//當兄弟節點為黑色且其左孩子為黑色、其右孩子為紅色時,將其右孩子變成黑色、兄弟節點變成紅色,左旋兄弟節點,更新兄弟節點 w.right.color = true; w.color = false; leftTotate(w); w = node.parent.left; } else {//當兄弟節點為黑色且其左孩子為紅色時,將父節點的顏色賦給兄弟節點,父節點變成黑色,兄弟節點的左孩子變成黑色,右旋父節點 w.color = node.parent.color; node.parent.color = true; w.left.color = true; rightTotate(node.parent); // 將根節點賦給node if (root.parent != null) { root = root.parent; } node = root; } } } // 將node節點變成黑色 node.color = true; } public static void main(String[] args) { int[] arr = { 21, 3, 6, 7, 12, 25, 17, 8, 15 }; RBTree rb = new RBTree(21); for (int i = 1; i < arr.length; i++) { rb.RBTreeInsert(arr[i]); } rb.inOrderTreeWalk(root); rb.RBTreeDelete(rb.treeSearch(root, 21)); System.out.println(); rb.inOrderTreeWalk(root); } }