/* * RBInsert and RBDelete modify the tree which may result in a violation of the * red-black poperties. In order to fix this we may need to "move around" some of * the nodes as well as their colors. LeftRotate and RightRotate help us do this. * */ private Node LeftRotate(Node x) { Node y = x.right; x.right = y.left; if (y.left != NIL.Instance()) { y.left.parent = x; } y.parent = x.parent; if (x.parent == NIL.Instance()) { root = y; } else if (x == x.parent.left) { x.parent.left = y; } else { x.parent.right = y; } y.left = x; x.parent = y; return(x); }
private void LeftRotate(Node nodeToRotate) { // setting node which will come in place of nodeToRotate Node nodeToReplace = nodeToRotate.Right; //turn nodeToReplace's left subtree into nodeToRotate's right subtree nodeToRotate.Right = nodeToReplace.Left; if (nodeToReplace.Left != NIL.Instance()) { // if left subtree exists make it's parent nodeToRotate nodeToReplace.Left.Parent = nodeToRotate; } if (nodeToReplace != NIL.Instance()) { // link nodeToRotate parent to nodeToReplace nodeToReplace.Parent = nodeToRotate.Parent; } if (nodeToRotate.Parent == NIL.Instance()) { // if nodeToRotate is the root, make nodeToReplace as new root Root = nodeToReplace; } if (nodeToRotate == nodeToRotate.Parent.Left) { // if nodeToRotate is a left child, nodeToReplace has to become left child of nodeToRotate's parent nodeToRotate.Parent.Left = nodeToReplace; } else { // if nodeToRotate is a right child, nodeToReplace has to become right child of nodeToRotate's parent nodeToRotate.Parent.Right = nodeToReplace; } // put nodeToRotate on nodeToReplace's left nodeToReplace.Left = nodeToRotate; // if nodeToRotate is not nil, make it's parent nodeToReplace if (nodeToRotate != NIL.Instance()) { nodeToRotate.Parent = nodeToReplace; } }
/* * To find the maximum of the three from node n (including * the root) we just keep going down the right braches until there * are no more nodes. * */ private Node RBTreeMaximum(Node x) { while (x.right != NIL.Instance()) { x = x.right; } return(x); }
/* * To find the minimum of the tree from node n (including * the root) we just keep going down the left branches until there * are no more nodes. * */ private Node RBTreeMinimum(Node x) { while (x.left != NIL.Instance()) { x = x.left; } return(x); }
/// <summary> /// passing through the tree by InOrderTraversal /// </summary> /// <param name="root"> root of a subtree to be passed </param> private void InOrderDisplay(Node root) { if (root != NIL.Instance()) { InOrderDisplay(root.Left); Console.Write("Key is {0} and Value is {1} ", root.Key, root.Value); InOrderDisplay(root.Right); } }
/// <summary> /// to restore the red-black properties /// </summary> /// <param name="NewAddedNode"> node which was inserted </param> private void RBT_InsertFixUp(Node NewAddedNode) { while (NewAddedNode != Root && NewAddedNode.Parent.color == COLOR.Red) { // if parent of new added node is a left child if (NewAddedNode.Parent == NewAddedNode.Parent.Parent.Left) { // uncle of newAddedNode Node uncle = NewAddedNode.Parent.Parent.Right; if (uncle != NIL.Instance() && uncle.color == COLOR.Red) { NewAddedNode.Parent.color = COLOR.Black; uncle.color = COLOR.Black; NewAddedNode.Parent.Parent.color = COLOR.Red; // make newNode's grandparent as the new newNode and repeat the steps NewAddedNode = NewAddedNode.Parent.Parent; } // if uncle is black and parent of newNode is not black there are 2 cases // 1 case (left right case) else if (NewAddedNode == NewAddedNode.Parent.Right) { NewAddedNode = NewAddedNode.Parent; LeftRotate(NewAddedNode); } else {// case 2 (left left case) NewAddedNode.Parent.color = COLOR.Black; NewAddedNode.Parent.Parent.color = COLOR.Red; RightRotate(NewAddedNode.Parent.Parent); } } else { // if parent of a new added node is right child Node y = NewAddedNode.Parent.Parent.Left; // uncle of newNode if (y != NIL.Instance() && y.color == COLOR.Red) { NewAddedNode.Parent.color = COLOR.Black; y.color = COLOR.Black; NewAddedNode.Parent.Parent.color = COLOR.Red; NewAddedNode = NewAddedNode.Parent.Parent; } // case 1 (right left) else if (NewAddedNode == NewAddedNode.Parent.Left) { NewAddedNode = NewAddedNode.Parent; RightRotate(NewAddedNode); } else { //case 2(right right) NewAddedNode.Parent.color = COLOR.Black; NewAddedNode.Parent.Parent.color = COLOR.Red; LeftRotate(NewAddedNode.Parent.Parent); } } Root.color = COLOR.Black; } }
/* * * */ public void RBInsert(Key kz, Value vz) { //Only add a new node if the key does not already exist Node newNode = new Node(); newNode.key = kz; newNode.val = vz; newNode.left = NIL.Instance(); newNode.right = NIL.Instance(); RBInsert(newNode); }
/// <summary> /// displaying tree /// </summary> public void Display() { if (Root != NIL.Instance()) { InOrderDisplay(Root); } else { throw new Exception("No tree"); } }
/// <summary> /// to delete node from the tree /// </summary> /// <param name="nodeToDelete"> node to be deleted </param> private void RBT_Delete(Node nodeToDelete) { Node node = nodeToDelete; /* * We have to store nodeToDelete's original color, because when we move a node * into it's postion and the color of nodeToDelete is black we must call DeleteFixup */ COLOR originalColor = node.color; Node x; // when nodeToDelete has one child we just need to replace nodeToDelete with the child if (nodeToDelete.Left == NIL.Instance()) { x = nodeToDelete.Right; RBTransplant(nodeToDelete, nodeToDelete.Right); } else if (nodeToDelete.Right == NIL.Instance()) { x = nodeToDelete.Left; RBTransplant(nodeToDelete, nodeToDelete.Left); } else { /* if nodeToDelete has two children we have to find the successor (the smallest key * that is larger than nodeToDelete) and move it into nodeToDelete's position */ node = RBTreeMinimum(nodeToDelete.Right); originalColor = node.color; x = node.Right; // if successor is right child if (node.Parent == nodeToDelete) { x.Parent = node; } else { // succesor will move into nodeToDelete's position RBTransplant(node, node.Right); node.Right = nodeToDelete.Right; node.Right.Parent = node; } RBTransplant(nodeToDelete, node); node.Left = nodeToDelete.Left; node.Left.Parent = node; node.color = nodeToDelete.color; } // if node which was deleted is black, we restore red-black tree properties if (originalColor == COLOR.Black) { RBT_DeleteFixup(x); } }
/* * Used to "replace" u with v. Used when deleting a node and we need to replace * the deleted node with an other node from the tree. * */ private void RBTransplant(Node u, Node v) { if (u.parent == NIL.Instance()) { root = v; } else if (u == u.parent.left) { u.parent.left = v; } else { u.parent.right = v; } v.parent = u.parent; }
/* * This is similar to insert for a binary search tree with a few differences. We use NIL.Instance() * instead of null. * After inserting we call RBInsertFixup incase we've violated one of the red-black properties. * */ private void RBInsert(Node z) { Node y = NIL.Instance(); Node x = root; int cmp; while (x != NIL.Instance()) { y = x; cmp = z.key.CompareTo(x.key); if (cmp < 0) { x = x.left; } else if (cmp > 0) { x = x.right; } else if (cmp == 0) //This key already exists, exit without adding it { return; } } z.parent = y; cmp = z.key.CompareTo(y.key); if (y == NIL.Instance()) { root = z; } else if (cmp < 0) { y.left = z; } else if (cmp > 0) { y.right = z; } else if (cmp == 0)//This key already exists, exit without adding it { return; } z.left = NIL.Instance(); z.right = NIL.Instance(); z.color = RBColor.RED; z = RBInsertFixup(z); }
/// <summary> /// replaces the subtree rooted at node u with the subtree rooted at v /// </summary> /// <param name="u"> node to be replaced </param> /// <param name="v"> node which subtree will come into the place of u node's subtree </param> private void RBTransplant(Node x, Node y) { // if u is a root make v as a root if (x.Parent == NIL.Instance()) { Root = y; } else if (x == x.Parent.Left) { x.Parent.Left = y; } else { x.Parent.Right = y; } // even if u.Parent is NIL we can assign it y.Parent = x.Parent; }
/// <summary> /// Insert a given node /// </summary> /// <param name="newNode"> node to be inserted into the tree </param> private void Insert(Node newNode) { // if tree is empty, make NewNode as the root if (Root == NIL.Instance()) { Root = newNode; Root.color = COLOR.Black; return; } Node parentOfNewNode = NIL.Instance(); Node a = Root; while (a != NIL.Instance()) { // finding the right subtree to insert the newNode parentOfNewNode = a; if (newNode.Key.CompareTo(a.Key) < 0) { a = a.Left; } else { a = a.Right; } } newNode.Parent = parentOfNewNode; if (parentOfNewNode == NIL.Instance()) { Root = newNode; } // finding in which subtree of b newNode have to be inserted else if (newNode.Key.CompareTo(parentOfNewNode.Key) >= 0) { parentOfNewNode.Right = newNode; } else { parentOfNewNode.Left = newNode; } // making inserted node's left and right children NIL and it's color RED newNode.Left = NIL.Instance(); newNode.Right = NIL.Instance(); newNode.color = COLOR.Red; // because coloring red may cause a violation of one of the red-black properties we must guarantee that the red-black properties are preserved RBT_InsertFixUp(newNode); }
// Adds an element with given key and value public void Add(TKey key, TValue value) { if (ContainsKey(key) == false) { Node NewNode = new Node { Key = key, Value = value, Left = NIL.Instance(), Right = NIL.Instance(), Parent = NIL.Instance() }; Keys_List.Add(key); Key_Values.Add(value); Insert(NewNode); listForNodes.Add(new KeyValuePair <TKey, TValue>(key, value)); } else { throw new Exception("Key is already inserted"); } }
/* * Delete node z and replace it with y. If z has only one child we just replace z with * that child. If z has two children then y should be z's successor. * */ private void RBDelete(Node z) { Node x; //First, set y equal to z Node y = z; /* * We want to store z's original color so when we move a node * into z's postion and the value of yOriginalColor is black then we call * RBDeleteFixup. */ RBColor yOriginalColor = y.color; /* * The first two if statements cover when z just has one child. If * so, just replace z with the child */ if (z.left == NIL.Instance()) { x = z.right; RBTransplant(z, z.right); } else if (z.right == NIL.Instance()) { x = z.left; RBTransplant(z, z.left); } else { /* * z has two children. First find the successor (the smallest key * that is larger than z. Move it into z's position by setting it's * parent to z and re-assign child nodes. */ y = RBTreeMinimum(z.right); yOriginalColor = y.color; x = y.right; if (y.parent == z) { x.parent = y; } else { RBTransplant(y, y.right); y.right = z.right; y.right.parent = y; } RBTransplant(z, y); y.left = z.left; y.left.parent = y; y.color = z.color; } /* * If node y was black, several problems may arise which RBDeleteFixup will fix. * */ if (yOriginalColor == RBColor.BLACK) { RBDeleteFixup(x); } }
/// <summary> /// Removes all items from the tree /// </summary> public void Clear() { Root = NIL.Instance(); }