第二章(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来申请空间。),所以何必要申请空间呢!
相关文章推荐
- 数据结构学习之路-第二章:一元多项式的表示及相加
- 一元多项式的表示及相加(抽象数据类型Polynomial的实现)
- 一元多项式的表示及相加(抽象数据类型Polynomial的实现)
- 一元多项式的表示及相加
- pat(A) 1002. A+B for Polynomials (一元多项式的表示及相加)
- 2007.08.25一元多项式的表示及相加
- 数据结构学习笔记 --- 线性表 (一元多项式的表示及相加)
- 一元多项式的表示及相加
- 数据结构学习笔记 --- 线性表 (一元多项式的表示及相加)
- 利用单链表实现一元多项式的表示及相加
- 一元多项式的表示和相加
- 一元多项式表示相加操作
- Polynomial 一元多项式的表示及相加 (线性链表实现 严蔚敏版)
- 链表表示的 一元多项式,无参构造器,有参构造器,相加,遍历
- 一元多项式的表示及相加
- 一元多项式的表示及相加 【链表的应用】
- Polynomial 一元多项式的表示及相加 (线性链表实现 严蔚敏版)
- Polynomial 一元多项式的表示及相加 (线性链表实现 严蔚敏版)
- 线性表的应用---一元多项式的表示与相加
- 用单链表表示一元多项式及相加相减相乘运算