From f6eb9ca18d6ced059183e8d6aebc70b93b35af79 Mon Sep 17 00:00:00 2001 From: freckles30 <72254336+freckles30@users.noreply.github.com> Date: Tue, 20 Oct 2020 08:47:45 +0530 Subject: [PATCH] Added code for Red Black Tree in java --- Tree/RedBlackTree.java | 357 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 357 insertions(+) create mode 100644 Tree/RedBlackTree.java diff --git a/Tree/RedBlackTree.java b/Tree/RedBlackTree.java new file mode 100644 index 0000000..06af7cd --- /dev/null +++ b/Tree/RedBlackTree.java @@ -0,0 +1,357 @@ +import java.util.Scanner; + +public class RedBlackTree { + + private final int RED = 0; + private final int BLACK = 1; + + private class Node { + + int key = -1, color = BLACK; + Node left = nil, right = nil, parent = nil; + + Node(int key) { + this.key = key; + } + } + + private final Node nil = new Node(-1); + private Node root = nil; + + public void printTree(Node node) { + if (node == nil) { + return; + } + printTree(node.left); + System.out.print(((node.color==RED)?"Color: Red ":"Color: Black ")+"Key: "+node.key+" Parent: "+node.parent.key+"\n"); + printTree(node.right); + } + + private Node findNode(Node findNode, Node node) { + if (root == nil) { + return null; + } + + if (findNode.key < node.key) { + if (node.left != nil) { + return findNode(findNode, node.left); + } + } else if (findNode.key > node.key) { + if (node.right != nil) { + return findNode(findNode, node.right); + } + } else if (findNode.key == node.key) { + return node; + } + return null; + } + + private void insert(Node node) { + Node temp = root; + if (root == nil) { + root = node; + node.color = BLACK; + node.parent = nil; + } else { + node.color = RED; + while (true) { + if (node.key < temp.key) { + if (temp.left == nil) { + temp.left = node; + node.parent = temp; + break; + } else { + temp = temp.left; + } + } else if (node.key >= temp.key) { + if (temp.right == nil) { + temp.right = node; + node.parent = temp; + break; + } else { + temp = temp.right; + } + } + } + fixTree(node); + } + } + + //Takes as argument the newly inserted node + private void fixTree(Node node) { + while (node.parent.color == RED) { + Node uncle = nil; + if (node.parent == node.parent.parent.left) { + uncle = node.parent.parent.right; + + if (uncle != nil && uncle.color == RED) { + node.parent.color = BLACK; + uncle.color = BLACK; + node.parent.parent.color = RED; + node = node.parent.parent; + continue; + } + if (node == node.parent.right) { + //Double rotation needed + node = node.parent; + rotateLeft(node); + } + node.parent.color = BLACK; + node.parent.parent.color = RED; + //if the "else if" code hasn't executed, this + //is a case where we only need a single rotation + rotateRight(node.parent.parent); + } else { + uncle = node.parent.parent.left; + if (uncle != nil && uncle.color == RED) { + node.parent.color = BLACK; + uncle.color = BLACK; + node.parent.parent.color = RED; + node = node.parent.parent; + continue; + } + if (node == node.parent.left) { + //Double rotation needed + node = node.parent; + rotateRight(node); + } + node.parent.color = BLACK; + node.parent.parent.color = RED; + //if the "else if" code hasn't executed, this + //is a case where we only need a single rotation + rotateLeft(node.parent.parent); + } + } + root.color = BLACK; + } + + void rotateLeft(Node node) { + if (node.parent != nil) { + if (node == node.parent.left) { + node.parent.left = node.right; + } else { + node.parent.right = node.right; + } + node.right.parent = node.parent; + node.parent = node.right; + if (node.right.left != nil) { + node.right.left.parent = node; + } + node.right = node.right.left; + node.parent.left = node; + } else {//Need to rotate root + Node right = root.right; + root.right = right.left; + right.left.parent = root; + root.parent = right; + right.left = root; + right.parent = nil; + root = right; + } + } + + void rotateRight(Node node) { + if (node.parent != nil) { + if (node == node.parent.left) { + node.parent.left = node.left; + } else { + node.parent.right = node.left; + } + + node.left.parent = node.parent; + node.parent = node.left; + if (node.left.right != nil) { + node.left.right.parent = node; + } + node.left = node.left.right; + node.parent.right = node; + } else {//Need to rotate root + Node left = root.left; + root.left = root.left.right; + left.right.parent = root; + root.parent = left; + left.right = root; + left.parent = nil; + root = left; + } + } + + //Deletes whole tree + void deleteTree(){ + root = nil; + } + + //Deletion Code . + + //This operation doesn't care about the new Node's connections + //with previous node's left and right. The caller has to take care + //of that. + void transplant(Node target, Node with){ + if(target.parent == nil){ + root = with; + }else if(target == target.parent.left){ + target.parent.left = with; + }else + target.parent.right = with; + with.parent = target.parent; + } + + boolean delete(Node z){ + if((z = findNode(z, root))==null)return false; + Node x; + Node y = z; // temporary reference y + int y_original_color = 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 = treeMinimum(z.right); + y_original_color = 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(y_original_color==BLACK) + deleteFixup(x); + return true; + } + + 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; + rotateLeft(x.parent); + w = x.parent.right; + } + if(w.left.color == BLACK && w.right.color == BLACK){ + w.color = RED; + x = x.parent; + continue; + } + else if(w.right.color == BLACK){ + w.left.color = BLACK; + w.color = RED; + rotateRight(w); + w = x.parent.right; + } + if(w.right.color == RED){ + w.color = x.parent.color; + x.parent.color = BLACK; + w.right.color = BLACK; + rotateLeft(x.parent); + x = root; + } + }else{ + Node w = x.parent.left; + if(w.color == RED){ + w.color = BLACK; + x.parent.color = RED; + rotateRight(x.parent); + w = x.parent.left; + } + if(w.right.color == BLACK && w.left.color == BLACK){ + w.color = RED; + x = x.parent; + continue; + } + else if(w.left.color == BLACK){ + w.right.color = BLACK; + w.color = RED; + rotateLeft(w); + w = x.parent.left; + } + if(w.left.color == RED){ + w.color = x.parent.color; + x.parent.color = BLACK; + w.left.color = BLACK; + rotateRight(x.parent); + x = root; + } + } + } + x.color = BLACK; + } + + Node treeMinimum(Node subTreeRoot){ + while(subTreeRoot.left!=nil){ + subTreeRoot = subTreeRoot.left; + } + return subTreeRoot; + } + + public void consoleUI() { + Scanner scan = new Scanner(System.in); + while (true) { + System.out.println("\n1.- Add items\n" + + "2.- Delete items\n" + + "3.- Check items\n" + + "4.- Print tree\n" + + "5.- Delete tree\n"); + int choice = scan.nextInt(); + + int item; + Node node; + switch (choice) { + case 1: + item = scan.nextInt(); + while (item != -999) { + node = new Node(item); + insert(node); + item = scan.nextInt(); + } + printTree(root); + break; + case 2: + item = scan.nextInt(); + while (item != -999) { + node = new Node(item); + System.out.print("\nDeleting item " + item); + if (delete(node)) { + System.out.print(": deleted!"); + } else { + System.out.print(": does not exist!"); + } + item = scan.nextInt(); + } + System.out.println(); + printTree(root); + break; + case 3: + item = scan.nextInt(); + while (item != -999) { + node = new Node(item); + System.out.println((findNode(node, root) != null) ? "found" : "not found"); + item = scan.nextInt(); + } + break; + case 4: + printTree(root); + break; + case 5: + deleteTree(); + System.out.println("Tree deleted!"); + break; + } + } + } + public static void main(String[] args) { + RedBlackTree rbt = new RedBlackTree(); + rbt.consoleUI(); + } +} \ No newline at end of file