第二章(6).一元多项式的表示及相加

来源:互联网 发布:mac安装包损坏 编辑:程序博客网 时间:2024/06/04 00:37

#include < stdio.h >
#include < stdlib.h >
//#include < math.h >

typedef struct {    //项的表示,多项式的项做为LinkList的数据元素
 float coef ;    //系数
 int  expn ;    //指数(用指数来表示位置?)
} term , ElemType ;

typedef struct LNode {   //结点
 ElemType elem ;
 struct LNode *next ;
} *Link , *Position ;

typedef struct {
 Link head ;    //头结点空置,不存储值.省去了tail尾指针。
 int  len ;    
} LinkList ;

typedef LinkList polynomial ; //用带表头结点的有序链表表示多项式
#define  TRUE 1
#define  FALSE 0
#define  OK  1
#define  ERROR 0

//------------------链表基本操作函数---------------------//

void InitList( LinkList *L )
{
 L->head = ( Link )malloc( sizeof( struct LNode ) ) ;       //头结点空置,不存储值
 if( !L->head )
  exit( 0 ) ;

 L->head->next =  NULL ;
 L->len = 0 ;

}

Position GetHead( LinkList L )
{ //返回线性链表L中头结点的位置
 return  L.head ; 
}

void SetCurElem( Link *p , ElemType e )
{
  ( *p )->elem = e ;
}

ElemType GetCurElem( Link p )
{
 return p->elem ;
}

int ListEmpty( LinkList L )
{
 return L.len == 0 ;
// if( L.len == 0 )
//  return TRUE ;
// return FALSE ;
}

void InsFirst( Link h , Link s )
{ //将s所指结点插入在h所指结点之后 //注意:此处和书上略有不同,如果按照书上所说的那样做,那在本例中就会是一个倒序的形式.
         
 s->next = h->next ;
 h->next = s ;
}

void DelFirst( Link h , Link *q )
{ //删除链表中h所指结点后的第一个结点并以q返回   //同上
 *q = h->next ;
 h->next = ( *q )->next ;
}

void Append( LinkList *L , Link s )
{ //将指针s所指的一串结点链接在线性链表L的最后一个结点之后
 Link p = ( *L ).head ;
 while( p->next )
 {
  p = p->next ;
 }
 p->next = s ; 
}

Position PriorPos( LinkList L , Link p )
{ //已知p指向线性链表L中的一个结点,返回p所指结点的直接前驱的位置,若无前驱,则返回NULL.
 Link q = L.head ;
 while( q->next && q->next !=  p )
  q = q->next ;
 if( q->next )
  return q ;
 return NULL ;
}

Position NextPos( LinkList L , Link p )
{ //已知p指向线性链表L中的一个结点,返回p所指结点的直接后继的位置,若无后继,则返回NULL.
 Link q = L.head ;
 while( q && q !=  p )    //PriorPos与NextPos的区别在于头结点的处理
  q = q->next ;
 if( q )
  return q->next ;
 return NULL ;
}

void FreeNode( Link *p )
{
 free( *p ) ;
 *p = NULL ;
}

int LocateElem( LinkList L , ElemType e , Position *q , int ( *compare )( ElemType , ElemType ) ) 

{
 Link p = L.head ;
 while( p->next )
 {
  if( compare( p->next->elem , e ) < 0 )
  {
   p = p->next ;
  }
  else   
  {
   if( compare( p->next->elem , e ) == 0 )
   {
    *q = p->next ;
    return TRUE ;
   }
   else         //compare( p->next->elem , e ) > 0 
   {
    *q = p ;
    return FALSE ;
   }
  }  
 }
 *q = p ;
 return FALSE ;
}
int MakeNode( Link *s , ElemType e )
{
 *s = ( Link )malloc( sizeof( struct LNode ) ) ;
 if( *s )
 {
  ( *s )->elem = e ;
  return OK ;
 }
 return ERROR ;
}
void OrderInsert( LinkList *L , ElemType e , int ( *compare )( ElemType , ElemType ) )
{ //按有序判定函数compare()的约定,将值为e的结点插入到有序链表L的适当位置上
 Link p = ( *L ).head ;
 Position q , s ;

 if( LocateElem( *L , e , &q , compare )  ) //原链表中有相同指数的结点
 {
  q->elem.coef += e.coef ;
  if( !q->elem.coef )      //系数变为0,删除当前结点
  {
   s = PriorPos( *L , q ) ;
   if( !s )       //前驱不存在
    s = ( *L ).head ;
   DelFirst( s ,  &q ) ;  
   FreeNode( &q ) ;
   ( *L ).len-- ;
  }
 }
 else          //原链表无有相同指数的结点
 {
  if( MakeNode( &s , e ) )
  {
   InsFirst( q , s ) ;
   ( *L ).len++ ;
  }
 }
}

//----------------一元多项式基本操作函数-----------------//

int cmp( term a , term b )
{ //依a的指数值<(或=)(或>)b的指数值,分别返回-1,0和+1
 return ( a.expn < b.expn ) ? -1 :( ( a.expn > b.expn ) ? 1 : 0 ) ;
// return ( a.expn - b.expn == 0 ) ? 0 :( ( a.expn - b.expn )/abs( a.expn - b.expn) ) ;
}

void CreatPolyn( polynomial *P , int m )  
{ //输入m项的系数和指数,建立表示一元多项式的有序链表P
 Link h , s ;
 ElemType e ;
 int i ;
 Position q ;

 InitList( P ) ;
 h = GetHead( *P ) ;
 e.coef = 0.0 ; e.expn = -1 ;
 SetCurElem( &h , e ) ;    //设置头结点的数据元素
 for( i = 1 ; i < m + 1 ; ++ i )  //依次输入m个非零项
 {
  scanf( "%f %d", &e.coef , &e.expn ) ;
  if( !LocateElem( *P , e , &q , cmp ) ) //当前链表中不存在该指数项
  {
   if( MakeNode( &s , e ) )
   {
    InsFirst( q , s ) ;
    ( *P ).len++ ;
   }
  }
 } 
}

void DestroyPolyn( polynomial *P )
{ //销毁一元多项式P
 Link q , L = ( *P ).head ;

 while( L->next )    //删除L的下一个结点,所以必须保证L的下一个结点存在
 {
  DelFirst( L , &q ) ;
  ( *P ).len-- ;
  FreeNode( &q ) ;
 }
 FreeNode( &L ) ;    //头结点
 L = NULL ;
}

void PrintPolyn( polynomial P )
{
 Link q = P.head ;
 while( q->next )
 {
  printf( "{ %f , %d } " , q->next->elem.coef , q->next->elem.expn ) ;
  q = q->next ;
 }
}

void AddPoly( polynomial *Pa , polynomial *Pb )
{ //完成多项式相加运算,即Pa = Pa + Pb,并销毁一元多项式Pb
 Position ha = GetHead( *Pa ) , hb = GetHead( *Pb ) ;   //ha, hb分别指向Pa和Pb中头结点
 Position qa = NextPos( *Pa , ha ) , qb = NextPos( *Pb , hb ) ; //qa,qb分别指向Pa和Pb中当前结点(头结点空置)
 ElemType a , b , c ;
 float sum ;

 while( qa && qb )
 {
  a = GetCurElem( qa ) , b = GetCurElem( qb ) ;
  switch( cmp( a , b ) )
  {
  case -1:
   ha = qa ; qa = NextPos( *Pa , qa ) ;
   break ;
  case 0:         //两者指数值相等
   sum = a.coef + b.coef ;
   if( sum )       //修改多项式Pa中当前结点的系数值
   {
    c.expn = a.expn ;
    c.coef = sum ;
    SetCurElem( &qa , c ) ;
    ha = qa ;
   }
   else        //删除多项式Pa中当前结点
   {
    DelFirst( ha , &qa ) ;
    Pa->len-- ;
    FreeNode( &qa ) ;
   }
   DelFirst( hb , &qb ) ;
   Pb->len-- ;
   FreeNode( &qb ) ;
   qb = NextPos( *Pb , hb ) ;
   qa = NextPos( *Pa , ha ) ;
   break ;
  case 1:         //多项式Pb中当前结点的指数值小
   DelFirst( hb , &qb ) ;
   Pb->len-- ;
   InsFirst( ha , qb ) ;
   Pa->len-- ;
   qb = NextPos( *Pb , hb ) ;
   ha = NextPos( *Pa , ha ) ;
   break ;
  }  // switch
 } //while
 if( !ListEmpty( *Pb ) )
  Append( Pa , qb ) ;   //链接Pb中剩余结点
 FreeNode( &hb ) ;    //释放Pb的头结点
}


void AddPoly2( polynomial *Pa , polynomial *Pb )
{
 Position hb = GetHead( *Pb ) ;
 Position qb = NextPos( *Pb , hb ) ;
 term b ;

 while( qb )
 {
  b = GetCurElem( qb ) ;
  OrderInsert( Pa , b , cmp ) ;
  qb = qb->next ;
 }
 DestroyPolyn( Pb ) ;
}

void SubtractPoly( polynomial *Pa , polynomial *Pb )
{ //完成多项式相加运算,即Pa = Pa - Pb,并销毁一元多项式Pb
 Position ha = GetHead( *Pa ) , hb = GetHead( *Pb ) ;   //ha, hb分别指向Pa和Pb中头结点
 Position qa = NextPos( *Pa , ha ) , qb = NextPos( *Pb , hb ) ; //qa,qb分别指向Pa和Pb中当前结点(头结点空置)
 Position qc ;
 ElemType a , b , c ;
 float sum ;

 while( qa && qb )
 {
  a = GetCurElem( qa ) , b = GetCurElem( qb ) ;
  switch( cmp( a , b ) )
  {
  case -1:
   ha = qa ; qa = NextPos( *Pa , qa ) ;
   break ;
  case 0:         //两者指数值相等
   sum = a.coef - b.coef ;    //Take care!
   if( sum )       //修改多项式Pa中当前结点的系数值
   {
    c.expn = a.expn ;
    c.coef = sum ;
    SetCurElem( &qa , c ) ;
    ha = qa ;
   }
   else        //删除多项式Pa中当前结点
   {
    DelFirst( ha , &qa ) ;
    Pa->len-- ;
    FreeNode( &qa ) ;
   }
   DelFirst( hb , &qb ) ;
   Pb->len-- ;
   FreeNode( &qb ) ;
   qb = NextPos( *Pb , hb ) ;
   qa = NextPos( *Pa , ha ) ;
   break ;
  case 1:         //多项式Pb中当前结点的指数值小
   DelFirst( hb , &qb ) ;
   Pb->len-- ;
   qb->elem.coef = 0 - qb->elem.coef ; //Take care!
//   qb->elem.coef -= 2*qb->elem.coef ;
   InsFirst( ha , qb ) ;
   Pa->len-- ;
   qb = NextPos( *Pb , hb ) ;
   ha = NextPos( *Pa , ha ) ;
   break ;
  }  // switch
 } //while
 if( !ListEmpty( *Pb ) )      //Take care!
 {
  qc = qb ;
  while( qc )
  {
   qc->elem.coef = 0 - qc->elem.coef ;
   qc = qc->next ;
  }
  Append( Pa , qb ) ;   //链接Pb中剩余结点
 }
 FreeNode( &hb ) ;    //释放Pb的头结点

}

void SubtractPoly2( polynomial *Pa , polynomial *Pb )
{
 Position qc ;
 if( !ListEmpty( *Pb ) )      //Take care!
 {
  qc = Pb->head->next ;
  while( qc )
  {
//   qc->elem.coef = 0 - qc->elem.coef ;
   qc->elem.coef *= -1 ;
   qc = qc->next ;
  }
  AddPoly( Pa , Pb ) ;
 }
}

void MultiplyPoly( polynomial *Pa , polynomial *Pb )
{
 Position ha = GetHead( *Pa ) , hb = GetHead( *Pb ) ;   //ha, hb分别指向Pa和Pb中头结点
 Position q , qb , qa = NextPos( *Pa , ha ) ; //qa,qb分别指向Pa和Pb中当前结点(头结点空置)
 term a , b , c ;
 polynomial Pc ;

 InitList( &Pc ) ;
 while( qa )
 {
  a = GetCurElem( qa ) ;
  qb = NextPos( *Pb , hb ) ;
  while( qb )
  {
   b = GetCurElem( qb ) ;
   c.coef = a.coef * b.coef ;
   c.expn = a.expn + b.expn ;
   OrderInsert( &Pc , c , cmp ) ;
   qb = qb->next ;
  }
  ha->next = qa->next ;  //顺便删除用过的结点,便于下面的操作。
  q = qa ;
  qa = qa->next ;
  free( q ) ;
 }
 DestroyPolyn( Pb ) ;
 Pa->head = Pc.head ;
 Pa->len = Pc.len ; 
}

//---------------------Main----------------------//

int main( )
{
 polynomial Pa , Pb ;

 CreatPolyn( &Pa , 3 ) ;
 CreatPolyn( &Pb , 3 ) ;
 
// AddPoly2( &Pa , &Pb ) ;
// SubtractPoly2( &Pa , &Pb ) ;
 MultiplyPoly( &Pa , &Pb ) ;

 PrintPolyn( Pa ) ;
 printf( "\n" ) ;     // 最好用字符串格式。用字符格式'\n',没有影响,但是会有警告!
 DestroyPolyn( &Pa ) ;

 return 0 ;
}


这次学习可谓得到了一个很深刻的教训啊!就是关于对于链表标准型的嵌套结构体的空间申请问题:

 void InitList( LinkList *L )
{
 L->head = ( Link )malloc( sizeof( struct LNode ) ) ;       //头结点空置,不存储值
 if( !L->head )
  exit( 0 ) ;
 L->head->next =  NULL ;
 L->len = 0 ;
}
void FreeNode( Link *p )
{
 free( *p ) ;
 *p = NULL ;
}


看到"void InitList( LinkList *L )",按着本能,就想着给给L申请空间"L = (LinkList*)malloc(sizeof(LinkList)",结果经历很长一段时间的调试,看到书本后面关于链队列空间的申请,突然恍然大悟!这里只能"L->head = ( Link )malloc( sizeof( struct LNode ) ) ; " 就从空间上来说,L所指内容还包括len,但len定义的是一个整数,所以已有空间,再去给它申请,岂不是会有冲突!!!LinkList的那个结构体中本无指针类型(当然这里是把Link当成一个内建型别,而Link空间的申请得由它所属的那个结构体去申请,所以有L->head来申请空间。),所以何必要申请空间呢!
0 0
原创粉丝点击