java實現紅黑樹

紅黑樹是一種經典的數據結構,在linux內存管理、nginx 等很多地方用到它。主要操作包括插入、刪除,其中插入6種情況,刪除8種情況,詳細的思路就不說了,如果不太明白的請參考算法導論13章,看的時候一定要把每一種插入、刪除的情況在紙上自己畫出來,這樣會節省你很多時間。下面是java實現的代碼:


[java] view plaincopy
  1. package com.algorithm.rbtree;  
  2.   
  3. public class RBTree {  
  4.       
  5.     private final Node NIL = new Node(null,null,null,Color.BLACK,-1);  
  6.     private Node root;  
  7.       
  8.     public RBTree() {  
  9.         root = NIL;  
  10.     }  
  11.       
  12.     public RBTree(Node  root) {  
  13.         this.root = root;  
  14.     }  
  15.       
  16.       
  17.       
  18.       
  19.       
  20.     //插入節點  
  21.     public void rbInsert(Node node) {  
  22.           
  23.         Node previous = NIL;  
  24.         Node temp = root;  
  25.           
  26.         while (temp != NIL) {  
  27.             previous = temp;  
  28.             if (temp.getValue() < node.getValue()) {  
  29.                 temp = temp.getRight();  
  30.             } else {  
  31.                 temp = temp.getLeft();  
  32.             }  
  33.         }  
  34.         node.setParent(previous);  
  35.           
  36.         if (previous == NIL) {  
  37.             root = node;  
  38.             root.setParent(NIL);  
  39.         } else  if (previous.getValue() > node.getValue()) {  
  40.             previous.setLeft(node);  
  41.         } else {  
  42.             previous.setRight(node);  
  43.         }  
  44.           
  45.         node.setLeft(NIL);  
  46.         node.setRight(NIL);  
  47.         node.setColor(Color.RED);  
  48.         rb_Insert_Fixup(node);  
  49.           
  50.     }  
  51.       
  52.     //插入節點後的調整  
  53.     private void rb_Insert_Fixup(Node node) {  
  54.       
  55.         while (node.getParent().getColor() == Color.RED) {  
  56.               
  57.             if (node.getParent() == node.getParent().getParent().getLeft()) {  
  58.                   
  59.                 Node rightNuncle = node.getParent().getParent().getRight();  
  60.                   
  61.                 if (rightNuncle.getColor() == Color.RED) {         //Case 1  
  62.                       
  63.                     rightNuncle.setColor(Color.BLACK);  
  64.                     node.getParent().setColor(Color.BLACK);  
  65.                     node.getParent().getParent().setColor(Color.RED);  
  66.                     node = node.getParent().getParent();  
  67.                                           
  68.                 } else if (node == node.getParent().getRight()) {  //case 2  
  69.                       
  70.                     node = node.getParent();  
  71.                     leftRotate(node);  
  72.                       
  73.                 } else {                                          //case 3  
  74.                       
  75.                     node.getParent().setColor(Color.BLACK);  
  76.                     node.getParent().getParent().setColor(Color.RED);  
  77.                       
  78.                     rightRotate(node.getParent().getParent());  
  79.                       
  80.                 }  
  81.                                   
  82.             } else {  
  83.                   
  84.                 Node leftNuncle = node.getParent().getParent().getLeft();  
  85.                   
  86.                 if (leftNuncle.getColor() == Color.RED) {     //case 4  
  87.                       
  88.                     leftNuncle.setColor(Color.BLACK);  
  89.                     node.getParent().setColor(Color.BLACK);  
  90.                     node.getParent().getParent().setColor(Color.RED);  
  91.                     node = node.getParent().getParent();  
  92.                   
  93.                 } else if (node == node.getParent().getLeft()) { //case 5  
  94.                   
  95.                     node = node.getParent();  
  96.                     rightRotate(node);  
  97.                                           
  98.                 } else {                                          // case 6  
  99.                       
  100.                     node.getParent().setColor(Color.BLACK);  
  101.                     node.getParent().getParent().setColor(Color.RED);  
  102.                     leftRotate(node.getParent().getParent());  
  103.                               
  104.                 }  
  105.                                   
  106.             }  
  107.               
  108.               
  109.         }  
  110.           
  111.         root.setColor(Color.BLACK);  
  112.           
  113.     }  
  114.       
  115.       
  116.     //刪除節點  
  117.     public Node rbDelete(int data) {  
  118.           
  119.         Node node = search(data);  
  120.         Node temp = NIL;  
  121.         Node child = NIL;  
  122.         if (node == null) {  
  123.             return null;  
  124.         } else {  
  125.             if (node.getLeft() == NIL || node.getRight() == NIL) {  
  126.                 temp = node;              
  127.             } else {  
  128.                 temp = successor(node);  
  129.             }  
  130.               
  131.             if (temp.getLeft() != NIL) {  
  132.                 child = temp.getLeft();  
  133.             } else {  
  134.                 child = temp.getRight();  
  135.             }  
  136.               
  137.             child.setParent(temp.getParent());  
  138.               
  139.             if (temp.getParent() == NIL) {  
  140.                 root = child;  
  141.             } else if (temp == temp.getParent().getLeft()) {  
  142.                 temp.getParent().setLeft(child);  
  143.             } else {  
  144.                 temp.getParent().setRight(child);  
  145.             }  
  146.               
  147.             if (temp != node) {  
  148.                 node.setValue(temp.getValue());  
  149.             }  
  150.               
  151.             if (temp.getColor() == Color.BLACK) {  
  152.                 rb_Delete_Fixup(child);  
  153.             }  
  154.             return temp;  
  155.         }  
  156.           
  157.           
  158.           
  159.           
  160.     }  
  161.       
  162.     //刪除節點後的調整  
  163.     private void rb_Delete_Fixup(Node node) {  
  164.           
  165.         while (node != root && node.getColor() == Color.BLACK) {  
  166.               
  167.             if (node == node.getParent().getLeft()) {  
  168.                   
  169.                 Node rightBrother = node.getParent().getRight();  
  170.                 if (rightBrother.getColor() == Color.RED) {          //case 1 node節點爲左孩子,node節點的兄弟爲RED  
  171.                     rightBrother.setColor(Color.BLACK);  
  172.                     node.getParent().setColor(Color.RED);  
  173.                     leftRotate(node.getParent());  
  174.                     rightBrother = node.getParent().getRight();  
  175.                 }  
  176.                   
  177.                 if (rightBrother.getLeft().getColor() == Color.BLACK && rightBrother.getRight().getColor() == Color.BLACK) {  
  178.                     rightBrother.setColor(Color.RED);  
  179.                     node = node.getParent();  
  180.                 } else if (rightBrother.getRight().getColor() == Color.BLACK) {  
  181.                     rightBrother.getLeft().setColor(Color.BLACK);  
  182.                     rightBrother.setColor(Color.RED);  
  183.                     rightRotate(rightBrother);  
  184.                     rightBrother = node.getParent().getRight();  
  185.                 } else {  
  186.                     rightBrother.setColor(node.getParent().getColor());  
  187.                     node.getParent().setColor(Color.BLACK);  
  188.                     rightBrother.getRight().setColor(Color.BLACK);  
  189.                     leftRotate(node.getParent());  
  190.                     node = root;  
  191.                 }  
  192.                   
  193.                   
  194.             } else {  
  195.                   
  196.                 Node leftBrother = node.getParent().getLeft();  
  197.                 if (leftBrother.getColor() == Color.RED) {  
  198.                     leftBrother.setColor(Color.BLACK);  
  199.                     node.getParent().setColor(Color.RED);  
  200.                     rightRotate(node.getParent());  
  201.                     leftBrother = node.getParent().getLeft();  
  202.                 }   
  203.                   
  204.                 if (leftBrother.getLeft().getColor() == Color.BLACK && leftBrother.getRight().getColor() == Color.BLACK) {  
  205.                     leftBrother.setColor(Color.RED);  
  206.                     node = node.getParent();  
  207.                                                       
  208.                 } else if (leftBrother.getLeft().getColor() == Color.BLACK) {  
  209.                       
  210.                     leftBrother.setColor(Color.RED);  
  211.                     leftBrother.getRight().setColor(Color.BLACK);  
  212.                     leftRotate(leftBrother);  
  213.                     leftBrother = node.getParent().getLeft();  
  214.                       
  215.                 } else {  
  216.                       
  217.                     leftBrother.setColor(node.getParent().getColor());  
  218.                     node.getParent().setColor(Color.BLACK);  
  219.                     leftBrother.getLeft().setColor(Color.BLACK);  
  220.                     rightRotate(node.getParent());  
  221.                     node = root;  
  222.                                                               
  223.                 }  
  224.                                   
  225.             }  
  226.                       
  227.         }  
  228.               
  229.         node.setColor(Color.BLACK);  
  230.     }  
  231.       
  232.       
  233.     //查找節點node的後繼節點  
  234.   
  235.     public Node successor(Node node) {  
  236.           
  237.         Node rightChild = node.getRight();  
  238.         if  (rightChild != NIL) {  
  239.             Node previous = null;  
  240.             while (rightChild != NIL) {  
  241.                 previous = rightChild;  
  242.                 rightChild = rightChild.getLeft();  
  243.             }  
  244.             return previous;  
  245.         } else {  
  246.               
  247.             Node parent = node.getParent();  
  248.             while (parent != NIL && node != parent.getLeft()) {  
  249.                 node = parent;  
  250.                 parent = parent.getParent();  
  251.             }  
  252.               
  253.             return parent;  
  254.                           
  255.         }  
  256.   
  257.     }  
  258.       
  259.       
  260.     //查找節點  
  261.     public Node search(int data) {  
  262.         Node temp = root;  
  263.           
  264.         while (temp != NIL) {  
  265.             if (temp.getValue() == data) {  
  266.                 return temp;  
  267.             } else  if (data < temp.getValue()) {  
  268.                 temp = temp.getLeft();  
  269.             } else {  
  270.                 temp = temp.getRight();  
  271.             }  
  272.         }  
  273.         return null;  
  274.     }  
  275.       
  276.       
  277.       
  278.       
  279.     //左轉函數  
  280.     private void leftRotate(Node node) {  
  281.           
  282.         Node rightNode = node.getRight();  
  283.           
  284.         node.setRight(rightNode.getLeft());  
  285.         if (rightNode.getLeft() != NIL) {  
  286.             rightNode.getLeft().setParent(node);  
  287.         }  
  288.         rightNode.setParent(node.getParent());  
  289.           
  290.         if (node.getParent() == NIL) {  
  291.             rightNode = root;  
  292.         } else if (node == node.getParent().getLeft()) {  
  293.             node.getParent().setLeft(rightNode);  
  294.         } else {  
  295.             node.getParent().setRight(rightNode);  
  296.         }  
  297.           
  298.         rightNode.setLeft(node);  
  299.         node.setParent(rightNode);  
  300.           
  301.           
  302.     }  
  303.       
  304.     //右轉函數  
  305.     private void rightRotate(Node node) {  
  306.           
  307.         Node leftNode = node.getLeft();  
  308.         node.setLeft(leftNode.getRight());  
  309.           
  310.         if (leftNode.getRight() != null) {  
  311.             leftNode.getRight().setParent(node);  
  312.         }  
  313.           
  314.         leftNode.setParent(node.getParent());  
  315.           
  316.         if (node.getParent() == NIL) {  
  317.             root = leftNode;  
  318.         } else if (node == node.getParent().getLeft()) {  
  319.             node.getParent().setLeft(leftNode);  
  320.         } else {  
  321.             node.getParent().setRight(leftNode);  
  322.         }  
  323.           
  324.         leftNode.setRight(node);  
  325.         node.setParent(leftNode);  
  326.                       
  327.     }  
  328.       
  329.     //中序遍歷紅黑樹  
  330.     public void printTree() {  
  331.         inOrderTraverse(root);  
  332.     }  
  333.       
  334.     private void inOrderTraverse(Node node) {  
  335.           
  336.         if (node != NIL) {  
  337.             inOrderTraverse(node.getLeft());  
  338.             System.out.println(" 節點:"+node.getValue() + "的顏色爲:" + node.getColor());  
  339.             inOrderTraverse(node.getRight());  
  340.         }  
  341.           
  342.     }  
  343.       
  344.       
  345.     public Node getNIL() {  
  346.         return NIL;  
  347.     }  
  348.   
  349. }  
  350.   
  351.   
  352.   
  353. class Node {  
  354.     private Node left;  
  355.     private Node right;  
  356.     private Node parent;  
  357.     private Color color;  
  358.     private int value;  
  359.     public Node(Node left, Node right, Node parent, Color color, int value) {  
  360.         super();  
  361.         this.left = left;  
  362.         this.right = right;  
  363.         this.parent = parent;  
  364.         this.color = color;  
  365.         this.value = value;  
  366.     }  
  367.       
  368.     public Node() {  
  369.     }  
  370.       
  371.     public Node(int value) {  
  372.         this(null,null,null,null,value);  
  373.     }  
  374.   
  375.     public Node getLeft() {  
  376.         return left;  
  377.     }  
  378.   
  379.     public void setLeft(Node left) {  
  380.         this.left = left;  
  381.     }  
  382.   
  383.     public Node getRight() {  
  384.         return right;  
  385.     }  
  386.   
  387.     public void setRight(Node right) {  
  388.         this.right = right;  
  389.     }  
  390.   
  391.     public Node getParent() {  
  392.         return parent;  
  393.     }  
  394.   
  395.     public void setParent(Node parent) {  
  396.         this.parent = parent;  
  397.     }  
  398.   
  399.     public Color getColor() {  
  400.         return color;  
  401.     }  
  402.   
  403.     public void setColor(Color color) {  
  404.         this.color = color;  
  405.     }  
  406.   
  407.     public int getValue() {  
  408.         return value;  
  409.     }  
  410.   
  411.     public void setValue(int value) {  
  412.         this.value = value;  
  413.     }  
  414.       
  415. }  
  416.   
  417. enum Color {  
  418.     RED,BLACK  
  419. }  


下面是測試代碼:


[html] view plaincopy
  1. package com.algorithm.rbtree;  
  2.   
  3. public class RBTreeTest {  
  4.   
  5.     /**  
  6.      * @param args  
  7.      */  
  8.     public static void main(String[] args) {  
  9.           
  10.         RBTree rbTree = new RBTree();  
  11.           
  12.         rbTree.rbInsert(new Node(41));  
  13.         rbTree.rbInsert(new Node(38));  
  14.         rbTree.rbInsert(new Node(31));  
  15.         rbTree.rbInsert(new Node(12));  
  16.         rbTree.rbInsert(new Node(19));  
  17.         rbTree.rbInsert(new Node(8));  
  18.           
  19.         //rbTree.printTree();  
  20.           
  21.           
  22.         rbTree.rbDelete(19);  
  23.           
  24.         rbTree.printTree();  
  25.           
  26.   
  27.     }  
  28.   
  29. }  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章