Path: blob/master/test/hotspot/jtreg/vmTestbase/jit/graph/RBTree.java
40948 views
/*1* Copyright (c) 2008, 2019, Oracle and/or its affiliates. All rights reserved.2* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.3*4* This code is free software; you can redistribute it and/or modify it5* under the terms of the GNU General Public License version 2 only, as6* published by the Free Software Foundation.7*8* This code is distributed in the hope that it will be useful, but WITHOUT9* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or10* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License11* version 2 for more details (a copy is included in the LICENSE file that12* accompanied this code).13*14* You should have received a copy of the GNU General Public License version15* 2 along with this work; if not, write to the Free Software Foundation,16* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.17*18* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA19* or visit www.oracle.com if you need additional information or have any20* questions.21*/2223package jit.graph;2425// This class defines the tree object.26public class RBTree {27public final static int maxNodes = 70; // maximum nodes allowed.28public final static int INSERT = 0; // constants indicating29public final static int DELETE = 1; // the current operation30public final static int NOP = 2;31public final static Node treeNull = new Node(); // the tree NULL node.3233private Node root;34private int num_of_nodes;35private int height; // The tree height, it is updated36// in each operation.3738// since the algorithm is executed in stages I have to remember data39// on the state.40private Node node; // The current operation is being done on it.41private int action; // The operation being performed (insert / delete)42private int stage; // The current stage of execution4344// the constructor initializes the object fields.45public RBTree() {46root = treeNull;47node = treeNull;48num_of_nodes = 0;49height = 0;50action = NOP;51stage = 0;52}5354// This method returns the root of the tree.55public Node getRoot() {56return root;57}5859// This method returns the number of nodes in the tree.60public int getNodes() {61return num_of_nodes;62}6364// This method returns the height of the tree.65public int getHeight() {66return height;67}686970// This method inserts k into the Red Black Tree71public boolean RBInsert(int k) {72// checking similar to the RB_Insert method73if (action != NOP) {74System.out.println("Only one operation can be done at a time.");75return false;76}7778if (num_of_nodes == maxNodes) {79System.out.println("The maximum nodes allowed is already reached.");80return false;81}8283// Check if there is already node with key k.84if (Search(k) == treeNull) {85action = INSERT;86node = new Node(k);87node.setNode(Node.Left_son, treeNull);88node.setNode(Node.Right_son, treeNull);89node.setNode(Node.Parent, treeNull);90stage = 1;91// This is the loop that perform all the operation steps.92while (stage != 0) {93// perform one step94InsertStep();95// update the tree height96updateHeight();97}98// set the action to NoOPretion.99action = NOP;100return true;101} else102System.out.println("Insertion failed. This key already exist.");103return false;104}105106107// This method deletes the element k from the Red Black tree108public boolean RBDelete(int k) {109// checking like in RB_Delete method110if (action != NOP) {111System.out.println("Only one operation can be done at a time.");112return false;113}114node = Search(k);115// Check if there is a node with key k.116if (node != treeNull) {117action = DELETE;118stage = 1;119// this loop perform all the operation steps.120while (stage != 0) {121// perform one step122DeleteStep();123// update the tree height124updateHeight();125}126action = NOP;127return true;128} else129System.out.println("Deletion failed. This key doesn't exist.");130return false;131}132133// This method performs one step in the insertion operation.134// It performs a step according to the stage variable.135// I will not explain exactly what each stage do, just that they136// divided to 4 categories:137// 1. inserting a node to the tree.138// 2. marking nodes that will be recolored.139// 3. recoloring nodes.140// 4. rotating right or left.141private void InsertStep() {142// Pr is parent, GrPr is grandparent and Un is uncle.143Node Pr, GrPr, Un;144switch (stage) {145// Inserting a node to the tree146case 1:147Tree_Insert();148break;149// mid stage that moves the algorithm to the proper next stage150case 2:151Pr = node.getNode(Node.Parent);152GrPr = Pr.getNode(Node.Parent);153if (Pr == GrPr.getNode(Node.Left_son)) {154Un = GrPr.getNode(Node.Right_son);155if (Un.getColor() == Node.Red) {156stage = 3;157} else if (node == Pr.getNode(Node.Right_son)) {158node = Pr;159stage = 5;160} else {161stage = 6;162}163} else {164Un = GrPr.getNode(Node.Left_son);165if (Un.getColor() == Node.Red) {166stage = 3;167} else if (node == Pr.getNode(Node.Left_son)) {168node = Pr;169stage = 5;170} else {171stage = 6;172}173}174break;175// This stage marks node that will be recolored176case 3:177Pr = node.getNode(Node.Parent);178GrPr = Pr.getNode(Node.Parent);179if (Pr == GrPr.getNode(Node.Left_son)) {180Un = GrPr.getNode(Node.Right_son);181} else {182Un = GrPr.getNode(Node.Left_son);183}184node = GrPr;185stage = 4;186break;187// This stage recolors marked nodes.188case 4:189node.setColor(Node.Red);190node.getNode(Node.Left_son).setColor(Node.Black);191node.getNode(Node.Right_son).setColor(Node.Black);192193if ((node == root) ||194(node.getNode(Node.Parent).getColor() == Node.Black)) {195if (root.getColor() == Node.Red) {196stage = 9;197} else198stage = 0;199} else {200stage = 2;201InsertStep();202}203break;204// This stage performs rotation operation205case 5:206Pr = node.getNode(Node.Parent);207if (node == Pr.getNode(Node.Left_son)) {208Left_Rotate(node);209} else {210Right_Rotate(node);211}212stage = 6;213break;214// This stage marks nodes that will be recolor.215case 6:216Pr = node.getNode(Node.Parent);217GrPr = Pr.getNode(Node.Parent);218219stage = 7;220break;221// This stage recolors marked nodes.222case 7:223Pr = node.getNode(Node.Parent);224Pr.setColor(Node.Black);225GrPr = Pr.getNode(Node.Parent);226GrPr.setColor(Node.Red);227228stage = 8;229break;230// This stage performs rotation operation231case 8:232Pr = node.getNode(Node.Parent);233GrPr = Pr.getNode(Node.Parent);234if (Pr == GrPr.getNode(Node.Left_son)) {235Right_Rotate(GrPr);236} else {237Left_Rotate(GrPr);238}239if (root.getColor() == Node.Red) {240stage = 9;241} else242stage = 0;243break;244// this stage marks the root.245case 9:246stage = 10;247break;248// This stage recolors the root.249case 10:250root.setColor(Node.Black);251stage = 0;252break;253}254}255256// This method performs one step in the deletion operation.257// It perform sa step according to the stage variable.258// I will explain exactly what each stage do, just that they259// divided to 4 categories:260// 1. deleting a node from the tree.261// 2. marking nodes that will be recolored.262// 3. recoloring nodes.263// 4. rotating right or left.264public void DeleteStep() {265// Pr is Parent, Br is Brother266Node Pr, Br;267switch (stage) {268// This stage delete a node from the tree.269case 1:270Tree_Delete();271break;272// This stage marks a nodes that will be recolored or perform other stage.273case 2:274Pr = node.getNode(Node.Parent);275if (node == Pr.getNode(Node.Left_son)) {276Br = Pr.getNode(Node.Right_son);277} else {278Br = Pr.getNode(Node.Left_son);279}280if (Br.getColor() == Node.Red) {281stage = 3;282} else if ((Br.getNode(Node.Right_son).getColor() == Node.Black)283&& (Br.getNode(Node.Left_son).getColor() == Node.Black)) {284stage = 5;285DeleteStep();286} else {287stage = 7;288DeleteStep();289}290break;291// This stage recolors marked nodes.292case 3:293Pr = node.getNode(Node.Parent);294if (node == Pr.getNode(Node.Left_son)) {295Br = Pr.getNode(Node.Right_son);296} else {297Br = Pr.getNode(Node.Left_son);298}299Br.setColor(Node.Black);300Pr.setColor(Node.Red);301302stage = 4;303break;304// This stage performs rotation operation305case 4:306Pr = node.getNode(Node.Parent);307if (node == Pr.getNode(Node.Left_son)) {308Left_Rotate(Pr);309Br = Pr.getNode(Node.Right_son);310} else {311Right_Rotate(Pr);312Br = Pr.getNode(Node.Left_son);313}314if ((Br.getNode(Node.Right_son).getColor() == Node.Black)315&& (Br.getNode(Node.Left_son).getColor() == Node.Black)) {316stage = 5;317} else {318stage = 7;319}320321break;322// This stage marks nodes that will be recolor.323case 5:324Pr = node.getNode(Node.Parent);325if (node == Pr.getNode(Node.Left_son)) {326Br = Pr.getNode(Node.Right_son);327} else {328Br = Pr.getNode(Node.Left_son);329}330stage = 6;331break;332// This stage recolors marked nodes.333case 6:334Pr = node.getNode(Node.Parent);335if (node == Pr.getNode(Node.Left_son)) {336Br = Pr.getNode(Node.Right_son);337} else {338Br = Pr.getNode(Node.Left_son);339}340Br.setColor(Node.Red);341node = Pr;342343if ((node != root) && (node.getColor() == Node.Black)) {344stage = 2;345} else if (node.getColor() == Node.Red) {346stage = 13;347} else348stage = 0;349break;350// This stage marks nodes that will be recolor or perform other stage.351case 7:352Pr = node.getNode(Node.Parent);353if (node == Pr.getNode(Node.Left_son)) {354Br = Pr.getNode(Node.Right_son);355if ((Br.getNode(Node.Right_son)).getColor() == Node.Black) {356stage = 8;357} else {358stage = 10;359DeleteStep();360}361} else {362Br = Pr.getNode(Node.Left_son);363if ((Br.getNode(Node.Left_son)).getColor() == Node.Black) {364stage = 8;365} else {366stage = 10;367DeleteStep();368}369}370break;371// This stage recolors marked nodes.372case 8:373Pr = node.getNode(Node.Parent);374if (node == Pr.getNode(Node.Left_son)) {375Br = Pr.getNode(Node.Right_son);376Br.getNode(Node.Left_son).setColor(Node.Black);377} else {378Br = Pr.getNode(Node.Left_son);379Br.getNode(Node.Right_son).setColor(Node.Black);380}381Br.setColor(Node.Red);382stage = 9;383break;384// This stage performs rotation operation385case 9:386Pr = node.getNode(Node.Parent);387if (node == Pr.getNode(Node.Left_son)) {388Br = Pr.getNode(Node.Right_son);389Right_Rotate(Br);390} else {391Br = Pr.getNode(Node.Left_son);392Left_Rotate(Br);393}394395stage = 10;396break;397// This stage marks node that will be recolor.398case 10:399Pr = node.getNode(Node.Parent);400if (node == Pr.getNode(Node.Left_son)) {401Br = Pr.getNode(Node.Right_son);402} else {403Br = Pr.getNode(Node.Left_son);404}405406stage = 11;407break;408// This stage recolors marked nodes.409case 11:410Pr = node.getNode(Node.Parent);411if (node == Pr.getNode(Node.Left_son)) {412Br = Pr.getNode(Node.Right_son);413Br.getNode(Node.Right_son).setColor(Node.Black);414} else {415Br = Pr.getNode(Node.Left_son);416Br.getNode(Node.Left_son).setColor(Node.Black);417418}419if (Br.getColor() != Pr.getColor()) {420Br.setColor(Pr.getColor());421}422if (Pr.getColor() != Node.Black) {423Pr.setColor(Node.Black);424}425426stage = 12;427break;428// This stage performs rotation operation.429case 12:430Pr = node.getNode(Node.Parent);431if (node == Pr.getNode(Node.Left_son)) {432Left_Rotate(Pr);433} else {434Right_Rotate(Pr);435}436node = root;437if (node.getColor() == Node.Red) {438stage = 13;439} else {440stage = 0;441}442break;443// This stage marks a node that will be recolored444case 13:445stage = 14;446break;447// This stage recolors marked node.448case 14:449node.setColor(Node.Black);450stage = 0;451break;452}453}454455// This method inserts the node 'node' to the tree.456// it called from the first stage in the InsertStep method.457// we 'dive' from the root to a leaf according to the node key458// and insert the node in the proper place.459private void Tree_Insert() {460Node n1, n2;461n1 = root;462n2 = treeNull;463while (n1 != treeNull) {464n2 = n1;465if (node.getKey() < n1.getKey()) {466n1 = n1.getNode(Node.Left_son);467} else {468n1 = n1.getNode(Node.Right_son);469}470}471node.setNode(Node.Parent, n2);472if (n2 == treeNull) {473root = node;474}475else {476if (node.getKey() < n2.getKey()) {477n2.setNode(Node.Left_son, node);478} else {479n2.setNode(Node.Right_son, node);480}481}482// updating the insertion stage.483if ((node == root) ||484(node.getNode(Node.Parent).getColor() == Node.Black)) {485if (root.getColor() == Node.Red) {486stage = 9;487} else {488stage = 0;489}490} else {491stage = 2;492InsertStep();493}494num_of_nodes++; // increasing the number of nodes495}496497// This method deletes the node 'node' from the tree.498// it called from the first stage in the DeleteStep method.499// if node has at most one son we just remove it and connect500// his son and parent. If it has 2 sons we delete his successor501// that has at most one son and replace him with the successor.502private void Tree_Delete() {503Node n1, n2, n3;504if ((node.getNode(Node.Left_son) == treeNull) ||505(node.getNode(Node.Right_son) == treeNull)) {506n1 = node;507} else {508n1 = Tree_Successor(node);509}510511if (n1.getNode(Node.Left_son) != treeNull) {512n2 = n1.getNode(Node.Left_son);513} else {514n2 = n1.getNode(Node.Right_son);515}516517n3 = n1.getNode(Node.Parent);518n2.setNode(Node.Parent, n3);519if (n3 == treeNull) {520root = n2;521} else if (n1 == n3.getNode(Node.Left_son)) {522n3.setNode(Node.Left_son, n2);523} else {524n3.setNode(Node.Right_son, n2);525}526527if (n1 != node) {528node.setKey(n1.getKey());529}530531node = n2;532if (n1.getColor() == Node.Black) {533if ((node != root) && (node.getColor() == Node.Black)) {534stage = 2;535} else if (node.getColor() == Node.Red) {536stage = 13;537} else {538stage = 0;539}540} else {541stage = 0;542}543// decrease the number of nodes.544num_of_nodes--;545}546547// This method returns the successor of the node n in the tree.548private Node Tree_Successor(Node n) {549Node n1;550if (n.getNode(Node.Right_son) != treeNull) {551n = n.getNode(Node.Right_son);552while (n.getNode(Node.Left_son) != treeNull) {553n = n.getNode(Node.Left_son);554}555return n;556}557n1 = n.getNode(Node.Parent);558while ((n1 != treeNull) && (n == n1.getNode(Node.Right_son))) {559n = n1;560n1 = n1.getNode(Node.Parent);561}562return n1;563}564565// This method performs Left Rotation with n1.566private void Left_Rotate(Node n1) {567Node n2;568569n2 = n1.getNode(Node.Right_son);570n1.setNode(Node.Right_son, n2.getNode(Node.Left_son));571if (n2.getNode(Node.Left_son) != treeNull) {572n2.getNode(Node.Left_son).setNode(Node.Parent, n1);573}574n2.setNode(Node.Parent, n1.getNode(Node.Parent));575if (n1.getNode(Node.Parent) == treeNull) {576root = n2;577} else if (n1 == n1.getNode(Node.Parent).getNode(Node.Left_son)) {578n1.getNode(Node.Parent).setNode(Node.Left_son, n2);579} else {580n1.getNode(Node.Parent).setNode(Node.Right_son, n2);581}582n2.setNode(Node.Left_son, n1);583n1.setNode(Node.Parent, n2);584}585586// This method performs Right Rotation with n1.587private void Right_Rotate(Node n1) {588Node n2;589590n2 = n1.getNode(Node.Left_son);591n1.setNode(Node.Left_son, n2.getNode(Node.Right_son));592if (n2.getNode(Node.Right_son) != treeNull) {593n2.getNode(Node.Right_son).setNode(Node.Parent, n1);594}595n2.setNode(Node.Parent, n1.getNode(Node.Parent));596if (n1.getNode(Node.Parent) == treeNull) {597root = n2;598} else if (n1 == (n1.getNode(Node.Parent)).getNode(Node.Left_son)) {599n1.getNode(Node.Parent).setNode(Node.Left_son, n2);600} else {601n1.getNode(Node.Parent).setNode(Node.Right_son, n2);602}603n2.setNode(Node.Right_son, n1);604n1.setNode(Node.Parent, n2);605}606607// This method searches the tree for a node with key 'key', and608// returns the node on success otherwise treeNull.609public Node Search(int key) {610Node node;611node = root;612while ((node != treeNull) && (key != node.getKey())) {613if (key < node.getKey()) {614node = node.getNode(Node.Left_son);615} else {616node = node.getNode(Node.Right_son);617}618}619return node;620}621622// This method updates the tree height. it uses a recursive method623// findHeight.624private void updateHeight() {625height = 0;626if (root != treeNull) {627findHeight(root, 1);628}629}630631// This is a recursive method that find a node height.632private void findHeight(Node n, int curr) {633if (height < curr) {634height = curr;635}636if (n.getNode(Node.Left_son) != treeNull) {637findHeight(n.getNode(Node.Left_son), curr + 1);638}639if (n.getNode(Node.Right_son) != treeNull) {640findHeight(n.getNode(Node.Right_son), curr + 1);641}642}643644}645646647