public AVLTreeNode Delete(AVLTreeNode root, int data) { /* 1. Perform the normal BST delete */ if (root == null) { return(null); } if (data < root.Data) { //goes into left subtree root.Left = Delete(root.Left, data); } else if (data > root.Data) { root.Right = Delete(root.Right, data); } else { // node with only one child or no child if ((root.Left == null) || (root.Right == null)) { //when equal we need to delete this node AVLTreeNode temp = root.Left != null ? root.Left : root.Right; //if it has no childres if (temp == null) { root = null; } //if it has one children else { root = temp; } } else { //if it has two children // node with two children: Get the inorder successor (smallest // in the right subtree) AVLTreeNode temp = minValueNode(root.Right); // Copy the inorder successor's data to this node root.Data = temp.Data; //here we overwrite the node to be deleted with temp.data // Delete the inorder successor root.Right = Delete(root.Right, temp.Data); } } // If the tree had only one node then return if (root == null) { return(root); } /* 2. Update height of this ancestor node */ root.Height = Math.Max(GetHeight(root.Left), GetHeight(root.Right)) + 1; /* 3. Get the balance factor of this ancestor node to check whether * this node became unbalanced */ int balacefactor = GetBalanceFactor(root); if (balacefactor < -1 || balacefactor > 1) { //just for test test int i = balacefactor; } //check if the root is unbalaced for all the four case and do the rotation //here the logic is hard to follow with GetBalanceFactor //left left case if (root.Left != null && balacefactor > 1 && GetBalanceFactor(root.Left) >= 0) { //then rotate the root to right return(RotateRight(root)); } //right right case if (root.Right != null && balacefactor < -1 && GetBalanceFactor(root.Right) <= 0) { //then rotate the root to left return(RotateLeft(root)); } //left right case if (root.Left != null && balacefactor > 1 && GetBalanceFactor(root.Left) < 0) { //then we need to do 2 rotations root.Left = RotateLeft(root.Left); //and then rotate the root to right return(RotateRight(root)); } //right left case if (root.Right != null && balacefactor < -1 & GetBalanceFactor(root.Right) > 0) { root.Right = RotateRight(root.Right); return(RotateLeft(root)); } //if the root is balaced we return the actula unchanged root return(root); }
public AVLTreeNode Insert(AVLTreeNode root, int data) { /* 1. Perform the normal BST insert */ if (root == null) { //When we create a node, we default the height to 1 AVLTreeNode node = new AVLTreeNode(data); return(node); } if (data <= root.Data) { //goes into left subtree root.Left = Insert(root.Left, data); } else { root.Right = Insert(root.Right, data); } /* 2. Update height of this ancestor node */ // Max of Height of (Left, Right) + 1 root.Height = Math.Max(GetHeight(root.Left), GetHeight(root.Right)) + 1; /* 3. Get the balance factor of this ancestor node to check whether * this node became unbalanced */ //since the balancing factor is calculated by (Height of Left - Height of right) //If a root is unbalaced which means the height of left - right is greater than 1 or lesser than -1 //balacefactor is > 1, then left subtree of root has more height than right and that caused the unbalacing tree //balacefactore is < -1, then right subtree of root has more height and that caused the unbalancing int balacefactor = GetBalanceFactor(root); if (balacefactor < -1 || balacefactor > 1) { //just for test test int i = balacefactor; } //check if the root is unbalaced for all the four case and do the rotation //Logic: //root.left != null and balacefactor > 1 tells that root.left has more height //to differentiate btn left left case and left right case we have an another condition //Check whether the data (from the recursion params) that we added goes to the left or right of Root.Left //If data < root.Left.Data then the data (new node) has went to left of root.Left and that caused the unbalacing -- Left Left Case //If data > root.Right.Data then the data has went to right of root.Left and that caused unbalancing --Left Right case //similarly right right case and right left case //left left case if (root.Left != null && balacefactor > 1 && data < root.Left.Data) { //then rotate the root to right return(RotateRight(root)); } //right right case if (root.Right != null && balacefactor < -1 && data > root.Right.Data) { //then rotate the root to left return(RotateLeft(root)); } //left right case if (root.Left != null && balacefactor > 1 && data > root.Left.Data) { //then we need to do 2 rotations root.Left = RotateLeft(root.Left); //and then rotate the root to right return(RotateRight(root)); } //right left case if (root.Right != null && balacefactor < -1 & data < root.Right.Data) { root.Right = RotateRight(root.Right); return(RotateLeft(root)); } //if the root is balaced we return the actula unchanged root return(root); }
//this is a custome insert function //http://stackoverflow.com/questions/15197058/number-of-distinct-smaller-elements-on-left-for-each-position-in-a-array //http://www.geeksforgeeks.org/count-smaller-elements-on-right-side/ /*Logic * We need to find the number of smallest element on the right of a particular array element * So we add the array elements from right to left to a self balancing tree (eg AVL tree) * so that for each element we can see how many element were smaller from right side * * Here the counter parameter is returned on each insertion and it has the count of no of elements smaller than the data added * We create the insert logic of the AVL tree ( ie with the height propery and rotation management) * We add a new property called size to maintain the size of each node. Size of leaf node is 1 * When we add a data to a root * a) if the data is lesser than the root it goes to the right and the counter can still remind the same * b) if the data is greater than the root then it means that data is greater then root + size of root.Left so we have to handle this logic on the recurssion * The rotation really doesn't matter but we have to recalculate the height and size property during rotation * Counter is the variable that tells how many elements are lesser than the data without going to each elements with the help of size property * * Time Complexity: O(nLogn) * Auxiliary Space: O(n) * */ public AVLTreeNode Insert(AVLTreeNode root, int data, ref int counter) { /* 1. Perform the normal BST insert */ if (root == null) { AVLTreeNode node = new AVLTreeNode(data); return(node); } //Custom prob logic to skip inserting when the value already exists if (data == root.Data) { return(root); } if (data < root.Data) { //goes into left subtree root.Left = Insert(root.Left, data, ref counter); } else { if (data == 12) { int test = root.Data; } root.Right = Insert(root.Right, data, ref counter); //whenever we go to the right of a node to insert which means that current data is greater than the root //or the root is smaller than the current..the root might have left subtree so the counter should be update counter = counter + GetSize(root.Left) + 1; //1 is for the root itselft which is smaller and //source: http://stackoverflow.com/questions/15197058/number-of-distinct-smaller-elements-on-left-for-each-position-in-a-array } /* 2. Update height of this ancestor node */ root.Height = Math.Max(GetHeight(root.Left), GetHeight(root.Right)) + 1; //updat the size of the root root.Size = GetSize(root.Left) + GetSize(root.Right) + 1; /* 3. Get the balance factor of this ancestor node to check whether * this node became unbalanced */ int balacefactor = GetBalanceFactor(root); if (balacefactor < -1 || balacefactor > 1) { //just for test test int i = balacefactor; } //check if the root is unbalaced for all the four case and do the rotation //left left case if (root.Left != null && balacefactor > 1 && data < root.Left.Data) { //then rotate the root to right return(RotateRight(root)); } //right right case if (root.Right != null && balacefactor < -1 && data > root.Right.Data) { //then rotate the root to left return(RotateLeft(root)); } //left right case if (root.Left != null && balacefactor > 1 && data > root.Left.Data) { //then we need to do 2 rotations root.Left = RotateLeft(root.Left); //and then rotate the root to right return(RotateRight(root)); } //right left case if (root.Right != null && balacefactor < -1 & data < root.Right.Data) { root.Right = RotateRight(root.Right); return(RotateLeft(root)); } //if the root is balaced we return the actula unchanged root return(root); }