//Quickly fix the height values of the node, does not care about updating the values of parents //This is only called on nodes that I know need updating and dont effect the rest of the tree (ei the moved node in LR or RL balance issue) private void quickFixHeight(ADSNode n) { int l = (n.left == null) ? 0 : n.left.height + 1; int r = (n.right == null) ? 0 : n.right.height + 1; n.height = Math.Max(l, r); }
private void Balance(ref ADSNode imbalancedNode) { var imbalanceType = ImbalanceType(imbalancedNode); if (imbalanceType == "LR") { // left sub-rotation imbalancedNode.Left = LeftRotation(imbalancedNode.Left); // right rotation imbalancedNode = RightRotation(imbalancedNode); } if (imbalanceType == "LL") { imbalancedNode = RightRotation(imbalancedNode); } if (imbalanceType == "RR") { imbalancedNode = LeftRotation(imbalancedNode); } if (imbalanceType == "RL") { // right sub-rotation imbalancedNode.Right = RightRotation(imbalancedNode.Right); // left rotation imbalancedNode = LeftRotation(imbalancedNode); } }
// Return the node where value is located public ADSNode Find(T value) { ADSNode current = Root; while (true) { if (current == null) { return(null); } if (value.CompareTo(current.Key) == 0) { return(current); } if (value.CompareTo(current.Key) < 0) { current = current.Left; } else { current = current.Right; } } }
// Inserts a node into the tree and maintains it's balance public void insert(int value) { //Insert to root if null if (root == null) { root = new ADSNode() { key = value } } ; //Try to recursively insert node else { ADSNode n = addNode(root, value); //This is not neaded for root, so just discard this data if (n.height < 0) { n.height *= -1; } root = n; } //If you overwrite a node in your insertion, put that back in (IDK if this is most efficient, but its what im doing) while (overwritenNode != null) { insert(overwritenNode.key); } }
//fix balance on a specific node, returns the new head node reference private ADSNode fixBalance(ADSNode node) { //Gets the type of ballance issue; string type = heavy(node, false); if (type == "RR") { return(leftRotate(node)); } else if (type == "LL") { return(rightRotate(node)); } else if (type == "LR") { node.left = leftRotate(node.left); return(rightRotate(node)); } else //RL { node.right = rightRotate(node.right); return(leftRotate(node)); } }
private void PrintRecursive(ADSNode node, TraverseOrder order) { if (node == null) { return; } // used to output a tree to be loaded again without rebalancing if (order == TraverseOrder.PreOrder) { Console.Write(node.Key + " "); } PrintRecursive(node.Left, order); // used to print a tree for readability if (order == TraverseOrder.InOrder) { Console.Write(node.Key + " "); } PrintRecursive(node.Right, order); // used to print a tree to be deleted efficeintly if (order == TraverseOrder.PostOrder) { Console.Write(node.Key + " "); } }
// Inserts a node into the tree and maintains its balance public void Insert(T value) { var newNode = new ADSNode { Key = value, Cardinality = 1 }; InsertNode(ref Root, newNode); }
private ADSNode LeftRotation(ADSNode imbalancedNode) { var tempNode = imbalancedNode.Right; imbalancedNode.Right = tempNode.Left; tempNode.Left = imbalancedNode; return(tempNode); }
private ADSNode leftRotation(ADSNode node) { ADSNode newRoot = node.right; ADSNode temp = (newRoot.left == null) ? null : newRoot.left; newRoot.left = node; node.right = temp; return(newRoot); }
public static void PostOrderTraversal(ADSNode root) { if (root == null) { return; } PostOrderTraversal(root.left); // process the left PostOrderTraversal(root.right); // process the right Console.WriteLine(root.key); // process the root }
private ADSNode rightRotation(ADSNode node) { //should return newRoot ADSNode newRoot = node.left; ADSNode temp = (newRoot.right == null) ? null : newRoot.right; newRoot.right = node; node.left = temp; return(newRoot); }
private ADSNode rightLeftRotation(ADSNode node) { ADSNode temp = node.right; ADSNode newRoot = node.right.left; temp.left = null; node.right = newRoot; newRoot.right = temp; return(node); }
private string ImbalanceType(ADSNode node) { if (node.LeftHeight > node.RightHeight) { node = node.Left; return(node.LeftHeight > node.RightHeight ? "LL" : "LR"); } else { node = node.Right; return(node.LeftHeight > node.RightHeight ? "RL" : "RR"); } }
//Same as left rotation, but opposite private ADSNode rightRotate(ADSNode node) { ADSNode ret = node.left; overwritenNode = node.left.right; node.left.right = node; node.left = null; quickFixHeight(ret.right); quickFixHeight(ret); return(ret); }
public void printTree(ADSNode node, TraverseOrder order) { if (node == null) { return; } printTree(node.left, order); if (order == TraverseOrder.InOrder) { Console.Write(node.key); } printTree(node.right, order); }
private void breathPrint(ADSNode n) { int size = 64; List <List <ADSNode> > children = new List <List <ADSNode> >(); children.Add(new List <ADSNode> { root }); while (true) { children.Add(new List <ADSNode>()); bool cont = false; foreach (ADSNode child in children[0]) { if (child == null) { Console.Write("- ".PadLeft(size / 2).PadRight(size)); children[1].Add(null); children[1].Add(null); continue; } cont = true; Console.Write((child.key + "").PadLeft(size / 2).PadRight(size)); if (child.left != null) { children[1].Add(child.left); } else { children[1].Add(null); } if (child.right != null) { children[1].Add(child.right); } else { children[1].Add(null); } } Console.WriteLine("\n"); children.RemoveAt(0); size /= 2; if (!cont) { break; } } }
// Inserts a node into the tree and maintains its balance public void insert(int value) { if (root == null) { root = new ADSNode() { key = value } } ; else { root = insert(value, root); } }
//Rotate tree at node to the left private ADSNode leftRotate(ADSNode node) { ADSNode ret = node.right; //Move parent node to be under child overwritenNode = node.right.left; node.right.left = node; node.right = null; //Ret is new head node, ret.left is old head node //Update their heights quickFixHeight(ret.left); quickFixHeight(ret); return(ret); }
public ADSNode updateHeight(ADSNode node) { int left = (node.left == null) ? 0 : node.left.height + 1; int right = (node.right == null) ? 0 : node.right.height + 1; int height = Math.Max(left, right); node.height = height; int difference = Math.Abs(right - left); if (difference >= 2) { node = balance(node); } return(node); }
//Get type from pos private string heavy(ADSNode n, bool done = true) { //Gets the heights at a pos int l = (n.left == null) ? 0 : n.left.height + 1; int r = (n.right == null) ? 0 : n.right.height + 1; //Gets which is greater string val = (l > r) ? "L" : "R"; //If your done, return if (done) { return(val); } //If not, add the char and continue return(val + ((val == "L") ? heavy(n.left) : heavy(n.right))); }
// Inserts a node into the tree and maintains it's balance public void insert(ADSNode parent, int value) { ADSNode n = new ADSNode(); if (root == null) { root = new ADSNode(); } else { } if (value < parent.key) { if (parent.left == null) { //create new node n.key = value; parent.left = n; } else { insert(parent.right, value); parent.height = Math.Max(parent.left == null ? 0 : parent.left.height, parent.right == null ? 0 : parent.right.height) + 1; } } else if (value > parent.key) { if (parent.right == null) { //create new node n.key = value; parent.right = n; } else { insert(parent.right, value); parent.height = Math.Max(parent.right == null ? 0 : parent.right.height, parent.left == null ? 0 : parent.left.height) + 1; } } }
private ADSNode InsertNode(ref ADSNode head, ADSNode data) { if (head == null) { // do the insert head = data; return(head); } int keyComparison = head.Key.CompareTo(data.Key); if (keyComparison == 0) { head.Cardinality++; return(head); } else if (keyComparison < 0) { head.Right = InsertNode(ref head.Right, data); } else { head.Left = InsertNode(ref head.Left, data); } // attempt to rebalance when bubbling up if (Math.Abs(head.LeftHeight - head.RightHeight) > 1) { Balance(ref head); // recalculate heights head.Left?.RecalculateHeight(); head.Right?.RecalculateHeight(); } head.RecalculateHeight(); return(head); }
public void insert(ADSNode parent, int value) { if (value > parent.key) { if (parent.right == null) { // Create a new node connected to parent.right ADSNode n = new ADSNode(); n.key = value; parent.right = n; } else { insert(parent.right, value); parent.height = Math.Max(parent.left == null ? 0 : parent.left.height, parent.right == null ? 0 : parent.right.height) + 1; } } else if (value < parent.key) { if (parent.left == null) { // create a new node connected to parent.left ADSNode n = new ADSNode(); n.key = value; parent.left = n; } else { insert(parent.left, value); parent.height = Math.Max(parent.left == null ? 0 : parent.left.height, parent.right == null ? 0 : parent.right.height) + 1; } } }
// Inserts a node into the tree and maintains it's balance public void insert(int value) { ADSNode n = new ADSNode(); n.left = null; n.right = null; n.key = value; n.cardinality = 0; n.height = 0; ADSNode node = root; while (true) { if (value > node.key) { if (node.right == null) { node.right = n; break; } else { node = node.right; } } else if (value == root.key) { node.cardinality++; } else if (value < root.key) { root.left = n; } } }
//Takes a node and updates its height returns true if the height changed private ADSNode updateHeight(ADSNode n) { //Get the heights of the side nodes int l = (n.left == null) ? 0 : n.left.height + 1; int r = (n.right == null) ? 0 : n.right.height + 1; //Heavy on one side ? fix the balance if (Math.Abs(l - r) == 2) { return(fixBalance(n)); } //Save adjusted height int adjustedHeight = Math.Max(l, r); //If it is different, change it and indicate it by making it negative if (adjustedHeight != n.height) { n.height = -adjustedHeight; } //return node with changes return(n); }
public ADSTree() { root = null; }
public ADSTree() { Root = null; }
//adds a node to the tree and updates the heights as you go private ADSNode addNode(ADSNode n, int val) { //Increment cardinality and return, they are the same so nothing changes if (n.key == val) { n.cardinality++; return(n); } ADSNode side = (val > n.key) ? n.right : n.left; //You found your side, then inert it and you good if (side == null) { //If you are inserting a whole node and not just a value, then do that if (overwritenNode != null) { side = overwritenNode; overwritenNode = null; } else { side = new ADSNode() { key = val } }; //Adds node to propper size if (n.key > val) { n.left = side; } else { n.right = side; } return(updateHeight(n)); } //It wasnt ment to be inserted here, but it was inserted later. //This returns the new child reference just incase the insert shifted the tree ADSNode child = addNode(side, val); //Reasign references, they could have chnaged if (n.key > val) { n.left = child; } else { n.right = child; } //The sign of the int is used to determine if this node should re-adjust its height values if (child.height < 0) { child.height *= -1; //Update the node to see if the heights need to be adjusted and return it return(updateHeight(n)); } return(n); }