您的位置:首页 > 其它

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

2015-04-26 17:22 459 查看
#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 ) ;
[code] L->head->next = NULL ;
L->len = 0 ;
}
void FreeNode( Link *p )
{
free( *p ) ;
*p = NULL ;
}

[/code]
看到"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来申请空间。),所以何必要申请空间呢!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: