二叉树

二叉树的定义:二叉树是有N(N>0)个有限结点构成的集合。N=0的树成为i额空二叉树;N>0的树有一个根节点和两个互不相交的分别称作左子树和右子树的子二叉树构成,也就是说每个结点要么只有左右子树,要么只有右树,或是左树,要门没有子树。

    二叉树是有序树,二叉树即使只有一个子树的时候也要区分是左子树还是右子树。

满二叉树:在二叉树中所有的分支结点都有左子树和右子树,并且所有的叶子结点都在同一层上,就是满二叉树。

完全二叉树:如果具有N个结点二叉树的结构和满二叉树的前n个结点的结构相同这样的二叉树叫做完全二叉树。

二叉树的抽象数据类型:

     数据集合:二叉树的结点集合。

     操作集合:

        创建二叉树。

         撤销二叉树:

         左插入结点:insertLeftNode(curr,x);若当前结点非空,在curr插入左结点,原来的左结点为新结点的左结点

         右插入结点:insertLeftNode(curr,x);若当前结点非空,在curr插入右结点,原来的左结点为新结点的右结点

         左删除子树:DeleteLeftTree(curr)若curr为非空,删除curr所指结点的左子树;

        左删除子树:DeleteLeftTree(curr)若curr为非空,删除curr所指结点的右子树;

       遍历二叉树:Traveerse(T,Visit()) 若二叉树T非空,则按某一种顺序访问二叉树T的每个结点,且每个结点只访问依次访问结点要实现的操作有Visite操作。二叉树的遍历次序有先序遍历,中序遍历,后序遍历,层次遍历四种。

        二叉树的性质:

      性质1: 若规定 跟结点层次为0,则第i层最多只有 2i个结点

                   A                                      20=1

              B          C                               21=2

         D       E   F       G                          22=4

      特性2:如规定空树的度为-1,则深度为K的二叉树最多有 2K+1-1个结点,其实满树的结点 为 20+21+。。。。2n=2n+1-1;

      特性3:具有N个结点的完全二叉树的最大深度为K=log2(N+1)-1

                     2K-1<n<2K+1-1

                    K<log2(N+1)<k+1

     K必须为整数

    对于一颗非空二叉树,n=n0(度为0结点个数)+n1(度为1结点个数)+n2(度为2结点个数);

分支数B=n-1;度为1的结点发出一个分支,度为2的结点发出两个分支

    B=n1(度为1结点个数)+2*n2(度为2结点个数);

   n0=n2+1;

 

        性质5:

                   具有N个结点的二叉树的当从上往下,从左往右排序的时候,从0开始排序。

              当i>0的时候双亲结点为 (i-1)/2(整除,也就是左子树的序号除以)当i=0的时候,i为跟结点

              当2i+1<n,则序号为该结点的左子结点的号数,当2i+1>n则无子左节点

              当2i+2<=n,则序号为该结点的右子结点的号数,当2i+2>n则无右左节点

 

            A(k=0,i=0)                                     2的0次方=1

        B(k=1,i=1)          C (k=1,i=2)                              2的一次方=2

    D(k=2,i=3)       E(k=2,i=4)   F(k=2,i=5)       G(k=2,i=6)       2的二次方=4
(k=3,i=7) i=8       i=9,i=10        i=11,i=12       i=13,i=14
n = 2的K+1次方-1= 2的3次方-1=7
序号 i=从0开始,则最大序号 2的K+1次方-2

某一K层最多有 2的K次方结点
则最小的i = 2的K+1次方-1 - 2的K次方
最大的编号i = 2的K+1次方-2

某一K层的上一层最多有 2的(K-1)次方结点
 (左)最小的i = 2的K次方-1 - 2的(K-1)次方
 (右)最大的编号i = 2的K次方-2
 
 2*(2的K次方-1 - 2的(K-1)次方)+1 = 2的K+1次方-2 - 2的K次方 是不可能大于2的K+1次方-1 - 2的K次方

 

二叉树特性总结:

      1:规定根节点层次为0,那么i层最多有 2的i次方个结点

       2:规定空树的深度为-1,那么深度为K的最大节点数为 2的K+1次方减1个结点

      3:具有N个结点的完全二叉树的最大深度 log2(N+1)-1

      4:n=n0(度为0结点个数)+n1(度为1结点个数)+n2(度为2结点个数);n0=n2+1;

      5:若规定从上到下,从左往右排序,从0开始排序

           当i=0时表示是根节点,i>0,i减一除以2整除的树是双亲结点,子节点是双亲结点的倍数。

           当2*i+1 < n时是此结点的做孩子结点,当2*i+1 > n无左孩子结点

            当2*i+2<= n 是此结点的右孩子结点,

二叉树的链式结构实现:

      

 

二叉树的排序可以根据二叉树的特性来算出。

二叉树的顺序存储结构不适合存储非完全二叉树,会造成很大的空间浪费。

二叉树的链式存储结构:

        二叉树的链式存储结构:是用指针建立二叉树中结点之间的关系。二叉树最常用的链式存储结构是二叉链。二叉链存储结构的每个结点包含三个域,数据域,左孩子指针域,右孩子指针域。

 

二叉树的链式结构实现:

    <?php
/**
*
*二叉树的基本实现
*/

/**
*定义结点数据类型
*/

class Node {
    public $content; //数据域
    public $leftnext;//左孩子
    public $rightnext;//右孩子
}

class Three {
    public $root;
    /**
    *初始化
    */
    public function __construct($content) {
        $this->root = new Node;
        $this->root->content   = $content;
        $this->root->leftnext  = null;
        $this->root->rightnext = null;        
    }
    
    /**
    *插入左孩子结点
    */
    public Function insertLeftNode($curr,$content) {
    
        if($curr == null) return null;
        if($curr->leftnext == null) {
            $node = new Node;
            $node->content = $content;
            $node->leftnext = null;
            $node->rightnext = null;
            $curr->leftnext = $node;
        } else {
           $left = $curr->leftnext;
               $node = new Node;
            $node->content = $content;
            $node->leftnext = $left;
            $node->rightnext = null;
            $curr->leftnext = $node;
        }
        return $curr->leftnext;
    }
    
    /**
    *插入右孩子结点
    */
    public Function insertrightNode($curr,$content) {
    
        if($curr == null) return null;
        if($curr->rightnext == null) {
            $node = new Node;
            $node->content = $content;
            $node->leftnext = null;
            $node->rightnext = null;
            $curr->rightnext = $node;
        } else {
           $right = $curr->rightnext;
               $node = new Node;
            $node->content = $content;
            $node->leftnext = null;
            $node->rightnext = $right;
            $curr->leftnext = $node;
        }
        return $curr->rightnext;
    }
    
    /**
    *删除左结点
    */
    public function deleteLeftNode($curr) {
        if($curr == null || $curr->leftnext == null) return null;
        $curr->leftnext == null;
        return $curr;
    }
    
    /**
    *删除右子节点
    */
    public function deleteRightNode($curr) {
        if($curr == null || $curr->rightnext == null) return null;
        $curr->rightnext == null;
        return $curr;
    }
    
    /**
    *遍历二叉树
    *前序遍历方法递归方法
    *方法步骤:
    *    从跟结点遍历
    *     遍历左结点
    *     遍历右结点
    *     为空不遍历
    */
    public function listThree($curr) {
        if($curr == null ) return;
        static $vlist = array();
        $vlist[] = $curr->content;
        
        if($curr->leftnext != null) {
        
            $this->listThree($curr->leftnext);
        }
        if($curr->rightnext != null) {
            $this->listThree($curr->rightnext);
        }
        return $vlist;
    }
    
    
    /**
    *遍历二叉树
    *中序遍历方法递归方法
    *方法步骤:
    *    
    *     遍历左结点
            跟结点
    *     遍历右结点
    *     为空不遍历
    */
    
    public function InListThree($curr) {
        static $vlist = array();
        if($curr != null) {
            $this->InListThree($curr->leftnext);
            $vlist[] = $curr->content;
            $this->InListThree($curr->rightnext);
        }
        return $vlist;
    }
    
    /**
    *层次顺序遍历方法递归方法
    *方法步骤:
    *    存入跟结点
    *     访问左子结点
    *     访问右子节点

    */
    public function ArrThree($curr) {
        if($curr == null) return null;
        static $vlist = array();
        $vlist[0] = $this->root->content;
        if($curr->leftnext) $vlist[] = $curr->leftnext->content;
        if($curr->rightnext) $vlist[] = $curr->rightnext->content;
        $this->ArrThree($curr->leftnext);
        $this->ArrThree($curr->rightnext);
        return $vlist;
    }    
}

$three = new Three('a');
$left  = $three->insertLeftNode($three->root,'b');
$right = $three->insertrightNode($three->root,'c');
$three->insertLeftNode($left,'d');
$three->insertrightNode($left,'e');

$three->insertLeftNode($right,'f');
$three->insertrightNode($right,'g');
print_r($three->listThree($three->root)); //Array ( [0] => a [1] => b [2] => d [3] => e [4] => c [5] => f [6] => g )
print_r($three->ArrThree($three->root)); //Array ( [0] => a [1] => b [2] => c [3] => d [4] => e [5] => f [6] => g )

posted on 2015-03-19 14:12  木子牛  阅读(337)  评论(0编辑  收藏  举报

导航