#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来申请空间。),所以何必要申请空间呢!