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->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->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->BF = $L->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->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; 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->BF = $R->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->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; 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->BF) {//the original left and right sub-tree, etc., and now the tree is raised and trees increase case SELF::EH: $root->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->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-> ; 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)!