/// <summary> /// Checks various properties to determine if the tree is a valid AA Tree. /// Throws exceptions if properties are violated. /// Useful for debugging. /// </summary> /// <remarks> /// The properties that are checked are: /// <list type="number"> /// <item>The level of every leaf node is one.</item> /// <item>The level of every left child is exactly one less than that of its parent.</item> /// <item>The level of every right child is equal to or one less than that of its parent.</item> /// <item>The level of every right grandchild is strictly less than that of its grandparent.</item> /// <item>Every node of level greater than one has two children.</item> /// </list> /// More information: https://en.wikipedia.org/wiki/AA_tree . /// </remarks> /// <param name="node">The node to check from.</param> /// <returns>true if node passes all checks, false otherwise.</returns> private static bool Validate <T>(AaTreeNode <T>?node) { if (node is null) { return(true); } // Check level == 1 if node if a leaf node. var leafNodeCheck = CheckLeafNode(node); // Check level of left child is exactly one less than parent. var leftCheck = CheckLeftSubtree(node); // Check level of right child is equal or one less than parent. var rightCheck = CheckRightSubtree(node); // Check right grandchild level is less than node. var grandchildCheck = CheckRightGrandChild(node); // Check if node has two children if not leaf. var nonLeafChildrenCheck = CheckNonLeafChildren(node); var thisNodeResult = leafNodeCheck && leftCheck && rightCheck; thisNodeResult = thisNodeResult && grandchildCheck && nonLeafChildrenCheck; return(thisNodeResult && Validate(node.Left) && Validate(node.Right)); }
/// <summary> /// Checks if right node's level is either equal to or one less than node's level. /// </summary> /// <param name="node">The node to check.</param> /// <returns>true if node passes check, false otherwise.</returns> private static bool CheckRightSubtree <T>(AaTreeNode <T> node) { var condition = node.Right is not null && node.Level - node.Right.Level != 1 && node.Level != node.Right.Level; return(!condition); }
/// <summary> /// Checks if node is not a leaf, and if so if it has two children. /// </summary> /// <param name="node">The node to check.</param> /// <returns>true if node passes check, false otherwise.</returns> private static bool CheckNonLeafChildren <T>(AaTreeNode <T> node) { var condition = node.Level > 1 && (node.Left is null || node.Right is null); return(!condition); }
/// <summary> /// Checks if right grandchild's (right node's right node) level is less than node. /// </summary> /// <param name="node">The node to check.</param> /// <returns>true if node passes check, false otherwise.</returns> private static bool CheckRightGrandChild <T>(AaTreeNode <T> node) { var condition = node.Right?.Right is not null && node.Right.Level < node.Right.Right.Level; return(!condition); }
/// <summary> /// Checks if node is a leaf, and if so if its level is 1. /// </summary> /// <param name="node">The node to check.</param> /// <returns>true if node passes check, false otherwise.</returns> private static bool CheckLeafNode <T>(AaTreeNode <T> node) { var condition = node.Left is null && node.Right is null && node.Level != 1; return(!condition); }