二叉树的总结

本文详细介绍了二叉树的概念、性质、存储方式及遍历方法。包括二叉树的定义、基本形态、满二叉树与完全二叉树的区别,以及二叉树的顺序存储和链式存储结构。同时,深入探讨了先序、中序、后序和层次遍历的递归与非递归算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 一,二叉树的定义 

    二叉树(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;    /*   左结点入队  */
        }
     }
}





评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值