PHP实现平衡二叉树(AVL树)

<?php
    require 'bstOrder.php';

    $test = range(1, 10);
    //$test = array(3,9,1,4,8,5,7,6,2,10);
    $tree = new Bst($test, true);
    //$tree->deleteNode('30');(非平衡树可删除,平衡树的没写删除操作)
    print_r($tree->getTree()); 
?>


bstOrder.php
<?php
    /**
     * PHP实现二叉排序树
     * @author zhaojiangwei
     * @since 2011/11/16 16:29
     *
     */

    class Node{
        private $data;
        private $left;
        private $right;
        private $bf;//平衡度

        public function Node($data = NULL, $bf = 0, $left = NULL, $right = NULL){
            $this->data = $data;
            $this->left = $left;
            $this->right = $right;
            $this->bf = $bf;
        }

        public function getBf(){
            return $this->bf;
        }

        public function setBf($bf){
            $this->bf = $bf;
        }

        public function getData(){
            return $this->data;
        }

        public function setData($data){
            $this->data = $data;
        }

        public function &getLeft(){
            return $this->left;
        }

        public function &getRight(){
            return $this->right;
        }

        public function setLeft($left){
            $this->left = $left;
        }

        public function setRight($right){
            $this->right = $right;
        }
    }

    class Bst{
        private $head;//头结点
        private $data;//初始输入的数据,为数组形式,如array('a','b');
        private $tag;//查找时设置的前一结点(已无效,没用)
        
        //$bst:是否创建AVL树 
        public function Bst($data, $bst = FALSE){
            $this->data = $data;
            $this->head = NULL;
            
            if(!$bst){
                $this->createBst();
            }else{
                $this->createBfBst();
            }
        }

        public function createBfBst(){
            foreach($this->data as $value){
                $this->insertBfNode($this->head, $value);   
            }
        }

        private function insertBfNode(&$node, $value){
            if($node == NULL){
                $node = new Node($value, 0);  
                return TRUE; 
            }else{
                if($node->getData() > $value){
                    if(!$this->insertBfNode($node->getLeft(), $value)){
                        return FALSE;
                    }

                    switch($node->getBf()){
                        case 0:
                            $node->setBf(1);
                            return TRUE;
                        case 1:
                            $this->rightRotate($node);
                            return FALSE;
                        case -1:
                            $node->setBf(0);
                            return FALSE;
                    }
                }elseif($node->getData() < $value){
                    if(!$this->insertBfNode($node->getRight(), $value)){
                        return FALSE;
                    }

                    switch($node->getBf()){
                        case 0:
                            $node->setBf(-1);
                            return TRUE;
                        case 1:
                            $node->setBf(0);
                            return FALSE;
                        case -1:
                            $this->leftRotate($node);
                            return FALSE;
                    }
                }else{
                    return FAlse;
                }
            }
        }
        
        private function excuteLeft(&$node){
            $temp = $node;
            $node = $node->getRight();
            $temp->setRight($node->getLeft());
            $node->setLeft($temp);
        }

        private function excuteRight(&$node){
            $temp = $node;
            $node = $node->getLeft();
            $temp->setLeft($node->getRight());
            $node->setRight($temp);
        }

        private function leftRotate(&$node){
            $right = &$node->getRight();
            switch($right->getBf()){
                case 1:
                    $left = &$right->getLeft();
                    switch($left->getBf()){
                        case -1:
                            $right->setBf(0);
                            $node->setBf(1);
                            break;
                        case 0:
                            $right->setBf(0);
                            $node->setBf(0);
                            break;
                        case 1:
                            $right->setBf(-1);
                            $node->setBf(0);
                            break;
                    }

                    $left->setBf(0);
                    $this->excuteRight($right);
                    $this->excuteLeft($node);
                    break;
                    
                case -1:
                    $node->setBf(0);
                    $right->setBf(0);
                    $this->excuteLeft($node);
                    break;
            }
        } 

        private function rightRotate(&$node){
            $left = &$node->getLeft();
            switch($left->getBf()){
                case -1:
                    $right = &$left->getRight();
                    switch($right->getBf()){
                        case -1:
                            $left->setBf(1);
                            $node->setBf(0);
                            break;
                        case 0:
                            $left->setBf(0);
                            $node->setBf(0);
                            break;  
                        case 1:
                            $left->setBf(0);
                            $node->setBf(-1);
                            break;
                    }
                   
                    $right->setBf(0); 
                    $this->excuteLeft($left);
                    $this->excuteRight($node);
                    break;
                case 1:
                    $node->setBf(0);
                    $left->setBf(0);
                    $this->excuteRight($node);
                    break;
            }
        }

        public function createBst(){
            foreach($this->data as $value){
                $this->insertNode($value);
            }
        }

        //$pre:如果找不到该结点,是否返回前值
        public function &searchBst(& $node, $key, $pre = FALSE){
            if($node == NULL){
                if($pre){
                    return $this->tag;
                }else{
                    return FALSE;
                }
            }
            
            if($key > $node->getData()){
                $this->tag = $node;
                return $this->searchBst($node->getRight(), $key, $pre);   
            }elseif($key < $node->getData()){
                $this->tag = $node;
                return $this->searchBst($node->getLeft(), $key, $pre);
            }else{
                return $node;
            }
        }

        public function insertNode($key){
            if(!$this->head){
                $this->head = new Node($key);
            }else{
                $pre = $this->searchBst($this->head, $key, TRUE);
                $node = new Node($key);
               
                if($pre->getData() > $key){
                    $pre->setLeft($node);   
                }else{
                    $pre->setRight($node);
                }
            }
        }

        public function deleteNode($key){
            $node = &$this->searchBst($this->head, $key);
            
            if(!$node){
                return FALSE;   
            }

            if($node->getLeft() == NULL){
                $node = $node->getRight(); 
            }elseif($node->getRight() == NULL){
                $node = $node->getLeft(); 
            }else{
                $leftBig = &$this->searchLeftBig($node);
                $node->setData($leftBig->getData());
                
                if($leftBig->getLeft()){
                    $leftBig = $leftBig->getLeft();
                }
            }
        }

        private function &searchLeftBig(& $key){
            $result = &$key->getLeft();

            while($result){
                if($result->getRight() == NULL){
                    return $result;
                }

                $result = &$result->getRight();
            }
        }

        public function getTree(){
            return $this->head;
        }
    }
?>
posted @ 2011-11-20 17:20  黑暗遊侠  阅读(398)  评论(0编辑  收藏  举报