I. Preface Overview
In the previous blog posts "Introduction to algorithms-balanced binary tree-construction, insertion, query, and destruction" and "Introduction to algorithms-balanced binary tree-printing", we have provided the construction, insertion, query, and printing of algorithms. and destroy the C language implementation process of the balanced binary tree, the relevant struct, macros, enumeration, and functions in this article can be found in the above two articles. The primary reason for this is that the process of deleting a balanced binary tree is relatively complicated, and there are always various problems in the testing and implementation processes, which are not completely solved until today, the processing of a balanced binary tree can finally come to an end.
Ii. Handling ideas although the code for deleting a balanced binary tree node is complicated and the amount of code is large, the deletion process is only in the following three situations: [Note: as long as you firmly grasp the following three points, it is not too difficult to understand how to delete a balanced binary tree]
① The deleted node is a leaf node.
Solution: Delete the node from the tree directly, and use recursive features and height changes to determine whether the parent node and the ancestor node are out of balance. If there is an imbalance, determine the type of imbalance (LL, LR, RR, RL), and then rotate the unbalanced node until the root node or height does not change.
② The deleted node only has the left subtree or the right subtree.
Solution: Replace the left subtree (right subtree) with the original node location, and use recursive characteristics and height changes to determine whether the parent node and the ancestor node are out of balance. If there is an imbalance, determine the type of imbalance (LL, LR, RR, RL), and then rotate the unbalanced node until the root node or height does not change.
③ The deleted node has both the left subtree and the right subtree.
Solution: Find the rightmost node rnode of the Left subtree whose knots are deleted, assign the rnode value to the node, and then replace the left child of the rnode with the location of the rnode, release the rnode and use recursive features to reverse infer whether the parent and grandfather nodes of the rnode are out of balance. If there is an imbalance, determine the type of imbalance (LL, LR, RR, RL), and then rotate the unbalanced node until the root node or height does not change.
Iii. Code Implementation
/*************************************** **************************************** * Function Name: avl_delete ** function: delete a key value node (external interface) ** input parameter: ** tree: balanced binary tree ** key: deleted keyword ** output parameter: NONE ** return: AVL_SUCCESS: Successful AVL_FAILED: Failed ** implementation Description: ** Note: ** OPERATOR: # Qifeng. zou #2013.12.19 #************************************ **************************************** **/int avl_delete (avl_tree_t * tree, int key) {bool lower = false;/* whether the record height is reduced */if (NULL = tree-> root) {return AVL_SUCCESS;} return avl_search_and_delete (tree, tree-> root, key, & lower );}
Code 1 delete a node (external interface)
/*************************************** **************************************** * Function Name: avl_search_and_delete ** function: search for and delete a specified key value node (Internal interface) ** input parameter: ** tree: Balance Binary tree ** node: ** key: deleted keyword ** output parameter: ** lower: whether the height is reduced ** return: AVL_SUCCESS: Successful AVL_FAILED: failed ** implementation Description: ** Note: ** OPERATOR: # Qifeng. zou #2013.12.19 #************************************ **************************************** **/int avl_search_and_delete (avl_tree_t * tree, avl_node_t * node, int key, bool * lower) {avl_node_t * parent = node-> parent;/* 1. find the node to be deleted */if (key <node-> key)/* search for the left subtree */{if (NULL = node-> lchild) {return AVL_SUCCESS ;} avl_search_and_delete (tree, node-> lchild, key, lower); if (true = * lower) {return avl_delete_left_balance (tree, node, lower);} return AVL_SUCCESS ;} else if (key> node-> key)/* search for */{if (NULL = node-> rchild) {return AVL_SUCCESS;} avl_search_and_delete (tree, node-> rchild, key, lower); if (true = * lower) {return avl_delete_right_balance (tree, node, lower);} return AVL_SUCCESS;}/* 2. you have found the node to be deleted. * // * 2.1 The right subtree is empty. You only need to pick up the left subtree of the node (this also applies to the leaf node) */if (NULL = node-> rchild) {* lower = true; avl_replace_child (tree, parent, node, node-> lchild); free (node ), node = NULL; return AVL_SUCCESS;}/* 2.2 left subtree is empty, just pick up its right subtree */else if (NULL = node-> lchild) {* lower = true; avl_replace_child (tree, parent, node, node-> rchild) free (node), node = NULL; return AVL_SUCCESS ;} /* left and right subtree not blank: Find the node on the far right of the Left subtree to replace the deleted node */avl_replace_and_delete (tree, node, node-> lchild, lower ); if (true = * lower) {avl_print (tree); return avl_delete_left_balance (tree, node, lower);} return AVL_SUCCESS ;}
Code 2: Find and delete a node (Internal interface)
/*************************************** **************************************** * Function Name: avl_replace_and_delete ** function: Find the replaced node and replace the deleted node (Internal interface). ** input parameter: ** tree: balanced binary tree ** dnode: ** rnode: the rightmost node of the deleted node is used to replace the deleted node. ** output parameter: ** lower: whether the height is changed ** return: AVL_SUCCESS: AVL_FAILED: Failed ** implementation Description: ** note: **> In fact, The dnode is not deleted here, but the rnode value is given to the dnode and then deleted. ** due to the recursive algorithm used here, if you release the dnode, it will cause an error in the stack pressure information! ** OPERATOR: # Qifeng. zou #2013.12.19 #************************************ **************************************** **/int avl_replace_and_delete (avl_tree_t * tree, avl_node_t * dnode, avl_node_t * rnode, bool * lower) {avl_node_t * parent = NULL, * rparent = NULL; if (NULL = rnode-> rchild) {* lower = true; parent = dnode-> parent; rparent = rnode-> parent; dnode-> key = rnode-> key;/* Note: the rnode value is assigned to dnode */if (rnode = dnode-> lchild) {avl_set_lchild (dnode, rnode-> lchild ); /* rnode-> parent = dnode node may be out of balance. This process is handed over to the function handler of the front stack */} else {avl_set_rchild (rparent, rnode-> lchild ); /* the parent node of the rnode may be out of balance. This processing is handed over to the function processing function of the front stack */} free (rnode), rnode = NULL;/* Note: The released node is not a dnode, instead, rnode */return AVL_SUCCESS;} avl_replace_and_delete (tree, dnode, rnode-> rchild, lower); if (true = * lower) {/* the parent node of dnode may be out of balance, this process is handed over to the function of the front stack for processing, but the dnode may be used. Therefore, you must handle */avl_delete_right_balance (tree, rnode, lower);} return AVL_SUCCESS;} here ;}
Code 3 replace and delete a node (Internal interface)
/*************************************** **************************************** * Function Name: avl_delete_left_balance ** function: a node in the left subtree of a node is deleted. After the left height is reduced, the balancer (Internal interface) ** input parameter: ** tree: balanced binary tree ** node: a node in the left subtree of the node has been deleted ** output parameter: ** lower: height changed ** return: AVL_SUCCESS: Successful AVL_FAILED: failed ** implementation Description: ** Note: ** OPERATOR: # Qifeng. zou #2013.12.19 #************************************ **************************************** **/int avl_delete_left_balance (avl_tree_t * tree, avl_node_t * node, bool * lower) {avl_node_t * rchild = NULL, * rlchild = NULL, * parent = node-> parent; switch (node-> bf) {case LH: /* left Height: height of the Left subtree decreases by 1. */{node-> bf = EH; * lower = true; break;} case EH:/* Height: height of the Left subtree minus 1 tree height unchanged */{node-> bf = RH; * lower = false; break;} case RH:/* Right height: left subtree height minus 1 tree out of balance */{rchild = node-> rchild; switch (rchild-> bf) {case EH:/* RR type: rotate left */case RH:/* RR type: Rotate left */{if (EH = rchild-> bf) {* lower = false; rchild-> bf = LH; node-> bf = RH;} else if (RH = rchild-> bf) {* lower = true; rchild-> bf = EH; node-> bf = EH;} avl_set_rchild (node, rchild-> lchild); avl_set_lchild (rchild, node); avl_replace_child (tree, parent, node, rchild); break ;} case LH:/* RL type: First rotate to the right and then rotate to the left */{* lower = true; rlchild = rchild-> lchild; switch (rlchild-> bf) {case LH: {node-> bf = EH; rchild-> bf = RH; rlchild-> bf = EH; break;} case EH: {node-> bf = EH; rchild-> bf = EH; rlchild-> bf = EH; break;} case RH: {node-> bf = LH; rchild-> bf = EH; rlchild-> bf = EH; break;} avl_set_rchild (node, rlchild-> lchild); avl_set_lchild (rchild, rlchild-> rchild); avl_set_lchild (rlchild, node ); avl_set_rchild (rlchild, rchild); avl_replace_child (tree, parent, node, rlchild); break ;}} break ;}return AVL_SUCCESS ;}
Code 4: Balance processing after the left subtree height is reduced
/*************************************** **************************************** * Function Name: avl_delete_right_balance ** function: a node in the right subtree of a node is deleted. After the left height is reduced, the balancer (Internal interface) ** input parameter: ** tree: balanced binary tree ** node: a node in the right subtree of a node has been deleted ** output parameter: ** lower: height changed ** return: AVL_SUCCESS: AVL_FAILED: failed ** implementation Description: ** Note: ** OPERATOR: # Qifeng. zou #2013.12.19 #************************************ **************************************** **/int avl_delete_right_balance (avl_tree_t * tree, avl_node_t * node, bool * lower) {avl_node_t * lchild = NULL, * lrchild = NULL, * parent = node-> parent; switch (node-> bf) {case LH: /* left Height: right subtree height minus 1 tree out of balance */{lchild = node-> lchild; switch (lchild-> bf) {case EH:/* LL type: right rotation */case LH:/* LL type: Right rotation */{if (EH = lchild-> bf) {* lower = false; lchild-> bf = RH; node-> bf = LH;} else {* lower = true; lchild-> bf = EH; node-> bf = EH;} avl_set_lchild (node, lchild-> rchild ); avl_set_rchild (lchild, node); avl_replace_child (tree, parent, node, lchild); break;} case RH:/* LR: first rotate left and then right */{* lower = true; lrchild = lchild-> rchild; switch (lrchild-> bf) {case LH: {node-> bf = RH; lchild-> bf = EH; lrchild-> bf = EH; break;} case EH: {node-> bf = EH; lchild-> bf = EH; lrchild-> bf = EH; break;} case RH: {node-> bf = EH; lchild-> bf = LH; lrchild-> bf = EH; break;} avl_set_lchild (node, lrchild-> rchild); avl_set_rchild (lchild, lrchild-> lchild); avl_set_rchild (lrchild, node ); avl_set_lchild (lrchild, lchild); avl_replace_child (tree, parent, node, lrchild); break ;}} high case EH: the height of the right subtree is reduced by 1. The height of the tree remains unchanged */{node-> bf = LH; * lower = false; break;} case RH:/* Right height: the height of the right subtree is reduced by 1. */{node-> bf = EH; * lower = true; break ;}} return AVL_SUCCESS ;}
Code 5: Balance processing after the height of the right subtree is reduced
/* # Check whether the pointer of a node has an exception # Very effective! */Void avl_assert (avl_node_t * node) {if (NULL = node) | (NULL = node-> parent) {return ;} if (node-> parent-> lchild! = Node) & (node-> parent-> rchild! = Node) {assert (0);} if (node-> parent = node-> lchild) | (node-> parent = node-> rchild )) {assert (0 );}}
Code 6 node Detection
4. The left figure of the processing result is the original balanced binary tree. After multiple nodes are randomly deleted, the right figure is displayed. We can see that the right graph is still a balanced binary tree.
Figure 1 test results
-- MA Qifeng
December 20, 2013