There are a lot of online resources on the principle of balancing binary trees, and the situation is a little complicated. so I will not describe them here. let's go directly to the code: there are a lot of online resources on the principle of balancing binary trees, and the situation is a little complicated. so I will not describe them here. let's go directly to the code:
Key = $ key; $ this-> parent = NULL; $ this-> left = NULL; $ this-> right = NULL; $ this-> bf = 0 ;}} // balanced binary tree class Avl {public $ root; const LH = + 1; // left high const EH = 0; // high level const RH =-1; // right high/*** initialize the tree structure * @ param $ arr initialize the tree structure array * @ return null */public function init ($ arr) {$ this-> root = new Node ($ arr [0]); for ($ I = 1; $ I <count ($ arr); $ I ++) {$ this-> Insert ($ arr [$ I]) ;}/ *** (internal) sequential traversal * @ param $ root (tree Or subtree) root node * @ return null */private function mid_order ($ root) {if ($ root! = NULL) {$ this-> mid_order ($ root-> left); echo $ root-> key. "-". $ root-> bf. ""; $ this-> mid_order ($ root-> right) ;}}/*** (external) in-order traversal * @ param null * @ return null */public function MidOrder () {$ this-> mid_order ($ this-> root );} /*** right-hand processing of the minimum unbalanced binary tree with $ root as the root node * @ param $ root (tree or subtree) root node * @ return null */private function R_Rotate ($ root) {$ L = $ root-> left; if (! Is_NULL ($ root-> parent) {$ P = $ root-> parent; if ($ root = $ P-> left) {$ P-> left = $ L;} else {$ P-> right = $ L;} $ L-> parent = $ P ;} else {$ L-> parent = NULL;} $ root-> parent = $ L; $ root-> left = $ L-> right; $ L-> right = $ root; // This sentence is required! If ($ L-> parent = NULL) {$ this-> root = $ L ;}} /*** perform left-hand processing on the minimum unbalanced binary tree with $ root as the root node * @ param $ root (tree or subtree) root node * @ return null */private function L_Rotate ($ root) {$ R = $ root-> right; if (! Is_NULL ($ root-> parent) {$ P = $ root-> parent; if ($ root = $ P-> left) {$ P-> left = $ R;} else {$ P-> right = $ R;} $ R-> parent = $ P ;} else {$ R-> parent = NULL;} $ root-> parent = $ R; $ root-> right = $ R-> left; $ R-> left = $ root; // This sentence is required! If ($ R-> parent = NULL) {$ this-> root = $ R ;}} /*** perform left-balanced processing on the binary tree whose nodes refer to $ root as the root node * @ param $ root (tree or subtree) root node * @ return null */public function LeftBalance ($ root) {$ L = $ root-> left; $ L_bf = $ L-> bf; switch ($ L_bf) {// check the balance of the left subtree of the root user and perform corresponding balancing. case self: LH: // insert the new node to the left subtree of the root user, perform a single right-hand processing $ root-> bf = $ L-> bf = self: EH; $ this-> R_Rotate ($ root); break; case self: RH: // insert the new node to the right subtree of the left child of the root node and perform double rotation. $ L_r = $ L-> r Ight; // root the right child root of the left child $ L_r_bf = $ L_r-> bf; // modify the balance factor switch ($ L_r_bf) of the root and its left child {case self :: LH: $ root-> bf = self: RH; $ L-> bf = self: EH; break; case self: EH: $ root-> bf = $ L-> bf = self: EH; break; case self: RH: $ root-> bf = self: EH; $ L-> bf = self: LH; break;} $ L_r-> bf = self: EH; // perform left balancing on the left subtree of root $ this-> L_Rotate ($ L ); // perform right balancing on root $ this-> R_Rotate ($ root );}} /*** perform right balancing on the binary tree with the node $ root as the root node * @ par Am $ root (tree or subtree) root node * @ return null */public function RightBalance ($ root) {$ R = $ root-> right; $ R_bf = $ R-> bf; switch ($ R_bf) {// check the balance of the right subtree of the root user and perform corresponding balancing. case self: RH: // insert the new node to the right tree of the right child of the root node. perform a single left-hand processing. $ root-> bf = $ R-> bf = self: EH; $ this-> L_Rotate ($ root); break; case self: LH: // insert the new node to the left tree of the right child of the root node, to perform double rotation, $ R_l = $ R-> left; // root the left subtree of the right child $ R_l_bf = $ R_l-> bf; // modify the balance factor switch ($ R_l_bf) of root and its right child {case s Elf: RH: $ root-> bf = self: LH; $ R-> bf = self: EH; break; case self: EH: $ root-> bf = $ R-> bf = self: EH; break; case self: LH: $ root-> bf = self: EH; $ R-> bf = self: RH; break;} $ R_l-> bf = self: EH; // perform right balancing on the right subtree of root $ this-> R_Rotate ($ R ); // perform left balancing on root $ this-> L_Rotate ($ root );}} /*** check whether the node corresponding to $ key exists in the search tree * @ param $ key: number to be searched * @ return $ key corresponding node */public function search ($ key) {$ current = $ this-> root; w Hile ($ current! = NULL) {if ($ current-> key ==$ key) {return $ current;} elseif ($ current-> key> $ key) {$ current = $ current-> left;} else {$ current = $ current-> right;} return $ current ;} /*** search for the smallest keyword in the tree * @ param $ root node * @ return node corresponding to the smallest keyword */function search_min ($ root) {$ current = $ root; while ($ current-> left! = NULL) {$ current = $ current-> left;} return $ current ;} /*** find the maximum keyword in the tree * @ param $ root node * @ return the node corresponding to the maximum keyword */function search_max ($ root) {$ current = $ root; while ($ current-> right! = NULL) {$ current = $ current-> right;} return $ current ;} /*** find the direct precursor node of a $ key in the middle order * @ param $ x reference of the node to be searched for the precursor node * @ return */private function predecessor ($ x) {// if ($ x-> left! = NULL) {return $ this-> search_max ($ x-> left) ;}// otherwise, find the parent node, until the current node is located on the right of the parent node $ p = $ x-> parent; // if x is the left child of p, it indicates that p is the successor of x, we need to find that p is the precursor of x while ($ p! = NULL & $ x = $ p-> left) {$ x = $ p; $ p = $ p-> parent;} return $ p ;} /*** find the direct successor node of a $ key in the middle order * @ param $ x reference of the node to be searched for the successor node * @ return reference of the successor node */private function successor ($ x) {if ($ x-> left! = NULL) {return $ this-> search_min ($ x-> right);} $ p = $ x-> parent; while ($ p! = NULL & $ x ==$ p-> right) {$ x = $ p; $ p = $ p-> parent;} return $ p ;} /*** (internal) insert a node. if the node does not exist, insert it, balance loss * @ param $ root node $ key number of the tree to be inserted * @ return null */private function insert_node (& $ root, $ key) {// locate the inserted Node. insert the new Node if (is_null ($ root) {$ root = new Node ($ key); // return TRUE if the Node is successfully inserted ;} else {// A node already exists in the tree that is equal to $ key if ($ key = $ root-> key) {// failed to insert node return FALSE ;} // search for elseif ($ key <$ r in the left subtree of the root user Oot-> key) {// failed to insert left subtree if (! ($ This-> insert_node ($ root-> left, $ key) {// return FALSE if the tree is not long;} // Insert successfully, modify the balance factor if (is_null ($ root-> left-> parent) {$ root-> left-> parent = $ root;} switch ($ root-> bf) {// The height of the left and right subtree. now the left subtree increases while the tree increases. case self: EH: $ root-> bf = self: LH; // return TRUE if the tree length is high; break; // if the left subtree is higher than the right subtree, perform left balancing. case self: LH: $ this-> LeftBalance ($ root); // after balancing, return FALSE; break; // case self: RH: $ root-> bf = s Elf: EH; // the tree does not have a long height. return FALSE; break ;}/// search for else in the right subtree of the root user {// failed to insert the right subtree if (! $ This-> insert_node ($ root-> right, $ key) {// return FALSE if the tree is not long;} // Insert successfully, modify the balance factor if (is_null ($ root-> right-> parent) {$ root-> right-> parent = $ root;} switch ($ root-> bf) {// The height of the left and right subtree. now the right subtree increases while the tree increases. case self: EH: $ root-> bf = self: RH; // return TRUE; break; // case self: LH: $ root-> bf = self: EH; return FALSE; break; // if the original right subtree is greater than the left subtree, perform right balancing. case self: RH: $ this-> RightBalance ($ root );// Return FALSE; break ;}}/ *** (external) insert $ key into the tree * @ param $ key number of the tree to be inserted * @ return null */public function Insert ($ key) {$ this-> insert_node ($ this-> root, $ key);}/*** get the node to be deleted (the deleted final node) * @ param $ key the number to be deleted * @ return the final deleted node */private function get_del_node ($ key) {$ dnode = $ this-> search ($ key ); if ($ dnode = NULL) {throw new Exception ("The node does not exist! "); Return;} if ($ dnode-> left = NULL | $ dnode-> right = NULL) {# if the node to be deleted has no subnode or only one subnode, c = dnode $ c = $ dnode;} else {# if the node to be deleted has two subnodes, c is the direct successor of the dnode, and the value of the node to be deleted is changed to the value of the subsequent node $ c = $ this-> successor ($ dnode );} $ dnode-> key = $ c-> key; return $ c;}/*** (internal) delete a specified node, the balance factor * @ param $ node for processing the upstream node of the node eventually deletes the node * @ return null */private function del_node ($ node) {if ($ node = $ this-> root) {$ this-> root = NULL; retu Rn;} $ current = $ node; // There are only two types of node: either one subnode or no subnode $ P = $ current-> parent; // delete a node. the balance of the first parent node will change. $ lower = TRUE; while ($ lower = TRUE &&! Is_null ($ P) {// The node to be deleted is the left node if ($ current = $ P-> left) {if ($ current = $ node) {if (! Is_null ($ current-> left) {$ P-> left = $ current-> left;} else {$ P-> left = $ current-> left ;}} $ P_bf = $ P-> bf; switch ($ P_bf) {case self: LH: $ P-> bf = self: EH; $ lower = TRUE; $ current = $ P; $ P = $ current-> parent; break; case self: EH: $ P-> bf = self: RH; $ lower = FALSE; break; case self: RH: $ this-> RightBalance ($ P); $ lower = TRUE; $ current = $ P-> parent; $ P = $ current-> parent; break;} // right else {If ($ current = $ node) {if (! Is_null ($ current-> left) {$ P-> right = $ current-> left;} else {$ P-> right = $ current-> left ;}} $ P_bf = $ P-> bf; switch ($ P_bf) {case self: LH: $ this-> LeftBalance ($ P); $ lower = TRUE; $ current = $ P-> parent; $ P = $ current-> parent; break; case self: EH: $ P-> bf = self: LH; $ lower = FALSE; break; case self: RH: $ P-> bf = self: LH; $ lower = TRUE; $ current = $ P; $ P = $ current-> parent; break ;}}}}/*** (External) Delete a specified node * @ param $ key Delete the key value of the node * @ return null */public function Delete ($ key) {$ del_node = $ this-> get_del_node ($ key); $ this-> del_node ($ del_node);}/*** (internal) obtain the depth of the tree * @ param $ root node * @ return tree depth */private function getdepth ($ root) {if ($ root = NULL) {return 0 ;} $ dl = $ this-> getdepth ($ root-> left); $ dr = $ this-> getdepth ($ root-> right); return ($ dl> $ dr? $ Dl: $ dr) + 1;}/*** (external) obtain the Depth of the tree * @ param null * @ return null */public function Depth () {return $ this-> getdepth ($ this-> root );}}
During debugging, you can call the middle-order traversal method. in my previous blog, we provided a binary tree graph implemented by PHP. with visual help, we can better help with debugging, for details, visit my previous blog: "Using PHP to display binary tree Images".
The above is the PHP binary tree (II): The balance binary tree (AVL) content, for more information, please follow the PHP Chinese network (www.php1.cn )!