第五章(6).广义表的扩展线性链表存储表示

#include < stdio.h >
#include < stdlib.h >
#include < string.h >

#define TRUE 1   //  'true' is OK !
#define FALSE 0      // 'false' is OK !
#define OK 1
#define ERROR 0
#define OVERFLOW -2

#define MAXSIZE 100  //串的定长顺序存储表示
typedef char SString[ MAXSIZE + 1 ] ;   //0号单元存放串的当前长度

typedef int Status;  
typedef char AtomType ;  

typedef enum { ATOM , LIST }ElemTag ; //ATOM==0:原子,LIST==1:子表  ( enum 枚举 )

typedef struct GLNode
{
 ElemTag tag ;    // 公共部分,用于区分原子结点和表结点
 union      // 原子结点和表结点的联合部分 ( union 联合体 )
 {
  AtomType atom ;   // atom是原子结点的值域,AtomType由用户定义.只供原子节点使用
  struct GLNode *hp ;  //表结点的表头指针
 } ;   
 struct GLNode *tp ;   //相当于线性链表的next,指向下一个元素结点
} GLNode , *GList ;

//-----------------------String Fuction!--------------------------//
Status StrAssign( SString T , char *ch )
{
 int i = 0 ;
 
 if( strlen( ch ) > MAXSIZE )
 {
  exit( 0 ) ;
 }
 else
 {
  T[ 0 ] = strlen( ch ) ;
  for( i = 1 ; i <= T[ 0 ] ; ++ i )
  {
   T[ i ] = ch[ i - 1 ] ;
  }
 }
 T[ i ] = '\0' ;

 return OK ;
}

Status StrCopy( SString T , SString S )  //S = T ;
{
 int i = 0 ;

 for( i = 0 ; i <= T[ 0 ] ; ++ i )
 {
  S[ i ] = T[ i ] ;
 }

 return OK ;
}

Status StrEmpty( SString S ) //已有的前提是S已经存在
{
 if( S[ 0 ] == 0 )
 {
  return TRUE  ;
 }
 else
 {
  return FALSE ;
 }
}

// 若S>T,则返回值>0;若S=T,则返回值=0;若S<T,则返回值<0
Status StrCompare( SString S , SString T )
{
 int i = 0 ;

 for( i = 1 ; i <= S[ 0 ] && i <= T[ 0 ] ; ++ i )
 {
  if( S[ i ] != T[ i ] ) //相等则比较下一位
  {
   return S[ i ] - T[ i ] ;
  }
 }
 return S[ 0 ] - T[ 0 ] ; //相同长度的字符比较完后如果还没分出胜负,呵呵,就得看谁耐力更好了!
}

// 返回串的元素个数
Status StrLength( SString S )
{
 return S[ 0 ] ;
}

// 将S清为空串
Status ClearString( SString S )
{
 S[ 0 ] = 0 ;
 return OK ;
}

// 用Sub返回串S的第pos个字符起长度为len的子串。
Status SubString( SString Sub , SString S , int pos , int len )
{
 int i = 0 ;

 if( pos < 0 || pos > S[ 0 ] || len < 0 || len > S[ 0 ] - pos + 1 )  //安全判断必不可少哦!
 {
  exit( 0 ) ;
 }

 Sub[ 0 ] = len ;

// for( i = pos ; i < pos + len ; ++ i )
// {
//  Sub[ i - pos + 1 ] = S[ i ] ;
// } 
 
 for( i = 1 ; i <= len ; ++ i )  // It's OK !
 {
  Sub[ i ] = S[ i + pos - 1 ] ;
 }
 Sub[ i ] = '\0' ;

 return OK ;
}

//将非空串str分割成两部分:hsub为第一个','之前的子串,str为之后的子串
//如果串str中没有字符',',则操作后的hstr即为操作前的str,而操作后的str为空串NULL
Status sever( SString str , SString hstr )
{
 int n = 0 , i = 0 , k = 0 ; // k记尚未配对的左括号个数
 SString ch , c1 , c2 , c3 ;

 n = StrLength( str ) ;
/* do   //搜索最外层的第一个逗号
 {
  ++ i ;
  SubString( ch , str , i , 1 ) ;
  if( ch == '(' )
  {
   ++ k ;
  }
  else
  {
   if( ch == ')' )
   {
    -- k ;
   }
  }
 }while( i < n && ( ch != ',' || k != 0 ) ) ; //Take care about it ! 

 if( i < n )   //ch != ',' or k != 0
 {
  SubString( hstr , str , 1 , i - 1 ) ;
  SubString( str , str , i + 1 , n - i ) ;
 }
 else
 {
  StrCopy( str , hstr ) ;  //hstr = str ;
  ClearString( str ) ;
 } */

 StrAssign( c1 , "," ) ;
 StrAssign( c2 , "(" ) ;
 StrAssign( c3 , ")" ) ;
 SubString( ch , str , 1 , 1 ) ;
 // 搜索最外层的第一个逗号
 for( i = 1 , k = 0 ; i <= n && StrCompare( ch , c1 ) || k != 0 ; ++ i )
 {
  SubString( ch , str , i , 1 ) ;
  if( !StrCompare( ch , c2 ) )
  {
   ++ k ;
  }
  else
  {
   if( !StrCompare( ch , c3 ) )
   {
    -- k ;
   }
  }
 }

 if( i <= n )   //ch != ',' or k != 0
 {
  SubString( hstr , str , 1 , i - 2 ) ;
  SubString( str , str , i , n - i + 1 ) ;
 }
 else
 {
  StrCopy( str , hstr ) ;  //hstr = str ;
  ClearString( str ) ;
 } 

 return OK ;
}

//---------------------------GList Fuction!-----------------------------//
Status InitGList( GList *L )
{
 *L = NULL ;
 return OK ;
}

Status CreateGList( GList *L , SString S )
{
 SString emp , sub , hsub ;

 GList p ;
 StrAssign( emp , "()" ) ;

 *L = ( GList )malloc( sizeof( GLNode ) ) ; //take care! It's '*L', not 'L'.
 if( !(*L) )
 {
  exit( OVERFLOW ) ;
 }

 if( !StrCompare( S , emp ) )  //List is NULL!
 {
  ( *L )->tag = LIST ;
  ( *L )->hp = ( *L )->tp = NULL ;
 }
 else
 {
  if( StrLength( S ) == 1 ) //only one atom!
  {
   ( *L )->tag = ATOM ;
   ( *L )->atom = S[ 1 ] ;
   ( *L )->tp = NULL ;
  }
  else
  {
   ( *L )->tag = LIST ;
   ( *L )->tp = NULL ;

   SubString( sub , S , 2 , StrLength( S ) - 2 ) ;
   sever( sub , hsub ) ;
   CreateGList( &( *L )->hp , hsub ) ;
   p = ( *L )->hp ;
   while( !StrEmpty( sub ) )
   {
    sever( sub , hsub ) ;
    CreateGList( & p->tp , hsub ) ;
    p = p->tp ;
   }
  }
 }
 return OK ;
}

Status DestoryGList( GList *L )
{
 GList ph , pt ;

 if( *L )   // (*L) is not a NULL List .
 {
  if( ( *L )->tag == 1 ) //It's a List !
  {
   ph = ( *L )->hp ;
  }
  else     //It's a atom!
  {
   ph = NULL ;
  }
  

  pt = ( *L )->tp ;
  DestoryGList( &ph ) ;
  DestoryGList( &pt ) ;
  free( *L ) ;
  ( *L ) = NULL ;
 }
 return OK ;
}

Status CopyGList( GList *T , GList L ) //( *T ) = L ;
{
 ( *T ) = NULL ;       //when L is a NULL List ,that's OK!
 if( L )
 {
  ( *T ) = ( GList )malloc( sizeof( GLNode ) ) ;
  if( !( *T ) )
  {
   exit( OVERFLOW ) ;
  }

  ( *T )->tag = L->tag ;
  if( L->tag == ATOM ) //atom
  {
   ( *T )->atom = L->atom ;
  }
  else     //List 
  {
   CopyGList( &( *T )->hp , L->hp ) ;
  }

  if( L->tp == NULL )  //the tail of list !
  {
   ( *T )->tp = L->tp ;
  }
  else
  {
   CopyGList( &( *T )->tp , L->tp ) ;
  }
 }
 return OK ;
}

int GListDepth( GList L ) //括弧的重数
{
 int max , dep ;
 GList p ;

 if( L == NULL || ( L->tag == LIST && !( L->hp ) ) )
 {
  return 1 ;  //The List of NULL!
 }
 else
 {
  if( L->tag == ATOM )
  {
   return 0 ; //only one atom!
  }
  else
  {
   for( max = 0 , p = L->hp ; p ; p = p->tp)
   {
    dep = GListDepth( p ) ;
    if( dep > max )
    {
     max = dep ;
    }
   }
  }
 }
 return ( max + 1 ) ;
}

int GListLength( GList L ) //广义表长度是数第一层括号内的逗号数目加一
{
 int len = 0 ;
 if( L )
 {
  L = L->hp ;
  while( L )
  {
   L = L->tp ;
   ++ len ;
  }
 }
 return len ;
}

Status GListEmpty( GList L )
{
 if( L == NULL || ( L->tag == LIST && !( L->hp ) ) )  //"L == NULL" is more clear than "!L".
 {
  return OK ;
 }
 return FALSE ;
}

GList GetHead( GList L )
{
 GList h , p ;

 if( L == NULL || ( L->tag == LIST && !( L->hp ) ) )
 {
  return NULL ;
 }

 p = L->hp->tp ;  //p point to the tail!  take care about it!
 L->hp->tp = NULL ; // cut the tail!

 CopyGList( &h , L->hp ) ;//very good!
 L->hp->tp = p ;  //recover the tail!

 return h ;
}

GList GetTail( GList L )
{
 GList t , p ;

 if( L == NULL || ( L->tag == LIST && !( L->hp ) ) )
 {
  return NULL ;
 }

 p = L->hp ;
 L->hp = p->tp ;  //cut head of 'p'! Then L is a tail!

 CopyGList( &t , L ) ;
 L->hp = p ;   //recover!

 return t ;
}

Status InsertFirst_GL( GList *L , GList e )
{
 GList p ;

 p = ( *L )->hp ;
 ( *L )->hp = e ;
 e->tp = p ;   //link!

 return OK ;
}

Status DeleteFirst_GL( GList *L , GList *e )
{
 if( ( *L ) && ( *L )->hp )
 {
  *e = ( *L )->hp ;
  ( *L )->hp = ( *e )->tp ;
  ( *e )->tp = NULL ;
 }
 else
 {
  *e = *L ;
 }
 return OK ;
}

Status Travers_GL( GList L , void ( *v )( AtomType ) )
{
 GList hp ;
 if( L )
 {
  if( L->tag == ATOM )
  {
   v( L->atom ) ;
   hp = NULL ;
  }
  else
  {
   hp = L->hp ;
  }

  Travers_GL( hp , v ) ;
  Travers_GL( L->tp , v ) ;
 }
 return OK ;
}

Status visit( AtomType e )
{
 printf( "%3c" , e ) ;
 return OK ;
}

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

int main( )
{
 char *ch = { "(a,(b),c,(d,(e)))" } ;
 SString T ;
 GList L  ;

 InitGList( &L ) ;
 StrAssign( T , ch ) ;

// printf( "%d\n" , GListEmpty( L ) ) ;  //'1' equal empty!
// printf( "%d\n" , GListDepth( L ) ) ;
// printf( "%d\n" , GListLength( L ) ) ;

 CreateGList( &L , T ) ;

 puts( ch ) ;
// printf( "%d\n" , GListEmpty( L ) ) ; 
// printf( "%d\n" , GListDepth( L ) ) ;
// printf( "%d\n" , GListLength( L ) ) ;
 
 Travers_GL( L , visit ) ;
 printf( "\n" ) ;

 Travers_GL( GetHead( L ) , visit ) ;
 printf( "\n" ) ;

 Travers_GL( GetTail( L ) , visit ) ;
 printf( "\n" ) ;

 InsertFirst_GL( &L , GetHead( L ) ) ;
 Travers_GL( L , visit ) ;
 printf( "\n" ) ;
 
 DeleteFirst_GL( &L , GetHead( L ) ) ;
 Travers_GL( L , visit ) ;
 printf( "\n" ) ;

return 0 ;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值