//--------------------树的孩子兄弟存储表示又称树的二叉链表存储表示------------------------//
//--------------------它结合了树的双亲存储和树的孩子存储的优点----------------------------//
//易于实现找结点孩子等的操作,如果为每个结点增设一个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
#endiftypedef 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 ] ) ;
#endiffflush( 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!: " ) ;
#endifInitCSTree( &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 ;
}
第六章(5).树的孩子兄弟表示法
最新推荐文章于 2023-11-12 20:15:21 发布