您的位置:首页 > 其它

二叉树的总结

2014-02-19 17:05 459 查看
 一,二叉树的定义 

    二叉树(Binary   tree)是n(n≥0)个结点的有限集合。若n=0时称为空树,否则:

    ⑴有且只有一个特殊的称为树的根(Root)结点;

    ⑵若n>1时,其余的结点被分成为二个互不相交的子集T1,T2,分别称之为左、右子树,并且左、右子树又都是二叉树。

    由此可知,二叉树的定义是递归的。

     二叉树在树结构中起着非常重要的作用。因为二叉树结构简单,存储效率高,树的操作算法相对简单,且任何树都很容易转化成二叉树结构。

二,二叉树的基本形态






三,二叉树的性质

性质1:在非空二叉树中,第i层上至多有2i-1个结点(i≧1)。

性质2:深度为k的二叉树至多有2k-1个结点(k≧1) 

性质3:对任何一棵二叉树,若其叶子结点数为n0,度为2的结点数为n2,则n0=n2+1。

    证明:设二叉树中度为1的结点数为n1,二叉树中总结点数为N,因为二叉树中所有结点均小于或等于2,则有:N=n0+n1+n2
再看二叉树中的分支数:

    除根结点外,其余每个结点都有唯一的一个进入分支,而所有这些分支都是由度为1和2的结点射出的。设B为二叉树中的分支总数,则有:      N=B+1

        ∴     B=n1+2*n2         

        ∴     N=B+1=n1+2*n2+1

        ∴     n0+n1+n2=n1+2*n2+1

       即      n0=n2+1                                         

四,满二叉树和完全二叉树

     一棵深度为k且有 2^k -1 个结点的二叉树称为满二叉树(Full Binary Tree)。

      满二叉树的特点:

     ◆ 基本特点是每一层上的结点数总是最大结点数。

     ◆ 满二叉树的所有的支结点都有左、右子树。

     ◆ 可对满二叉树的结点进行连续编号,若规定从根结点开始,按“自上而下、自左至右”的原则进行。

      完全二叉树(Complete Binary Tree):如果深度为k,由n个结点的二叉树,当且仅当其每一个结点都与深度为k的满二叉树中编号从1到n的结点一一对应,该二叉树称为完全二叉树。 或深度为k的满二叉树中编号从1到n的前n个结点构成了一棵深度为k的完全二叉树。 其中 2^(k-1 )≦n≦2^k-1 。

       完全二叉树是满二叉树的一部分,而满二叉树是完全二叉树的特例。

       完全二叉树的特点:

       若完全二叉树的深度为k,则所有的叶子结点都出现在第k层或k-1层。对于任一结点,如果其右子树的最大层次为l,则其左子树的最大层次为l或l+1。

     性质4:n个结点的完全二叉树深度为:[log2n]+1

    性质5:若对一棵有n个结点的完全二叉树的结点按层序自左至右进行编号,则对于编号为i(1≦i≦n)的结点:

     ⑴ 若i=1:则结点i是二叉树的根,无双亲结点;否则,若i>1,则其双亲结点编号是[ i/2 ]。

      ⑵ 如果2i>n:则结点i为叶子结点,无左孩子;否则,其左孩子结点编号是2i。

     ⑶ 如果2i+1>n:则结点i无右孩子;否则,其右孩子结点编号是2i+1。

五,二叉树的存储

1,顺序存储结构

用  一组地址连续的存储单元依次“自上而下、自左至右”存储完全二叉树的数据元素。

      对于完全二叉树上编号为i的结点元素存储在一维数组的下标值为i-1的分量中,

     对于一般的二叉树,将其每个结点与完全二叉树上的结点相对照,存储在一维数组中。

    

 

2,链式存储结构

    

① 二叉链表结点。有三个域:一个数据域,两个分别指向左右子结点的指针域。

    typedef  struct  BTNode

    {  

           ElemType  data ;

           structBTNode  *Lchild, *Rchild;

     }BTNode;

    三叉链表结点。除二叉链表的三个域外,再增加一个指针域,用来指向结点的父结点,如图6-7(b)所示。

    typedef  struct   BTNode_3

   {   

         ElemType  data ;

         structBTNode_3  *Lchild, *Rchild, *parent ;

    }BTNode_3;

   


六,二叉树的遍历

    遍历二叉树(TraversingBinary Tree):是指按指定的规律对二叉树中的每个结点访问一次且仅访问一次。

    若以L、D、R分别表示遍历左子树、遍历根结点和遍历右子树,则有六种遍历方案:DLR、LDR、LRD、DRL、RDL、RLD。若规定先左后右,则只有前三种情况三种情况,分别是:

    DLR——先(根)序遍历。

    LDR——中(根)序遍历。

    LRD——后(根)序遍历。

1,先序遍历

递归算法:

       若二叉树为空,则遍历结束;否则

       ⑴访问根结点;

      ⑵先序遍历左子树(递归调用本算法);

      ⑶先序遍历右子树(递归调用本算法)。

void  PreorderTraverse(BTNode  *T)
{  
if  (T!=NULL) 
    { 
visit(T->data) ;       /*  访问根结点  */
       PreorderTraverse(T->Lchild) ;
       PreorderTraverse(T->Rchild) ;     
    }
}
 

 非递归算法:

设T是指向二叉树根结点的指针变量,非递归算法是:

    若二叉树为空,则返回;否则,令p=T;

   ⑴ 访问p所指向的结点;

   ⑵ q=p->Rchild,若q不为空,则q进栈;

   ⑶ p=p->Lchild,若p不为空,转(1),否则转(4);

  ⑷  退栈到p ,转(1),直到栈空为止。

#define  MAX_NODE  50
void  PreorderTraverse( BTNode  *T)
{
BTNode  *Stack[MAX_NODE] ,*p=T, *q ;
int  top=0 ;
if  (T==NULL)  printf(" Binary Tree is Empty!\n") ;
else
{
do
{
visit( p-> data ) ;
q=p->Rchild ;
if  ( q!=NULL )  stack[++top]=q ;
p=p->Lchild ;
if (p==NULL)
{
p=stack[top] ;
top-- ;
}
}while (p!=NULL) ;
}
}


同理,

2,中序遍历:

递归算法:

void  InorderTraverse(BTNode  *T)
{
if  (T!=NULL)
{
InorderTraverse(T->Lchild) ;
visit(T->data) ;       /*   访问根结点   */
InorderTraverse(T->Rchild) ;
}
}


非递归算法:

#define MAX_NODE  50
void  InorderTraverse( BTNode  *T)
{
BTNode  *Stack[MAX_NODE] ,*p=T ;
int  top=0 , bool=1 ;
if  (T==NULL)  printf("Binary Tree is Empty!\n") ;
else
{
do
{
while (p!=NULL)
{
stack[++top]=p ;
p=p->Lchild ;
}
if  (top==0)  bool=0 ;
else
{
p=stack[top] ;
top-- ;
visit( p->data ) ;
p=p->Rchild ;
}
}while (bool!=0) ;
}
}


3,后序遍历

递归算法:

void  PostorderTraverse(BTNode  *T)
{
if  (T!=NULL)
{
PostorderTraverse(T->Lchild) ;
PostorderTraverse(T->Rchild) ;
visit(T->data) ;       /*  访问根结点  */
}
}


非递归算法:

#define MAX_NODE  50
void  PostorderTraverse( BTNode  *T)
{
BTNode  *S1[MAX_NODE] ,*p=T ;
int S2[MAX_NODE] , top=0 , bool=1 ;
if  (T==NULL)  printf("Binary Tree is Empty!\n") ;
else
{
do
{
while (p!=NULL)
{
S1[++top]=p ;
S2[top]=0 ;
p=p->Lchild ;
}
if  (top==0)  bool=0 ;
else if  (S2[top]==0)
{
p=S1[top]->Rchild ;
S2[top]=1 ;
}
else
{
p=S1[top] ;
top-- ;
visit( p->data ) ;
p=NULL ;
/*  使循环继续进行而不至于死循环 */
}
}while (bool!=0) ;
}
}


4,层次遍历

层 次遍历二叉树,是从根结点开始遍历,按层次次序“自上而下,从左至右”访问树中的各结点。

    设T是指向根结点的指针变量,层次遍历非递归算法是:

    若二叉树为空,则返回;否则,令p=T,p入队;

     ⑴队首元素出队到p;

     ⑵访问p所指向的结点;

     ⑶将p所指向的结点的左、右子结点依次入队。直到队空为止。

#define MAX_NODE  50
void  LevelorderTraverse( BTNode  *T)
{
BTNode  *Queue[MAX_NODE] ,*p=T ;
int  front=0 , rear=0 ;
if  (p!=NULL)
{
Queue[++rear]=p;    /*   根结点入队  */
while (front<rear)
{
p=Queue[++front];
visit( p->data );
if (p->Lchild!=NULL)
Queue[++rear]=p->Lchild;    /*   左结点入队  */
if (p->Rchild!=NULL)
Queue[++rear]=p->Rchild;    /*   左结点入队  */
}
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息