PHP binary tree (II): balanced binary tree (AVL)

Source: Internet
Author: User
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 )!

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.