}
}
+VOID
+FORCEINLINE
+RtlpDeleteAvlTreeNode(IN PRTL_AVL_TABLE Table,
+ IN PRTL_BALANCED_LINKS Node)
+{
+ PRTL_BALANCED_LINKS DeleteNode, ParentNode;
+ PRTL_BALANCED_LINKS *Node1, *Node2;
+ CHAR Balance;
+
+ /* Take one of the children if possible */
+ if (!(RtlLeftChildAvl(Node)) || !(RtlRightChildAvl(Node))) DeleteNode = Node;
+
+ /* Otherwise, check if one side is longer */
+ if (!(DeleteNode) && (RtlBalance(Node) >= RtlBalancedAvlTree))
+ {
+ /* Pick the successor which will be the longest side in this case */
+ DeleteNode = RtlRightChildAvl(Node);
+ while (RtlLeftChildAvl(DeleteNode)) DeleteNode = RtlLeftChildAvl(DeleteNode);
+ }
+ else if (!DeleteNode)
+ {
+ /* Pick the predecessor which will be the longest side in this case */
+ DeleteNode = RtlLeftChildAvl(Node);
+ while (RtlRightChildAvl(DeleteNode)) DeleteNode = RtlRightChildAvl(DeleteNode);
+ }
+
+ /* Get the parent node */
+ ParentNode = RtlParentAvl(DeleteNode);
+
+ /* Pick which now to use based on whether or not we have a left child */
+ Node1 = RtlLeftChildAvl(DeleteNode) ? &DeleteNode->LeftChild : &DeleteNode->RightChild;
+
+ /* Pick which node to swap based on if we're already a left child or not */
+ Node2 = RtlIsLeftChildAvl(DeleteNode) ? &ParentNode->LeftChild : &ParentNode->RightChild;
+
+ /* Pick the correct balance depending on which side will get heavier */
+ Balance = RtlIsLeftChildAvl(DeleteNode) ? RtlLeftHeavyAvlTree : RtlRightHeavyAvlTree;
+
+ /* Swap the children nodes, making one side heavier */
+ *Node2 = *Node1;
+
+ /* If the node has a child now, update its parent */
+ if (*Node1) RtlSetParent(*Node1, ParentNode);
+
+ /* Assume balanced root for loop optimization */
+ RtlSetBalance(&Table->BalancedRoot, RtlBalancedAvlTree);
+
+ /* Loop up the tree by parents */
+ while (TRUE)
+ {
+ /* Check if the tree's balance increased */
+ if (RtlBalance(ParentNode) == Balance)
+ {
+ /* Now the tree is balanced */
+ RtlSetBalance(ParentNode, RtlBalancedAvlTree);
+ }
+ else if (RtlBalance(ParentNode) == RtlBalancedAvlTree)
+ {
+ /* The tree has now become less balanced, since it was balanced */
+ RtlSetBalance(ParentNode, -Balance);
+
+ /* Deal with the loop optimization to detect loss of a tree level */
+ if (RtlBalance(&Table->BalancedRoot) != RtlBalancedAvlTree) Table->DepthOfTree--;
+ break;
+ }
+ else
+ {
+ /* The tree has become unbalanced, so a rebalance is needed */
+ if (RtlpRebalanceAvlTreeNode(ParentNode)) break;
+
+ /* Get the new parent after the balance */
+ ParentNode = RtlParentAvl(ParentNode);
+ }
+
+ /* Choose which balance factor to use based on which side we're on */
+ Balance = RtlIsRightChild(ParentNode) ?
+ RtlRightHeavyAvlTree : RtlLeftHeavyAvlTree;
+
+ /* Iterate up the tree */
+ ParentNode = RtlParentAvl(ParentNode);
+ }
+
+ /* Check if this isn't the node we ended up deleting directly */
+ if (Node == DeleteNode) return;
+
+ /* Copy the deleted node itself */
+ RtlpCopyAvlNodeData(DeleteNode, Node);
+
+ /* Pick the right node to unlink */
+ Node1 = RtlIsLeftChildAvl(Node) ?
+ &(RtlParentAvl(DeleteNode))->LeftChild : &(RtlParentAvl(DeleteNode))->RightChild;
+ *Node1 = DeleteNode;
+
+ /* Reparent as appropriate */
+ if (RtlLeftChildAvl(DeleteNode)) RtlSetParent(RtlLeftChildAvl(DeleteNode), DeleteNode);
+ if (RtlRightChildAvl(DeleteNode)) RtlSetParent(RtlRightChildAvl(DeleteNode), DeleteNode);
+}
+
/* EOF */
RtlDeleteElementGenericTableAvl(IN PRTL_AVL_TABLE Table,
IN PVOID Buffer)
{
- UNIMPLEMENTED;
- return FALSE;
+ PRTL_BALANCED_LINKS Node;
+ TABLE_SEARCH_RESULT SearchResult;
+
+ /* Find the node */
+ SearchResult = RtlpFindAvlTableNodeOrParent(Table, Buffer, &Node);
+ if (SearchResult != TableFoundNode) return FALSE;
+
+ /* If this node was the key, update it */
+ if (Node == Table->RestartKey) Table->RestartKey = RtlRealPredecessorAvl(Node);
+
+ /* Do the delete */
+ Table->DeleteCount++;
+ RtlpDeleteAvlTreeNode(Table, Node);
+ Table->NumberGenericTableElements--;
+
+ /* Reset accounting */
+ Table->WhichOrderedElement = 0;
+ Table->OrderedPointer = NULL;
+
+ /* Free the node's data */
+ Table->FreeRoutine(Table, Node);
+
+ /* It's done */
+ return TRUE;
}
/* EOF */