PHP two fork Tree (ii): Balanced binary tree (AVL)

Source: Internet
Author: User
On the principle of balanced binary tree on-line resources are quite many, and the situation is a little complicated, so here I will no longer state, directly on the code bar:

<!--? php/** * Author:zhongjin * TIME:2016/10/20 11:53 * Description: Balanced binary tree *///node class node{public $key;    Public $parent;    Public $left;    Public $right; Public $BF;        Balance factor public Function __construct ($key) {$this--->key = $key;        $this->parent = NULL;        $this->left = NULL;        $this->right = NULL;    $this-&GT;BF = 0;    }}//balanced binary tree class avl{public $root;  Const LH = +1;   Zogao const EH = 0;  Equal-High Const RH =-1;        Right High/** * Initialize tree structure * @param an array of $arr initialization tree structure * @return NULL */Public function init ($arr) {        $this->root = new Node ($arr [0]);        for ($i = 1; $i < count ($arr), $i + +) {$this->insert ($arr [$i]);     }}/** * (internal) middle order 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-&GT;BF. " ";        $this->mid_order ($root->right); }}/** * (external) middle order traversal * @param NULL * @return NULL */Public Function Midorder () {$this-    >mid_order ($this->root); /** * The smallest unbalanced binary tree with $root as the root node is done right-handed * @param $root (tree or subtree) root node * @return NULL */Private Function R_rota        Te ($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 must be AH!        if ($L->parent = = NULL) {$this->root = $L; }}/** * The smallest unbalanced binary tree with $root as the root node is left-handed * @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 must be AH!        if ($R->parent = = NULL) {$this->root = $R; }}/** * The left balance of the two-tree that is the root node of the $root point * @param $root (tree or subtree) root node * @return NULL */Public function Le        Ftbalance ($root) {$L = $root->left;        $L _BF = $L->bf;                Switch ($L _BF) {//Check the balance of the left subtree of root and make the appropriate balance processing case SELF::LH://new node inserted in the left child tree of root left, to do single-right-handed processing                $root-&GT;BF = $L-&GT;BF = Self::eh;                $this->r_rotate ($root);            Break Case SELF::RH://NewThe node is inserted in the right subtree of the left child of the root, to do the double spin $L _r = $L->right;                Root left child's right sub root $L _R_BF = $L _r->bf;  Modify Root and its left child's balance factor switch ($L _r_bf) {case SELF::LH: $root-&GT;BF                        = SELF::RH;                        $L-&GT;BF = Self::eh;                    Break                        Case Self::eh: $root->bf = $L-&GT;BF = Self::eh;                    Break                        Case SELF::RH: $root->bf = Self::eh;                        $L-&GT;BF = SELF::LH;                Break                } $L _R-&GT;BF = Self::eh;                The Zuozi of root is left balanced $this->l_rotate ($L);        Right balance treatment of root $this->r_rotate ($root); }}/** * The right balance of the two-fork tree with the $root node as the root nodes * @param $root (tree or subtree) root node * @return NULL */Public function Ri Ghtbalance ($root) {$R = $root->righT        $R _BF = $R->bf;                Switch ($R _BF) {//Check the balance of the right subtree of root and make the appropriate balance processing case SELF::RH://new node inserted in the right subtree of root right child to do Tanzoo processing                $root-&GT;BF = $R-&GT;BF = Self::eh;                $this->l_rotate ($root);            Break   Case SELF::LH://The new node is inserted in the left subtree of the right child of the root to do the double spin $R _l = $R->left;                Root right child's Zogen $R _L_BF = $R _l->bf;  Change the balance factor switch ($R _l_bf) of root and its right child {case SELF::RH: $root-&GT;BF                        = SELF::LH;                        $R-&GT;BF = Self::eh;                    Break                        Case Self::eh: $root->bf = $R-&GT;BF = Self::eh;                    Break                        Case SELF::LH: $root->bf = Self::eh;                        $R-&GT;BF = SELF::RH;                Break                } $R _L-&GT;BF = Self::eh; To the right of rootSubtree for right balance treatment $this->r_rotate ($R);        Left balance treatment $this->l_rotate ($root) for root; }}/** * Find the $key node in the tree * @param $key number to search * @return $key corresponding node */Public Function search ($k        EY) {$current = $this->root;            while ($current! = NULL) {if ($current->key = = $key) {return $current;            } elseif ($current->key > $key) {$current = $current->left;            } else {$current = $current->right;    }} return $current;        /** * Find the Minimum keyword in the tree * @param $root root node * @return the node corresponding to the minimum keyword */function search_min ($root) {        $current = $root;        while ($current->left! = NULL) {$current = $current->left;    } return $current;        /** * Find the largest keyword in the tree * @param $root root node * @return The node for 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 sequence traversal * @param $x node reference for the precursor node to find * @return precursor node reference */Private function Predece Ssor ($x) {///left dial hand node exists, directly returns the right child node of the left child node if ($x->left! = NULL) {return $this->search_max ($x-&        Gt;left);        }//Otherwise finds its parent node until the current node is on the right side of the parent node $p = $x->parent;            If X is the left child of P, stating 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 of a $key in the middle sequence traversal * @param $x the node reference for the successor to be found * @return subsequent node reference */Private Function success        or ($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; /** * (Inward) Insert node, if the node does not exist then insert, lose balance to do balance processing * @param $root root node $key number to be inserted into the tree * @return NULL */Private FU Nction Insert_node (& $root, $key) {//found the insertion position, insert new node if (Is_null ($root)) {$root = new node            ($key);        Insert node success return TRUE; } else {//already exists in the tree and $key equal nodes if ($key = = $root->key) {//Insert node failed RET            Urn FALSE; }//In root record continue to search ElseIf ($key < $root->key) {//Insert left subtree failed if (! (                $this->insert_node ($root->left, $key))) {//Tree not long high return FALSE; }//successfully inserted, modify balance factor if (Is_null ($root->left->parent)) {$root->lef                T->parent = $root;        } switch ($root-&GT;BF) {//the original left and right sub-tree, etc., and now the tree is raised and trees increase case SELF::EH:                $root-&GT;BF = SELF::LH;                        Tree length high return TRUE;                    Break                        Originally Supi right subtree high, need to do left balance treatment case SELF::LH: $this->leftbalance ($root);                        After the balance, the tree does not grow high and return FALSE;                    Break                        The original right subtree is taller than the left sub-tree, and now the high case SELF::RH: $root->bf = Self::eh;                        The tree does not grow high and return FALSE;                Break }}//Continue searching in the right subtree of root for else {//Insert right subtree failed if (! $this->insert_node ($root                ->right, $key)) {//Tree not long high return FALSE; }//successfully inserted, modify balance factor if (Is_null ($root->right->parent)) {$root->righ                T->parent = $root; } SWITCH ($root->bf) {//the original left and right sub-tree, etc., now increase in tree height and trees increase case SELF::EH: $roo                        T-&GT;BF = SELF::RH;                        Tree length high return TRUE;                    Break                        The original Supi right sub-tree high, and now about the sub-tree and other high case SELF::LH: $root->bf = Self::eh;                        return FALSE;                    Break                        The original right subtree is taller than the left sub-tree, to do the right balance case SELF::RH: $this->rightbalance ($root);                        The tree does not grow high and return FALSE;                Break }}}}/** * (external) Insert $key into tree * @param $key number to be inserted in tree * @return NULL */Public fun    Ction Insert ($key) {$this->insert_node ($this->root, $key); /** * Gets the node to be deleted (the final node deleted) * @param $key the number to be deleted * @return the node that was eventually deleted */Private Function Get_del_node (   $key) {$dnode = $this->search ($key); if ($dnode = = NULL) {throw new Exception ("node does not exist!            ");        Return if ($dnode->left = = NULL | | $dnode->right = = null) {#如果待删除结点无子节点或只有一个子节点, then c = Dnode $c = $dnode        ;        The else {#如果待删除结点有两个子节点, C is the direct successor of Dnode, and the value of the node to be deleted is subsequently replaced by the value of its successor $c = $this->successor ($dnode);        } $dnode->key = $c->key;    return $c; /** * (Inward) deletes the specified node, processing the balance factor for the node's top node * @param $node eventually the deleted node * @return NULL */Private Function DEL_            Node ($node) {if ($node = = $this->root) {$this->root = NULL;        Return        } $current = $node;        Node now has only two cases, either one child node or no child node $P = $current->parent;        When you delete a node, the balance of the first parent is bound to change $lower = TRUE;                while ($lower = = TRUE &&!is_null ($P)) {//delete node is 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 node else {if ($current = = $node) {if (!is_null ($current->left)) {$P->right = $current-&gt                    ; 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 the 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);        /** * (inward) Gets the depth of the tree * @param $root 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) Gets the depth of the tree * @param null * @return NULL */Public Function Depth () {return $this    ->getdepth ($this->root); }}

debugging when you can call the sequence traversal to do, I in the previous blog provides PHP implementation of the two-tree graphics, with visual help can better help us to debug, detailed everyone can visit my previous blog: "Using PHP to achieve two-tree graphics display"

The above is the PHP two Fork Tree (ii): Balanced binary tree (AVL) content, more relevant content please pay attention to topic.alibabacloud.com (www.php.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.