第六章(5).树的孩子兄弟表示法

//--------------------树的孩子兄弟存储表示又称树的二叉链表存储表示------------------------//
//--------------------它结合了树的双亲存储和树的孩子存储的优点----------------------------//
//易于实现找结点孩子等的操作,如果为每个结点增设一个parent域,则同样能方便的实现Parent操作//
#include < stdio.h >
#include < stdlib.h >
#include < string.h >

#define TRUE 1  
#define FALSE 0    
#define OK 1
#define ERROR 0
#define OVERFLOW -2     //Include by "math.h"!

typedef int Status ;

//------------------------Link Tree--------------------------//

#define CHAR 1 
#if CHAR       
 typedef char TElemType ;
 #define N ' '     //Set different means according to different case!
#else
 typedef int TElemType ;
 #define N 0    
#endif

typedef struct CSNode{
 TElemType data ;
 struct CSNode *firstchild , *nextsibling ;
} CSNode , *CSTree ;

//-------------------------Link Queue---------------------------//

typedef CSTree QElemType ;

typedef struct QNode               //链结点
{
 QElemType data ;
 struct QNode *next ;
} QNode , *QueuePtr ;

typedef struct                   
{
 QueuePtr front ;               //队头指针   队头出元素
 QueuePtr rear ;                //队尾指针   队尾进元素
} LinkQueue ;

Status InitQueue( LinkQueue *Q ) ;
Status EnQueue( LinkQueue *Q , QElemType e ) ;
Status DeQueue( LinkQueue *Q , QElemType *e ) ;
Status QueueEmpty( LinkQueue Q ) ;

//---------------------Basic Fuction!--------------------------//

Status InitCSTree( CSTree *T )
{
 ( *T ) = NULL ;
 return OK ;
}

Status DestroyCSTree( CSTree *T ) //The same with Binary Tree!
{
 if( ( *T ) )
 {
  if( ( *T )->firstchild )
   DestroyCSTree( &( *T )->firstchild ) ;
  if( ( *T )->nextsibling )
   DestroyCSTree( &( *T )->nextsibling ) ;
  free( *T ) ;
  ( *T ) = NULL ;
  return OK ;
 }
 return ERROR ;
}

Status CreateCSTree( CSTree *T )
{
 TElemType ch[ 20 ] ;  //存放孩子结点的值(大小自设)
 CSTree p , pa ;

 LinkQueue Q ;
 int i = 0 , l = 0 ;

 printf( "Input the root:" ) ;
#if CHAR       
 scanf( "%c" , &ch[ 0 ] ) ;  //if "scanf( "%c%*c" , &ch[ 0 ] ) ;" ,then we can save "fflush( stdin ) ;"
#else
 scanf( "%d" , &ch[ 0 ] ) ;   
#endif 

 fflush( stdin ) ;  //It's needed!

 if( N == ch[ 0 ] )
  ( *T ) = NULL ;
 else
 {
  ( *T ) = ( CSTree )malloc( sizeof( CSNode ) ) ;
  if( !( *T ) )
   exit( OVERFLOW ) ;

  ( *T )->data = ch[ 0 ] ;
  ( *T )->nextsibling = NULL ;
  InitQueue( &Q ) ;
  EnQueue( &Q , ( *T ) ) ;

  while( !QueueEmpty( Q ) )
  {
   DeQueue( &Q , &p ) ;
   printf( "Input the children of %c:" , p->data ) ;
   gets( ch ) ;
   l = strlen( ch ) ;

   if( l > 0 )   //存在孩子
   {
    pa = p->firstchild  = ( CSTree )malloc( sizeof( CSNode ) ) ;    //树的长子
    pa->data = ch[ 0 ] ;
    for( i = 1 ; i < l ; ++ i )   //Take care! It's begin from 1 to i-1. //树的次子(即树长子的兄弟)
    {
     EnQueue( &Q , pa ) ;
     pa->nextsibling = ( CSTree )malloc( sizeof( CSNode ) ) ;
     pa = pa->nextsibling ;
     pa->data = ch[ i ] ;
    }

    pa->nextsibling = NULL ; //最后一个次子
    EnQueue( &Q , pa ) ;
   }
   else
   {
    p->firstchild = NULL ;
   }
  }//--while--//
 }//--else--//
 return OK ;
}

Status CSTreeEmpty( CSTree T )
{
 if( T )
  return FALSE ;
 return TRUE ;
}

Status CSTreeDepth( CSTree T )
{
 int max = 0 , dep = 0 ;
 CSTree p ;

 if( !T )    //空树
  return max ;
 if( !T->firstchild ) //无子树
 {
  ++ max ;
  return max ;
 }

 for( p = T->firstchild ; p ; p = p->nextsibling ) //求每棵子树的深度(递归)
 {
  dep = CSTreeDepth( p ) ;
  if( dep > max )
   max = dep ;
 }
 return ( max + 1 ) ;
}

TElemType Root( CSTree T )
{
 if( T )
  return T->data ;
 return ERROR ;
}

TElemType Value( CSTree p )  //返回p所指结点的值
{
 if( p )
  return p->data ;
 return ERROR ;
}

CSTree Point( CSTree T , TElemType e ) //返回在树中值为e的结点
{
 LinkQueue Q ;
 QElemType p ;    //CSTree p ;

 if( T )
 {
  InitQueue( &Q ) ;
  EnQueue( &Q , T ) ;

  while( !QueueEmpty( Q ) )
  {
   DeQueue( &Q , &p ) ;
   if( p->data == e )
    return p ;
   if( p->firstchild )
    EnQueue( &Q , p->firstchild ) ;
   if( p->nextsibling )
    EnQueue( &Q , p->nextsibling ) ;
  }
 }
 return ERROR ;
}

Status Assign( CSTree *T , TElemType e , TElemType value ) //将树中结点值为e的结点值设置为value
{
 CSTree p ;

 if( T )
 {
  p = Point( ( *T ) , e ) ;
  if( p )
  {
   p->data = value ;
   return OK ;
  }
 }
 return ERROR ;
}

TElemType Parent( CSTree T , TElemType e )  //返回结点值为e的双亲的值
{
 LinkQueue Q ;
 QElemType p , t ;

 if( T )
 {
  if( T->data == e )  //根结点不存在双亲结点
   return ERROR ;

  InitQueue( &Q ) ;
  EnQueue( &Q , T ) ;

  while( !QueueEmpty( Q ) )
  {
   DeQueue( &Q , &p ) ;
   if( p->firstchild )
   {
    if ( p->firstchild->data == e )
    {
     return p->data ;
    }

    t = p ;
    p = p->firstchild ;
    EnQueue( &Q , p ) ;  //长子入队列

    while( p->nextsibling )
    {
     if( p->nextsibling->data == e )
      return t->data ;
     
     p = p->nextsibling ;
     EnQueue( &Q , p ) ;
    }
   }
  }//--while--//
 }
 return ERROR ;
}

TElemType LeftChild( CSTree T , TElemType e )  //返回结点值为e的结点的左孩子
{
 CSTree p ;

 if( T )
 {
  p = Point( T , e ) ;
  if( p && p->firstchild )
   return p->firstchild->data ;
 }
 return ERROR ;
}

//RightChild equal the p->firstchild->nextsibling ! And the same to LeftSibling !

Status RightSibling( CSTree T , TElemType e )
{
 CSTree p ;

 if( T )
 {
  p = Point( T , e ) ;
 // if( p || p->nextsibling )   //May have many rightsiblings!
 //  return p->nextsibling->data ;
  while( p || p->nextsibling )
  {
   printf( "%3c" , p->nextsibling->data ) ;
   p = p->nextsibling ;
  }
  return OK ;
 }
 return ERROR ;
}

Status InsertChild( CSTree *T , CSTree p , int i , CSTree c )
{ //将c插入为p所指向的结点的第i棵子树( 1<= i <= p结点度+1 )
 int j = 0 ;

 if( !( *T ) )
  return ERROR ;
 else
 {
  if( i == 1 )    //长子树,不管p原本存不存在子树
  {
   c->nextsibling = p->firstchild ;
   p->firstchild = c ;
  }
  else      //找满足i的情况
  {
   p = p->firstchild ;  //第一棵子树
   j = 2 ;     //找"i-1"的位置
   while( p && i > j )
   {
    p = p->nextsibling ;
    ++ j ;    
   }

   if( j == i )
   {
    c->nextsibling = p->nextsibling ;
    p->nextsibling = c ;
   }
   else
   {
    return ERROR ;
   }
  }
  return OK ;
 }
}

Status DeleteChild( CSTree *T , CSTree p , int i )
{ //删除p结点所指结点的第i棵子树( 1<= i <= p结点度+1 )
 int j = 0 ;
 CSTree b ;

 if( !( *T ) )
  return ERROR ;
 else
 {
  if( i == 1 )
  {
  // p->firstchild = p->firstchild->nextsibling ; //没考虑到资源的释放啊!
   b = p->firstchild ;
   p->firstchild = b->nextsibling ;
   b->nextsibling = NULL ;
   DestroyCSTree( &b ) ;
  }
  else
  {
   p = p->firstchild ;  //长子结点
   j = 2 ;     //找'i'子树!此时p为第一棵子树
   while( p && i > j )
   {
    p = p->nextsibling ;
    ++ j ;
   }

   if( i == j )   //此时p为第i-1棵子树
   {
   // p = p->nextsibling ;
    b = p->nextsibling ;//b为第i棵树
    p->nextsibling = b->nextsibling ;
    b->nextsibling = NULL ;//防止悬空指针
    DestroyCSTree( &b ) ;
   }
   else
    return ERROR ;
  }
  return OK ;
 }
}

void visit( CSTree p ) //Take care! The paramer is CSTree!
{
#if CHAR       
 printf( "%3c" , p->data ) ;
#else
 printf( "%3d" , p->data ) ;
#endif
}

//所有存储结构的先序递归遍历是相同的//
Status PreOrderTraverse( CSTree T , void( *v )( CSTree ) )
{
 if( !T )
  return ERROR ;

 v( T ) ;
 PreOrderTraverse( T->firstchild , v ) ;
 PreOrderTraverse( T->nextsibling , v ) ;
 return OK ;
}

Status PostOrderTraverse( CSTree T , void( *v )( CSTree ) )  //从左至右先遍历各子树,最后遍历根结点
{
 CSTree p ;

 if( !T )
  return ERROR ;
 
 if( T->firstchild )
 {
  PostOrderTraverse( T->firstchild , v ) ; //遍历长子
  p = T->firstchild->nextsibling ;

  while( p )
  {
   PostOrderTraverse( p , v ) ;   //遍历各次子
   p = p->nextsibling ;
  }
 }
 v( T ) ;          //遍历双亲
 return OK ;
}

//--------中序遍历很为复杂--------//

Status LevelTraverse( CSTree T , void ( *v )( CSTree ) )
{
 LinkQueue Q ;
 QElemType p , pa ;

 if( !T )
  return ERROR ;

 InitQueue( &Q ) ;
 v( T ) ;     //先访问根结点
 EnQueue( &Q , T ) ;
 
 while( !QueueEmpty( Q ) )
 {
  DeQueue( &Q , &p ) ;

  if( p->firstchild )  //存在长子
  {
   v( p->firstchild ) ;
   EnQueue( &Q , p->firstchild ) ;

   pa = p->firstchild->nextsibling ;
   while( pa )
   {
    v( pa ) ;
    EnQueue( &Q , pa ) ;
    pa = pa->nextsibling ;
   }
  }
 }
 return OK ;
}

//-----------------------Main Fuction!------------------------//

int main( )
{
 CSTree T ;
 CSTree p ;

#if CHAR
 printf( "Input the Tree Node(char),blank is mean NULL Node!\n " ) ;
#else
 printf( "Input the Tree Node(int), 0 is mean NULL Node!: " ) ;
#endif

 InitCSTree( &T ) ;
 CreateCSTree( &T ) ;

// PreOrderTraverse( T , visit ) ;
// printf( "\n" ) ;

// PostOrderTraverse( T , visit ) ;
// printf( "\n" ) ;

// printf( "%3c\n" , Parent( T , 'd' ) );

// printf( "%3c\n" , LeftChild( T , 'a' ) ) ;

// p = Point( T , 'f' ) ;
// DeleteChild( &T , p , 2 ) ;

 LevelTraverse( T , visit ) ;
 printf( "\n" ) ;

return 0 ;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值