| /* |
| * Copyright (c) 2008, 2018, Oracle and/or its affiliates. All rights reserved. |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. |
| * |
| * This code is free software; you can redistribute it and/or modify it |
| * under the terms of the GNU General Public License version 2 only, as |
| * published by the Free Software Foundation. |
| * |
| * This code is distributed in the hope that it will be useful, but WITHOUT |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License |
| * version 2 for more details (a copy is included in the LICENSE file that |
| * accompanied this code). |
| * |
| * You should have received a copy of the GNU General Public License version |
| * 2 along with this work; if not, write to the Free Software Foundation, |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. |
| * |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA |
| * or visit www.oracle.com if you need additional information or have any |
| * questions. |
| */ |
| package jit.graph; |
| |
| import nsk.share.TestFailure; |
| |
| //import Node; |
| |
| // This class defines the tree object. |
| |
| public class RBTree |
| { |
| public final static int maxNodes = 70; // maximum nodes allowed. |
| public final static int INSERT = 0; // constants indicating |
| public final static int DELETE = 1; // the current operation |
| public final static int NOP = 2; |
| public final static Node treeNull = new Node(); // the tree NULL node. |
| |
| private Node root; |
| private int num_of_nodes; |
| private int height; // The tree heigth ,it is updated |
| // in each operation. |
| |
| // since the algorithem is executed in stages I have to remember data |
| // on the state. |
| private Node node; // The current operation is being done on it. |
| private int action;// The operation being performed (insert / delete) |
| private int stage; // The current stage of execution |
| |
| // the constructor initialize the object fields. |
| |
| public RBTree() |
| { |
| root = treeNull; |
| node = treeNull; |
| num_of_nodes = 0; |
| height = 0; |
| action = NOP; |
| stage = 0; |
| } |
| |
| // This method return the root of the tree. |
| |
| public Node getRoot() |
| { |
| return root; |
| } |
| |
| // This method return the number of nodes in the tree. |
| |
| public int getNodes() |
| { |
| return num_of_nodes; |
| } |
| |
| // This method return the heigth of the tree. |
| |
| public int getHeight() |
| { |
| return height; |
| } |
| |
| |
| |
| // This method inserts k into the Red Black Tree |
| |
| public boolean RBInsert(int k) |
| { |
| |
| Thread Pause = new Thread(); // this thread is used for delay |
| // between the stages. |
| if (action != NOP) // checking similar to the RB_Insert method |
| { |
| System.out.println |
| ("Only one operation can be done at a time."); |
| return false; |
| } |
| if (num_of_nodes == maxNodes) |
| { |
| System.out.println |
| ("The maximum nodes allowed is already reached."); |
| return false; |
| } |
| if (Search(k) == treeNull) // Check if there is already node with key k. |
| { |
| action = INSERT; |
| node = new Node(k); |
| node.setNode(Node.Left_son,treeNull); |
| node.setNode(Node.Right_son,treeNull); |
| node.setNode(Node.Parent,treeNull); |
| stage = 1; |
| while (stage != 0) // This is the loop that perform all the |
| { // operation steps. |
| InsertStep(); // perform one step |
| updateHeight(); // update the tree height |
| } |
| action = NOP; // set the action to NoOPretion. |
| return true; |
| } |
| else |
| System.out.println |
| ("Insertion failed. This key already exist."); |
| return false; |
| } |
| |
| |
| // This method deletes the element k from the Red Black tree |
| |
| public boolean RBDelete(int k) |
| { |
| Thread Pause = new Thread(); // this thread is used for delay |
| // between the stages. |
| if (action != NOP) |
| { // checking like in RB_Delete method |
| System.out.println |
| ("Only one operation can be done at a time."); |
| return false; |
| } |
| node = Search(k); |
| if (node != treeNull) // Check if there is a node with key k. |
| { |
| action = DELETE; |
| stage = 1; |
| while (stage != 0) // this loop perform all the operation |
| { // steps. |
| DeleteStep(); // perform one step |
| updateHeight(); // update the tree height |
| |
| } |
| action = NOP; |
| return true; |
| } |
| else |
| System.out.println |
| ("Deletion failed. This key doesn't exist."); |
| return false; |
| } |
| |
| // This method perform one step in the insertion operation. |
| // If perform a step acording to the stage variable. |
| // I will not explain exactly what each stage do, just that they |
| // divided to 4 categories: |
| // 1. inserting a node to the tree. |
| // 2. marking nodes that will be recolored. |
| // 3. recoloring nodes. |
| // 4. rotating right or left. |
| |
| private void InsertStep() |
| { |
| Node Pr,GrPr,Un; // Pr is parent, GrPr is grandparent |
| // and Un is uncle. |
| switch (stage) |
| { |
| case 1: // Inserting a node to the tree |
| /* |
| System.out.println // send a message to the screen |
| (new String("Inserting ") |
| .concat(Integer.toString(node.getKey()))); |
| */ |
| Tree_Insert(); // inserting an element to the tree |
| break; |
| case 2: // mid stage that move to algorithem to the |
| // proper next stage, and send proper message |
| // to the screen |
| Pr = node.getNode(Node.Parent); |
| GrPr = Pr.getNode(Node.Parent); |
| if (Pr == GrPr.getNode(Node.Left_son)) |
| { |
| Un = GrPr.getNode(Node.Right_son); |
| if (Un.getColor() == Node.Red) |
| { |
| stage = 3; |
| } |
| else |
| if (node == Pr.getNode(Node.Right_son)) |
| { |
| node = Pr; |
| stage = 5; |
| } |
| else |
| { |
| stage = 6; |
| } |
| } |
| else |
| { |
| Un = GrPr.getNode(Node.Left_son); |
| if (Un.getColor() == Node.Red) |
| { |
| stage = 3; |
| } |
| else |
| if (node == Pr.getNode(Node.Left_son)) |
| { |
| node = Pr; |
| stage = 5; |
| } |
| else |
| { |
| stage = 6; |
| } |
| } |
| break; |
| case 3: // This stage marks node that will be recolored |
| Pr = node.getNode(Node.Parent); |
| GrPr = Pr.getNode(Node.Parent); |
| if (Pr == GrPr.getNode(Node.Left_son)) |
| Un = GrPr.getNode(Node.Right_son); |
| else |
| Un = GrPr.getNode(Node.Left_son); |
| |
| node = GrPr; |
| stage = 4; |
| break; |
| case 4: // this stage recolor marked nodes. |
| node.setColor(Node.Red); |
| (node.getNode(Node.Left_son)).setColor(Node.Black); |
| (node.getNode(Node.Right_son)).setColor(Node.Black); |
| |
| if ((node == root) || |
| ((node.getNode(Node.Parent)).getColor() == Node.Black)) |
| if (root.getColor() == Node.Red) |
| { |
| stage = 9; |
| } |
| else |
| stage = 0; |
| else |
| { |
| stage = 2; |
| InsertStep(); |
| } |
| break; |
| case 5: // This stage perform rotation operation |
| Pr = node.getNode(Node.Parent); |
| if (node == Pr.getNode(Node.Left_son)) |
| Left_Rotate(node); |
| else |
| Right_Rotate(node); |
| |
| stage = 6; |
| break; |
| case 6: // This stage marks nodes that will be recolor. |
| Pr = node.getNode(Node.Parent); |
| GrPr = Pr.getNode(Node.Parent); |
| |
| stage = 7; |
| break; |
| case 7: // This stage recolor marked nodes. |
| Pr = node.getNode(Node.Parent); |
| Pr.setColor(Node.Black); |
| GrPr = Pr.getNode(Node.Parent); |
| GrPr.setColor(Node.Red); |
| |
| stage = 8; |
| break; |
| case 8: // This stage perform rotation operation |
| Pr = node.getNode(Node.Parent); |
| GrPr = Pr.getNode(Node.Parent); |
| if (Pr == GrPr.getNode(Node.Left_son)) |
| Right_Rotate(GrPr); |
| else |
| Left_Rotate(GrPr); |
| if (root.getColor() == Node.Red) |
| { |
| stage = 9; |
| } |
| else |
| stage = 0; |
| break; |
| case 9: // this stage mark the root. |
| stage = 10; |
| break; |
| case 10: // This stage recolor the root. |
| root.setColor(Node.Black); |
| stage = 0; |
| break; |
| } |
| } |
| |
| // This method perform one step in the deletion operation. |
| // If perform a step acording to the stage variable. |
| // I will explain exactly what each stage do, just that they |
| // divided to 4 categories: |
| // 1. deleting a node from the tree. |
| // 2. marking nodes that will be recolored. |
| // 3. recoloring nodes. |
| // 4. rotating right or left. |
| |
| public void DeleteStep() |
| { |
| Node Pr,Br; // Pr is Parent ,Br is Brother |
| switch (stage) |
| { |
| case 1: // This stage delete a node from the tree. |
| /* |
| System.out.println |
| (new String("Deleting ") |
| .concat(Integer.toString(node.getKey()))); |
| */ |
| Tree_Delete(); |
| break; |
| case 2: // This stage marks a nodes that will be recolored |
| // or perform other stage. |
| Pr = node.getNode(Node.Parent); |
| if (node == Pr.getNode(Node.Left_son)) |
| Br = Pr.getNode(Node.Right_son); |
| else |
| Br = Pr.getNode(Node.Left_son); |
| if (Br.getColor() == Node.Red) |
| { |
| stage = 3; |
| } |
| else |
| if (((Br.getNode(Node.Right_son)).getColor() == Node.Black) |
| && ((Br.getNode(Node.Left_son)).getColor() == Node.Black)) |
| { |
| stage = 5; |
| DeleteStep(); |
| } |
| else |
| { |
| stage = 7; |
| DeleteStep(); |
| } |
| break; |
| case 3: // this stage recolor marked nodes. |
| Pr = node.getNode(Node.Parent); |
| if (node == Pr.getNode(Node.Left_son)) |
| { |
| Br = Pr.getNode(Node.Right_son); |
| |
| } |
| else |
| { |
| Br = Pr.getNode(Node.Left_son); |
| } |
| Br.setColor(Node.Black); |
| Pr.setColor(Node.Red); |
| |
| stage = 4; |
| break; |
| case 4: // this stage perform rotation operation |
| Pr = node.getNode(Node.Parent); |
| if (node == Pr.getNode(Node.Left_son)) |
| { |
| Left_Rotate(Pr); |
| Br = Pr.getNode(Node.Right_son); |
| } |
| else |
| { |
| Right_Rotate(Pr); |
| Br = Pr.getNode(Node.Left_son); |
| } |
| if (((Br.getNode(Node.Right_son)).getColor() == Node.Black) |
| && ((Br.getNode(Node.Left_son)).getColor() == Node.Black)) |
| stage = 5; |
| else |
| stage = 7; |
| |
| break; |
| case 5: // this stage marks nodes that will be recolor. |
| Pr = node.getNode(Node.Parent); |
| if (node == Pr.getNode(Node.Left_son)) |
| Br = Pr.getNode(Node.Right_son); |
| else |
| Br = Pr.getNode(Node.Left_son); |
| |
| stage = 6; |
| break; |
| case 6: // This stage recolor marked nodes. |
| Pr = node.getNode(Node.Parent); |
| if (node == Pr.getNode(Node.Left_son)) |
| Br = Pr.getNode(Node.Right_son); |
| else |
| Br = Pr.getNode(Node.Left_son); |
| Br.setColor(Node.Red); |
| node = Pr; |
| |
| if ((node != root) && (node.getColor() == Node.Black)) |
| stage = 2; |
| else |
| if (node.getColor() == Node.Red) |
| { |
| stage = 13; |
| } |
| else |
| stage = 0; |
| break; |
| case 7: // this stage marks nodes that will be recolor |
| // or perform other stage. |
| Pr = node.getNode(Node.Parent); |
| if (node == Pr.getNode(Node.Left_son)) |
| { |
| Br = Pr.getNode(Node.Right_son); |
| if ((Br.getNode(Node.Right_son)).getColor() == Node.Black) |
| { |
| stage = 8; |
| } |
| else |
| { |
| stage = 10; |
| DeleteStep(); |
| } |
| } |
| else |
| { |
| Br = Pr.getNode(Node.Left_son); |
| if ((Br.getNode(Node.Left_son)).getColor() == Node.Black) |
| { |
| stage = 8; |
| } |
| else |
| { |
| stage = 10; |
| DeleteStep(); |
| } |
| } |
| break; |
| case 8: // this stage recolor marked nodes. |
| Pr = node.getNode(Node.Parent); |
| if (node == Pr.getNode(Node.Left_son)) |
| { |
| Br = Pr.getNode(Node.Right_son); |
| (Br.getNode(Node.Left_son)).setColor(Node.Black); |
| |
| } |
| else |
| { |
| Br = Pr.getNode(Node.Left_son); |
| (Br.getNode(Node.Right_son)).setColor(Node.Black); |
| |
| } |
| Br.setColor(Node.Red); |
| stage = 9; |
| break; |
| case 9: // this stage perform rotation operation |
| Pr = node.getNode(Node.Parent); |
| if (node == Pr.getNode(Node.Left_son)) |
| { |
| Br = Pr.getNode(Node.Right_son); |
| Right_Rotate(Br); |
| } |
| else |
| { |
| Br = Pr.getNode(Node.Left_son); |
| Left_Rotate(Br); |
| } |
| |
| stage = 10; |
| break; |
| case 10: // This stage marks node that will be recolor. |
| |
| Pr = node.getNode(Node.Parent); |
| if (node == Pr.getNode(Node.Left_son)) |
| { |
| Br = Pr.getNode(Node.Right_son); |
| } |
| else |
| { |
| Br = Pr.getNode(Node.Left_son); |
| } |
| |
| stage = 11; |
| break; |
| case 11: // this stage recolor marked nodes. |
| Pr = node.getNode(Node.Parent); |
| if (node == Pr.getNode(Node.Left_son)) |
| { |
| Br = Pr.getNode(Node.Right_son); |
| (Br.getNode(Node.Right_son)).setColor(Node.Black); |
| } |
| else |
| { |
| Br = Pr.getNode(Node.Left_son); |
| (Br.getNode(Node.Left_son)).setColor(Node.Black); |
| |
| } |
| if (Br.getColor() != Pr.getColor()) |
| Br.setColor(Pr.getColor()); |
| if (Pr.getColor() != Node.Black) |
| Pr.setColor(Node.Black); |
| |
| stage = 12; |
| break; |
| case 12: // this stage perform rotation operation. |
| Pr = node.getNode(Node.Parent); |
| if (node == Pr.getNode(Node.Left_son)) |
| Left_Rotate(Pr); |
| else |
| Right_Rotate(Pr); |
| node = root; |
| if (node.getColor() == Node.Red) |
| { |
| stage = 13; |
| } |
| else |
| stage = 0; |
| break; |
| case 13: // this stage marks a node that will be recolor |
| stage = 14; |
| break; |
| case 14: // this stage recolor marked node. |
| node.setColor(Node.Black); |
| stage = 0; |
| break; |
| } |
| } |
| |
| // This method insert the node 'node' to the tree. |
| // it called from the first stage in the InsertStep method. |
| // we 'dive' from the root to a leaf acording to the node key |
| // and insert the node in the proper place. |
| |
| private void Tree_Insert() |
| { |
| Node n1,n2; |
| n1 = root; |
| n2 = treeNull; |
| while (n1 != treeNull) |
| { |
| n2 = n1; |
| if (node.getKey() < n1.getKey()) |
| n1 = n1.getNode(Node.Left_son); |
| else |
| n1 = n1.getNode(Node.Right_son); |
| } |
| node.setNode(Node.Parent,n2); |
| if (n2 == treeNull) |
| root = node; |
| else |
| { |
| if (node.getKey() < n2.getKey()) |
| n2.setNode(Node.Left_son,node); |
| else |
| n2.setNode(Node.Right_son,node); |
| } |
| //Parent.display.drawTree(); |
| // updating the insertion stage. |
| if ((node == root) || |
| ((node.getNode(Node.Parent)).getColor() == Node.Black)) |
| if (root.getColor() == Node.Red) |
| { |
| stage = 9; |
| } |
| else |
| stage = 0; |
| else |
| { |
| stage = 2; |
| InsertStep(); |
| } |
| num_of_nodes++; // increasing the number of nodes |
| } |
| |
| // This method delete the node 'node' from the tree. |
| // it called from the first stage in the DeleteStep method. |
| // if node has at most one son we just remove it and connect |
| // his son and parent. If it has 2 sons we delete his successor |
| // that has at most one son and replace him with the successor. |
| |
| private void Tree_Delete() |
| { |
| Node n1,n2,n3; |
| if ((node.getNode(Node.Left_son) == treeNull) || |
| (node.getNode(Node.Right_son) == treeNull)) |
| n1 = node; |
| else |
| n1 = Tree_Successor(node); |
| if (n1.getNode(node.Left_son) != treeNull) |
| n2 = n1.getNode(Node.Left_son); |
| else |
| n2 = n1.getNode(Node.Right_son); |
| |
| n3 = n1.getNode(Node.Parent); |
| n2.setNode(Node.Parent,n3); |
| if (n3 == treeNull) |
| root = n2; |
| else |
| if (n1 == n3.getNode(Node.Left_son)) |
| n3.setNode(Node.Left_son,n2); |
| else |
| n3.setNode(Node.Right_son,n2); |
| |
| if (n1 != node) |
| { |
| node.setKey(n1.getKey()); |
| } |
| |
| |
| node = n2; |
| if (n1.getColor() == Node.Black) |
| if ((node != root) && (node.getColor() == Node.Black)) |
| stage = 2; |
| else |
| if (node.getColor() == Node.Red) |
| stage = 13; |
| else |
| stage = 0; |
| else |
| stage = 0; |
| num_of_nodes--; // decrease the number of nodes. |
| } |
| |
| // This method return the successor of the node n in the tree. |
| |
| private Node Tree_Successor(Node n) |
| { |
| Node n1; |
| if (n.getNode(Node.Right_son) != treeNull) |
| { |
| n = n.getNode(Node.Right_son); |
| while (n.getNode(Node.Left_son) != treeNull) |
| n = n.getNode(Node.Left_son); |
| return n; |
| } |
| n1 = n.getNode(Node.Parent); |
| while ((n1 != treeNull) && (n == n1.getNode(Node.Right_son))) |
| { |
| n = n1; |
| n1 = n1.getNode(Node.Parent); |
| } |
| return n1; |
| } |
| |
| // This method perform Left Rotation with n1. |
| |
| private void Left_Rotate(Node n1) |
| { |
| Node n2; |
| |
| n2 = n1.getNode(Node.Right_son); |
| n1.setNode(Node.Right_son,n2.getNode(Node.Left_son)); |
| if (n2.getNode(Node.Left_son) != treeNull) |
| (n2.getNode(Node.Left_son)).setNode(Node.Parent,n1); |
| n2.setNode(Node.Parent,n1.getNode(Node.Parent)); |
| if (n1.getNode(Node.Parent) == treeNull) |
| root = n2; |
| else |
| if (n1 == (n1.getNode(Node.Parent)).getNode(Node.Left_son)) |
| (n1.getNode(Node.Parent)).setNode(Node.Left_son,n2); |
| else |
| (n1.getNode(Node.Parent)).setNode(Node.Right_son,n2); |
| n2.setNode(Node.Left_son,n1); |
| n1.setNode(Node.Parent,n2); |
| } |
| |
| // This method perform Right Rotation with n1. |
| |
| private void Right_Rotate(Node n1) |
| { |
| Node n2; |
| |
| n2 = n1.getNode(Node.Left_son); |
| n1.setNode(Node.Left_son,n2.getNode(Node.Right_son)); |
| if (n2.getNode(Node.Right_son) != treeNull) |
| (n2.getNode(Node.Right_son)).setNode(Node.Parent,n1); |
| n2.setNode(Node.Parent,n1.getNode(Node.Parent)); |
| if (n1.getNode(Node.Parent) == treeNull) |
| root = n2; |
| else |
| if (n1 == (n1.getNode(Node.Parent)).getNode(Node.Left_son)) |
| (n1.getNode(Node.Parent)).setNode(Node.Left_son,n2); |
| else |
| (n1.getNode(Node.Parent)).setNode(Node.Right_son,n2); |
| n2.setNode(Node.Right_son,n1); |
| n1.setNode(Node.Parent,n2); |
| } |
| |
| // This method search the tree for a node with key 'key', and |
| // return the node on success otherwise treeNull. |
| |
| public Node Search(int key) |
| { |
| Node node; |
| node = root; |
| while ((node != treeNull) && (key != node.getKey())) |
| if (key < node.getKey()) |
| node = node.getNode(Node.Left_son); |
| else |
| node = node.getNode(Node.Right_son); |
| return node; |
| } |
| |
| // This method update the tree height it uses a recursive method |
| // findheight. |
| |
| private void updateHeight() |
| { |
| height = 0; |
| if (root != treeNull) |
| findHeight(root,1); |
| } |
| |
| // This is a recursive method that find a node height. |
| |
| private void findHeight(Node n,int curr) |
| { |
| if (height < curr) |
| height = curr; |
| if (n.getNode(Node.Left_son) != treeNull) |
| findHeight(n.getNode(Node.Left_son),curr+1); |
| if (n.getNode(Node.Right_son) != treeNull) |
| findHeight(n.getNode(Node.Right_son),curr+1); |
| } |
| |
| } |