private void AddTo(AVLTreeNode <T> node, T value) { if (value.CompareTo(node.Value) < 0) { if (node.Left == null) { node.Left = new AVLTreeNode <T>(value, node, this); } else { AddTo(node.Left, value); } } else { if (node.Right == null) { node.Right = new AVLTreeNode <T>(value, node, this); } else { AddTo(node.Right, value); } } node.Balance(); }
// Recursive add algorithm private void AddTo(AVLTreeNode <T> node, T value) { // Case 1: Value is less than the current node value if (value.CompareTo(node.Value) < 0) { // if there is no left child make this the new left if (node.Left == null) { node.Left = new AVLTreeNode <T>(value, node, this); } else { // else add it to the left node AddTo(node.Left, value); } } // Case 2: Value is equal to or greater than the current value else { // If there is no right, add it to the right if (node.Right == null) { node.Right = new AVLTreeNode <T>(value, node, this); } else { // else add it to the right node AddTo(node.Right, value); } } node.Balance(); }
// Алгоритм рекурсивного добавления нового узла в дерево. private void AddTo(AVLTreeNode <T> node, T value) { // Вариант 1: Добавление нового значения в дерево. Значение добавлемого узла меньше чем значение текущего узла. if (value.CompareTo(node.Value) < 0) { //Создание левого узла, если его нет. if (node.Left == null) { node.Left = new AVLTreeNode <T>(value, node, this); } else { // Переходим к следующему левому узлу AddTo(node.Left, value); } } // Вариант 2: Добавлемое значение больше или равно текущему значению. else { //Создание правого узла, если его нет. if (node.Right == null) { node.Right = new AVLTreeNode <T>(value, node, this); } else { // Переход к следующему правому узлу. AddTo(node.Right, value); } } node.Balance(); }
// Recursive add algorithm private void AddTo(AVLTreeNode <T> node, T value) { // Case 1: Value is less than the current node value if (value.CompareTo(node.Value) < 0) { // if there is no left child make this the new left if (node.Left == null) { node.Left = new AVLTreeNode <T>(value, node, this); } else { // recursively add it to the left node AddTo(node.Left, value); } } // Case 2: Value is equal to or greater than the current value else { // if there is no right, add it to the right if (node.Right == null) { node.Right = new AVLTreeNode <T>(value, node, this); } else { // recursively add it to the right node AddTo(node.Right, value); } } // Add can cause tree to be not balanced, // so we call node's balance function to make sure // the node will be balanced node.Balance(); }
public bool Remove(T value) { AVLTreeNode <T> current; current = Find(value); if (current == null) { return(false); } AVLTreeNode <T> treeToBalance = current.Parent; Count--; if (current.Right == null) { if (current.Parent == null) { Head = current.Left; if (Head != null) { Head.Parent = null; } } else { int result = current.Parent.CompareTo(current.Value); if (result > 0) { current.Parent.Left = current.Left; } else if (result < 0) { current.Parent.Right = current.Left; } } } else if (current.Right.Left == null) { current.Right.Left = current.Left; if (current.Parent == null) { Head = current.Right; if (Head != null) { Head.Parent = null; } } else { int result = current.Parent.CompareTo(current.Value); if (result > 0) { current.Parent.Left = current.Right; } else if (result < 0) { current.Parent.Right = current.Right; } } } else { AVLTreeNode <T> leftmost = current.Right.Left; while (leftmost.Left != null) { leftmost = leftmost.Left; } leftmost.Parent.Left = leftmost.Right; leftmost.Left = current.Left; leftmost.Right = current.Right; if (current.Parent == null) { Head = leftmost; if (Head != null) { Head.Parent = null; } } else { int result = current.Parent.CompareTo(current.Value); if (result > 0) { current.Parent.Left = leftmost; } else if (result < 0) { current.Parent.Right = leftmost; } } } if (treeToBalance != null) { treeToBalance.Balance(); } else { if (Head != null) { Head.Balance(); } } return(true); }
public bool Remove(T value) { AVLTreeNode <T> current; current = Find(value); // находим узел с удаляемым значением if (current == null) // узел не найден { return(false); } AVLTreeNode <T> treeToBalance = current.Parent; // баланс дерева относительно узла родителя Count--; // уменьшение колиества узлов // Вариант 1: Если удаляемый узел не имеет правого потомка if (current.Right == null) // если нет правого потомка { if (current.Parent == null) // удаляемый узел является корнем { Head = current.Left; // на место корня перемещаем левого потомка if (Head != null) { Head.Parent = null; // убераем ссылку на родителя } } else // удаляемый узел не является корнем { int result = current.Parent.CompareTo(current.Value); if (result > 0) { // Если значение родительского узла больше значения удаляемого, // сделать левого потомка удаляемого узла, левым потомком родителя. current.Parent.Left = current.Left; } else if (result < 0) { // Если значение родительского узла меньше чем удаляемого, // сделать левого потомка удаляемого узла - правым потомком родительского узла. current.Parent.Right = current.Left; } } } // Вариант 2: Если правый потомок удаляемого узла не имеет левого потомка, тогда правый потомок удаляемого узла // становится потомком родительского узла. else if (current.Right.Left == null) // если у правого потомка нет левого потомка { current.Right.Left = current.Left; if (current.Parent == null) // текущий элемент является корнем { Head = current.Right; if (Head != null) { Head.Parent = null; } } else { int result = current.Parent.CompareTo(current.Value); if (result > 0) { // Если значение узла родителя больше чем значение удаляемого узла, // сделать правого потомка удаляемого узла, левым потомком его родителя. current.Parent.Left = current.Right; } else if (result < 0) { // Если значение родительского узла меньше значения удаляемого, // сделать правого потомка удаляемого узла - правым потомком родителя. current.Parent.Right = current.Right; } } } // Вариант 3: Если правый потомок удаляемого узла имеет левого потомка, // заместить удаляемый узел, крайним левым потомком правого потомка. else { // Нахожление крайнего левого узла для правого потомка удаляемого узла. AVLTreeNode <T> leftmost = current.Right.Left; while (leftmost.Left != null) { leftmost = leftmost.Left; } // Родительское правое поддерево становится родительским левым поддеревом. leftmost.Parent.Left = leftmost.Right; // Присвоить крайнему левому узлу, ссылки на правого и левого потомка удаляемого узла. leftmost.Left = current.Left; leftmost.Right = current.Right; if (current.Parent == null) { Head = leftmost; if (Head != null) { Head.Parent = null; } } else { int result = current.Parent.CompareTo(current.Value); if (result > 0) { // Если значение родительского узла больше значения удаляемого, // сделать крайнего левого потомка левым потомком родителя удаляемого узла. current.Parent.Left = leftmost; } else if (result < 0) { // Если значение родительского узла, меньше чем значение удаляемого, // сделать крайнего левого потомка, правым потомком родителя удаляемого узла. current.Parent.Right = leftmost; } } } if (treeToBalance != null) { treeToBalance.Balance(); } else { if (Head != null) { Head.Balance(); } } return(true); }
/// <summary> /// Removes the first occurance of the specified value from the tree. /// </summary> /// <param name="value">The value to remove</param> /// <returns>True if the value was removed, false otherwise</returns> public bool Remove(T value) { AVLTreeNode <T> current; // Find the node to remove current = Find(value); // If no such node, then just return false if (current == null) { return(false); } AVLTreeNode <T> treeToBalance = current.Parent; _count--; // Case 1: If current has no right child, then // current's left replaces current if (current.Right == null) { // The node to be removed is the head node if (current.Parent == null) { _head = current.Left; if (_head != null) { _head.Parent = null; } } else { // This is to determine after the current's left replaces current, // it should be the left child or the right child of current's parent node. int result = current.Parent.CompareTo(current.Value); if (result > 0) { // if parent value is greater than current value // make the current's left child a left child of parent current.Parent.Left = current.Left; } else if (result < 0) { // if parent value is less than current value // make the current's left child a right child of parent current.Parent.Right = current.Left; } } } // Case 2: If current's right child has no left child, then current's // right child replaces current // first we move current's left child to its right child's left child since it has no left child. // the reason we can do this is because current's right must be bigger than current, but // current's left must be smaller than current, so it's safe to make such move. else if (current.Right.Left == null) { current.Right.Left = current.Left; if (current.Parent == null) { _head = current.Right; if (_head != null) { _head.Parent = null; } } else { int result = current.Parent.CompareTo(current.Value); if (result > 0) { // if parent value is greater than current value // make the current's right child a left child of parent current.Parent.Left = current.Right; } else if (result < 0) { // if parent value is less than current value // make the current right child a right child of parent current.Parent.Right = current.Right; } } } // Case 3: current's right has a left child, then replace current with current's // right child's left-most child. // Seems complicated but the reason is actually straightforward. // Current's right must be bigger than current, and current's right's left-most node // must be the least bigger value compared to current, so it needs to be replaced by // that value. else { // Find the right's left-most child // start with current.Right.Left as first AVLTreeNode <T> leftmost = current.Right.Left; while (leftmost.Left != null) { leftmost = leftmost.Left; } // if the leftmost node has a right child, make that right child // as leftmost's parent's left child leftmost.Parent.Left = leftmost.Right; // assign leftmost's left and right to current's left and right children leftmost.Left = current.Left; leftmost.Right = current.Right; if (current.Parent == null) { _head = leftmost; if (_head != null) { _head.Parent = null; } } else { int result = current.Parent.CompareTo(current.Value); if (result > 0) { // if parent value is greater than current value // make leftmost the parent's left child current.Parent.Left = leftmost; } else if (result < 0) { // if parent value is less than current value // make leftmost the parent's right child current.Parent.Right = leftmost; } } } // Removal done, need to consider balancing if (treeToBalance != null) { treeToBalance.Balance(); } else { if (_head != null) { _head.Balance(); } } return(true); }
/// <summary> /// Removes the first occurance of the specified value from the tree. /// </summary> /// <param name="value">The value to remove</param> /// <returns>True if the value was removed, false otherwise</returns> public bool Remove(T value) { var current = Find(value); if (current == null) { return(false); } var treeToBalance = current.Parent; Count--; // Case 1: If current has no right child, then current's left replaces current if (current.Right == null) { if (current.Parent == null) { _head = current.Left; if (_head != null) { _head.Parent = null; } } else { var result = current.Parent.CompareTo(current.Value); if (result > 0) { // if parent value is greater than current value make the current left child a left child of parent current.Parent.Left = current.Left; } else if (result < 0) { // if parent value is less than current value make the current left child a right child of parent current.Parent.Right = current.Left; } } } // Case 2: If current's right child has no left child, then current's right child // replaces current else if (current.Right.Left == null) { current.Right.Left = current.Left; if (current.Parent == null) { _head = current.Right; if (_head != null) { _head.Parent = null; } } else { var result = current.Parent.CompareTo(current.Value); if (result > 0) { // if parent value is greater than current value make the current right child a left child of parent current.Parent.Left = current.Right; } else if (result < 0) { // if parent value is less than current value make the current right child a right child of parent current.Parent.Right = current.Right; } } } // Case 3: If current's right child has a left child, replace current with current's // right child's left-most child else { // find the right's left-most child var leftmost = current.Right.Left; while (leftmost.Left != null) { leftmost = leftmost.Left; } // the parent's left subtree becomes the leftmost's right subtree leftmost.Parent.Left = leftmost.Right; // assign leftmost's left and right to current's left and right children leftmost.Left = current.Left; leftmost.Right = current.Right; if (current.Parent == null) { _head = leftmost; if (_head != null) { _head.Parent = null; } } else { var result = current.Parent.CompareTo(current.Value); if (result > 0) { // if parent value is greater than current value make leftmost the parent's left child current.Parent.Left = leftmost; } else if (result < 0) { // if parent value is less than current value make leftmost the parent's right child current.Parent.Right = leftmost; } } } if (treeToBalance != null) { treeToBalance.Balance(); } else { _head?.Balance(); } return(true); }