一元多项式的相加、相减、相乘

实验名称  一元多项式的相加、相减、相乘   

一元多项式相加:

#include <stdio.h>

#include <stdlib.h>

typedef struct tagNode

{

    float coef;

    int exp;

    struct tagNode *pNext;

};



typedef struct tagNode Node;

typedef struct tagNode *pNode;



// 将结点插入到链表的适当位置,这是一个指数升序排列的链表

void insertList(pNode head, pNode pnode) // 链表头结,待插入的结点

{

    pNode pPre = head;

    while(pPre->pNext != NULL)

    {

        if (pPre->pNext->exp > pnode->exp)

        {

            pnode->pNext = pPre->pNext;

            pPre->pNext = pnode;

            break;

        }

        else if(pPre->pNext->exp == pnode->exp)                 // 添加一个判断,判断新加入的结点和之前已加入结点是否有指数相同情况

        {                                                       // 即合并同类项

            pPre->pNext->coef = pPre->pNext->coef+pnode->coef;

            free(pnode);

            break;

        }

        pPre = pPre->pNext;

    }

    if (pPre->pNext == NULL) // 待插入的结点指数最大,直接插入到结点最后

    {

        pPre->pNext = pnode;

    }

}



// 输出链表

void printLinkedList(pNode head)

{

    pNode temp = head->pNext;

    while (temp != NULL)

    {

        printf(" %g", temp->coef);

        printf("x^%d +", temp->exp);

        temp = temp->pNext;

    }

    printf("\b \n");

}



// 两链表相加

void add_poly(Node *pa, Node *pb)

{

    Node *p = pa->pNext;   // 链表1,多项式结果放在链表1

    Node *q = pb->pNext;   // 链表2

    Node *pre = pa;

    Node *temp;            // 临时用

    float x;

    while(p != NULL && q != NULL)     // 当两个链表都不为空

    {

        if (p->exp < q->exp)          // 链表1的指数小于链表2的指数

        {

            pre = p;

            p = p->pNext;             // 链表1存放加和数据,不用操作。只需后移指针

        }

        else if(p->exp == q->exp)     // 链表1指数和链表2指数相等

        {

            x = p->coef + q->coef;    // x存放系数和。判断x是否为0

            if (x != 0)               // x不为0则在链表1中更新加和的值

            {

                p->coef = x;

                pre = p;

            }

            else                      // x为0则从链表1中移除该项

            {

                pre->pNext = p->pNext;

                free(p);

            }

            p = pre->pNext;           // p指向下一个判断的结点



            // 链表2结点的删除部分。

            temp = q;

            q = q->pNext;

            free(temp);

        }

        else                          // 如果链表1指数大于链表2指数,把当前结点插入链表1比较结点前

        {

            temp = q->pNext;

            q->pNext = p;

            pre->pNext = q;

            pre = q;

            q = temp;

        }

    }

    if (q)                           // 如果链表2比链表1长,则需要把2多余部分加到1后面。反之不用操作

    {

        pre->pNext = q;

    }

    free(pb);

}



int main()

{

    pNode head1 = (pNode)malloc(sizeof(struct tagNode));   // 给头指针分配空间

    pNode head2 = (pNode)malloc(sizeof(struct tagNode));

    int exp, temp1;                                               // 指数

    float coef, coef2;                                            // 系数

    pNode pTemp = NULL;

    head1->pNext = NULL;

    head2->pNext = NULL;



    // 读入多项式1

    printf("请输入要放入链表1中的数据,顺序为\'系数,指数\'。若多项式结束,则以0结尾。\n");

    // 读入数据,以0,0结尾,把数据插入链表中。

    scanf("%f,%d", &coef, &exp);

    while(coef != 0 || exp != 0)

    {

        pTemp = (pNode)malloc(sizeof(struct tagNode));

        pTemp->coef = coef;

        pTemp->exp = exp;

        pTemp->pNext = NULL;

        insertList(head1, pTemp);

        //temp1 = exp;

        //temp2 = coef;

        scanf("%f,%d", &coef, &exp)

    }

    printf("指数升序排列的多项式1为:\n");

    printLinkedList(head1);

    printf("\n");



    // 读入多项式2

    printf("请输入要放入链表2中的数据,顺序为\'系数,指数\'。若多项式结束,则以0结尾。\n");

    // 读入数据,以0,0结尾,把数据插入链表中。

    scanf("%f,%d", &coef, &exp);

    while(coef != 0 || exp != 0)

    {

        pTemp = (pNode)malloc(sizeof(struct tagNode));

        pTemp->coef = coef;

        pTemp->exp = exp;

        pTemp->pNext = NULL;

        insertList(head2, pTemp);

        scanf("%f,%d", &coef, &exp);

    }

    printf("指数升序排列的多项式2为:\n");

    printLinkedList(head2);

    printf("\n");



    // 多项式相加

    add_poly(head1, head2);

    printf("多项式相加的结果为:\n");

    printLinkedList(head1);

    printf("\n");

    return 0;

}

 

一元多项式相减:

#define   OK                    1

#define   ERROR                 0

#define   OVERFLOW             -2

#define   TRUE                  1

#define   FALSE                 0

typedef   int   Status;//为了方便算法可用性,算法的Status可以通过这里可改

#include <stdio.h>

#include <stdlib.h>

typedef struct{//项的表示,多项式的项作为LinkList的数据元素

    int coef;//系数

    int expn;//指数

}term, ElemType;//两个类型:term用于本ADT,ElemType为LinkList的数据对象名

typedef struct LNode{//节点类型

    ElemType  data;//这里表示了每一项,其指数和系数

    struct LNode *next;

}*Link, *Position;

typedef struct{//链表类型

    Link head, tail;//分别指向线性链表中的头结点和最后一个结点

    int len;//指示线性链表中数据元素的个数

}LinkList;//每一项组成一个列表

typedef LinkList polynomial;



Status InitList(LinkList *L)

{ /* 构造一个空的线性链表 */

    Link p;

    p = (Link)malloc(sizeof(LNode)); /* 生成头结点 */

    if (p)

    {

        p->next = NULL;

        (*L).head = (*L).tail = p;

        (*L).len = 0;

        return OK;

    }

    else

        return ERROR;//内存分配不够

}

Status MakeNode(Link *p, ElemType e)

{ /* 分配由p指向的值为e的结点,并返回OK;若分配失败。则返回ERROR */

    *p = (Link)malloc(sizeof(LNode));

    if (!*p)

        return ERROR;

    (*p)->data = e;

    return OK;

}



Status InsFirst(LinkList *L, Link h, Link s) /* 形参增加L,因为需修改L */

{ /* h指向L的一个结点,把h当做头结点,将s所指结点插入在第一个结点之前 */

    s->next = h->next;

    h->next = s;

    if (h == (*L).tail) /* h指向尾结点 */

        (*L).tail = h->next; /* 修改尾指针 */

    (*L).len++;

    return OK;

}



Position GetHead(LinkList L)

{ /* 返回线性链表L中头结点的位置 */

    return L.head;

}

Status SetCurElem(Link p, ElemType e)

{ /* 已知p指向线性链表中的一个结点,用e更新p所指结点中数据元素的值 */

    p->data = e;

    return OK;

}



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

{ /* 若升序链表L中存在与e满足判定函数compare()取值为0的元素,则q指示L中 */

    /* 第一个值为e的结点的位置,并返回TRUE;否则q指示第一个与e满足判定函数 */

    /* compare()取值>0的元素的前驱的位置。并返回FALSE。(用于一元多项式) */

    Link p = L.head, pp;

    do

    {

        pp = p;

        p = p->next;

    } while (p && (compare(p->data, e)<0)); /* 没到表尾且p->data.expn<e.expn */

    if (!p || compare(p->data, e)>0) /* 到表尾或compare(p->data,e)>0 */

    {

        *q = pp;

        return FALSE;

    }

    else /* 找到 */

    {/* 没到表尾且p->data.expn=e.expn */

        *q = p;

        return TRUE;

    }

}

Status Remove_Polyn(LinkList *L, Link q)

{ //由于项的指数为0,删除掉已有的项

    Link p, h;

    h = L->head;

    while (h->next != q)

    {

        h = h->next;

    }

    //找到了

    if (q == L->tail)

    {//删除的如果是表尾,改变表尾

        L->tail = h;

    }

    h->next = q->next;

    free(q);

    L->len--;

    return OK;

}

int cmp(term a, term b) // CreatPolyn()的实参

{ // 依a的指数值<、=或>b的指数值,分别返回-1、0或+1

    if (a.expn == b.expn)

        return 0;

    else

        return (a.expn - b.expn) / abs(a.expn - b.expn);

}

void CreatPolyn(polynomial &p, int m)

{//输入m项的系数和指数,建立表示一元多项式的有序链表P

    InitList(&p);//初始化多项式链表

    Link h = GetHead(p);//设置头结点的数据元素

    ElemType e;//头结点设置

    Position q, s;

    e.coef = 0; e.expn = -1; SetCurElem(h, e);//设置头结点的元素

    for (int i = 1; i <= m; ++i)//依次输入m个非零项

    {

        printf( "第 %d 项的系数:",i);

        scanf("%d",&e.coef);

        printf("第 %d 项的指数:",i);

        scanf("%d",&e.expn);

        if (!LocateElemP(p, e, &q, cmp))//当前链表中不存在该指数项

        {

            if (e.coef != 0)//不等于才插入

            if (MakeNode(&s, e))InsFirst(&p, q, s);//生成结点并插入链表

        }

        else//当前链表中存在该指数项,增加其系数

        {

            q->data.coef = q->data.coef + e.coef;

            //如果合起来等于0,则删除掉

            if (q->data.coef == 0)

                Remove_Polyn(&p, q);//删除掉当前节点

        }

    }

}

Status ListTraverse(LinkList L, void(*visit)(ElemType))

{ /* 依次对L的每个数据元素调用函数visit()。一旦visit()失败,则操作失败 */

    Link p = L.head->next;

    int j;

    for (j = 1; j <= L.len; j++)

    {

        visit(p->data);

        p = p->next;

    }

    printf("\b ");

    if (L.len == 0)

        printf("0");

    return OK;

}

void visit(ElemType e)

{

    if (e.coef > 0 && e.coef != 1 && e.expn != 0)

    {

        if (e.expn > 0)

printf("%dx^%d ",e.coef,e.expn);

//printf("+ ");

        else

printf("%dx^%d ",e.coef,e.expn);

printf("+ ");

    }

    else if (e.coef < 0 && e.expn != 0)

    {

        if (e.expn > 0)

printf("(%d)x^%d",e.coef,e.expn);

//printf("+ ");

        else

printf("(%d)x^(%d)",e.coef,e.expn);

printf(" + ");

    }

    else if (e.coef == 1 && e.expn != 0)

    {

        if (e.expn > 0)

printf("x^%d",e.expn);

//printf("+");

        else

printf("x^(%d)",e.expn);

printf(" + ");

    }

    else if (e.expn == 0 && e.coef != 0)

printf("%d",e.coef);

    else

        printf("");



}

Position NextPos(Link p)

{ /* 已知p指向线性链表L中的一个结点,返回p所指结点的直接后继的位置 */

    /* 若无后继,则返回NULL */

    return p->next;

}

ElemType GetCurElem(Link p)

{ /* 已知p指向线性链表中的一个结点,返回p所指结点中数据元素的值 */

    return p->data;

}

Status DelFirst(LinkList *L, Link h, Link *q) /* 形参增加L,因为需修改L */

{ /* h指向L的一个结点,把h当做头结点,删除链表中的第一个结点并以q返回。 */

    /* 若链表为空(h指向尾结点),q=NULL,返回FALSE */

    *q = h->next;

    if (*q) /* 链表非空 */

    {

        h->next = (*q)->next;

        if (!h->next) /* 删除尾结点 */

            (*L).tail = h; /* 修改尾指针 */

        (*L).len--;

        return OK;

    }

    else

        return FALSE; /* 链表空 */

}



void FreeNode(Link *p)

{ /* 释放p所指结点 */

    free(*p);

    *p = NULL;

}

Status ListEmpty(LinkList L)

{ /* 若线性链表L为空表,则返回TRUE,否则返回FALSE */

    if (L.len)

        return FALSE;

    else

        return TRUE;

}

Status Append(LinkList *L, Link s)

{ /* 将指针s(s->data为第一个数据元素)所指(彼此以指针相链,以NULL结尾)的 */

    /* 一串结点链接在线性链表L的最后一个结点之后,并改变链表L的尾指针指向新 */

    /* 的尾结点 */

    int i = 1;

    (*L).tail->next = s;

    while (s->next)

    {

        s = s->next;

        i++;

    }

    (*L).tail = s;

    (*L).len += i;

    return OK;

}

void AddPolyn(polynomial &Pa, polynomial &Pb)

{//多项式加法:Pa = Pa+Pb,利用两个多项式的结点构成“和多项式”

    Position ha, hb, qa = NULL, qb = NULL;

    term a, b;

    ha = GetHead(Pa); hb = GetHead(Pb);//ha和hb分别指向Pa和Pb的头结点

    if (Pa.len != 0 && Pb.len != 0)

    {

        qa = NextPos(ha); qb = NextPos(hb);//qa和qb分别指向Pa和Pb中的当前结点

        //此时qa和qb都是指向多项式第一项

        while (qa && qb)

        {//qa和qb非空

            a = GetCurElem(qa);

            b = GetCurElem(qb); // a和b为两表中当前比较元素

            int sum;

            switch (cmp(a, b))//比较两者的指数值

            {

            case -1://多项式中PA中的结点的指数小

                ha = qa;

                qa = NextPos(ha);

                break;

            case 0://两者指数值相等

                sum = a.coef + b.coef;

                if (sum != 0)

                {

                    //修改pa指向的该结点的系数值

                    qa->data.coef = sum;

                    //下一个

                    ha = qa;

                }

                else

                {

                    //删除结点

                    DelFirst(&Pa, ha, &qa);

                    FreeNode(&qa);

                }

                DelFirst(&Pb, hb, &qb);//也删除掉qb的结点

                //都往后移动一位

                qb = NextPos(hb);

                qa = NextPos(ha);

                break;

            case 1://多项式PB中的当前结点指数值小

                DelFirst(&Pb, hb, &qb);//把当前结点从PB中删除,并用qb指向当前结点用以插入

                InsFirst(&Pa, ha, qb);//插入在ha前

                qb = NextPos(hb);

                qa = NextPos(ha);

                break;

            }//switch

        }//while

        if (!ListEmpty(Pb))Append(&Pa, qb);//连接Pb中剩余结点

        FreeNode(&hb);//释放Pb的头结点

    }//A,B不为空

    if (Pa.len == 0)

    {

        Pa = Pb;//相加结果就是B

    }

    if (Pb.len == 0)

    {

        //相加结果就是A

    }

    //其中一个已经空了



}//AddPolyn

void Opposite(polynomial Pa)

{ // 一元多项式Pa系数取反

    Position p;

    p = Pa.head;

    while (p->next)

    {

        p = p->next;

        p->data.coef *= -1;

    }

}

void SubtractPolyn(polynomial &Pa, polynomial &Pb)

{//完成多项式相减运算,即:Pa = Pa-Pb,并销毁一元多项式Pb

    Opposite(Pb);

    AddPolyn(Pa, Pb);

}



int main()

{

    polynomial A, B;

    printf("请输入第一个多项式的项数为:");

    int length;

scanf("%d",&length);

    CreatPolyn(A, length);

    //显示A出来

    printf("PA(x) = ");

    ListTraverse(A, visit);

    printf("\n");

    //输入B

printf("请输入第二个多项式的项数为:");

    scanf("%d",&length);

    CreatPolyn(B, length);

    //输出B

    printf("PB(x) = ");

    ListTraverse(B, visit);

    printf("\n");

    //假设以上输入成功

    //进行相减

    SubtractPolyn(A, B);

    //这时候A是减后的结果

    printf("PA(x)-PB(x) = ");

    ListTraverse(A, visit);

    printf("\n");

    return 0;

}

一元多项式相乘

#include<stdio.h>

#include<stdlib.h>

#include<math.h>

#define LEN sizeof(Poly)

typedef struct term{

    float coef;        //系数

    int expn;        //指数

    struct term *next;

}Poly,*Link;

int LocateElem(Link p, Link s, Link &q);

void CreatePolyn(Link &p,int m);    //创建多项式

void PrintPolyn(Link p);            //打印多项式(表示)            

int cmp(Link a, Link b);

Link Reverse(Link p);                //逆置多项式

Link MultiplyPolyn(Link A,Link B);    //多项式相乘

void Calculate(Link p,float x);

       

int LocateElem(Link p, Link s, Link &q){

/*遍历链表p,每一个结点与s比较指数,

若相同,q指向相同指数项的结点,返回1,

若不相同,根据s所指指数大小在链表p中的位置来确定q的指向结点,返回0

*/

    Link p1 = p->next;

    Link p2 = p;

    while(p1){

        if(s->expn > p1->expn){

            p1 = p1->next;

            p2 = p2->next;

        }else if(s->expn == p1->expn){

            q = p1;

            return 1;

        }

else{

            q = p2;

            return 0;

        }

    }

    if(!p1){

        q = p2;

        return 0;

    }

}



void CreatePolyn(Link &p,int m)

/*创建带头结点的链表(多项式)

且无论按什么顺序输入,或是有相同指数项

最终在多项式中都是升幂顺序! 

*/

{

    Link s,q;

    int i;

    p=(Link)malloc(LEN);

    p->next=NULL;

    for(i=0;i<m;i++)

    {

        s=(Link)malloc(LEN);

        printf("输入系数和指数(以空格隔开):");

        scanf("%f %d", &s->coef, &s->expn);

        if(!LocateElem(p, s, q)){    //若没有相同指数项,则链入

            s->next = q->next;

            q->next = s;

        }else{                        //若有相同指数项,则系数相加                        

            q->coef+=s->coef;

        }

    }

}



void PrintPolyn(Link p)

//打印显示多项式

{

    Link s;

    s = p->next;

    while(s)

    {

            printf(" %.2f X^%d", s->coef, s->expn);

            s = s->next;

            if(s!=NULL)  

                if(s->coef>=0) printf(" +");

                //若下一项系数为正,则打印'+',否则不打印

    }

    printf("\n");

}

Link Reverse(Link p)

/*用头插法逆置链表,

使多项式由降幂变成升幂顺序

或使多项式由升幂变成降幂顺序

*/

{

    Link head=p;

    Link q1,q2;

    q2=head->next;

    head->next=NULL;//断开头结点与第一个结点

    while(q2)

    {

        q1=q2;      

        q2=q2->next;

        q1->next=head->next; //头插

        head->next=q1;  

    }      

    return head;//返回链表逆置后的头结点

}

Link MultiplyPolyn(Link A,Link B)

/*两个多项式相乘得一个新多项式,并且返回新多项式的头结点的指针

    相乘前,A,B两个多项式均是升幂排序

    相乘时,A为降幂排序,B为升幂排序  

*/

{

  Link pa,pb,pc,s,head;

  int k,maxExpn,minExpn;

  float coef;

  head=(Link)malloc(LEN);//头结点

  head->next=NULL;

  if(A->next!=NULL&&B->next!=NULL){

      minExpn=A->next->expn+B->next->expn; //minExpn为两个多项式中指数和的最小值

     A=Reverse(A);//将A降幂排列

    B=Reverse(B);//将B降幂排列

      maxExpn=A->next->expn+B->next->expn; //maxExpn为两个多项式中指数和的最大值

  }

  else{

          return head;

  }       

   pc=head;

   B=Reverse(B);//将B升幂排列

for(k = maxExpn;k>=minExpn;k--){ //多项式的乘积指数范围为:minExpn~maxExpn

           //根据两项的指数和使每一次循环都得到新多项式中一项  

           pa = A->next;

           while(pa !=NULL&&pa->expn>k){  //找到pa的位置

               pa = pa->next;

           }

           pb = B->next;

           while(pb!=NULL&&pa!=NULL&&pa->expn+pb->expn<k){//如果指数和和小于k,pb后移结点

               pb = pb->next;

           }

        coef=0.0;

        while(pa!=NULL&&pb!=NULL){

            if(pa->expn+pb->expn==k){ //如果指数和等于k,系数和累加,且pa,pb均后移结点

                coef+=pa->coef*pb->coef;

                pa=pa->next;

                pb=pb->next;

            }

            else if(pa->expn+pb->expn>k){//如果指数和大于k,pb后移结点

                pa = pa->next;

            }

            else{//如果指数和和小于k,pb后移结点

                    pb = pb->next;

            }    

        }

        if(coef!=0.0){

        //如果系数和不为0,则生成新结点,将系数和指数赋给新结点后插入到新多项式中

            s=(Link)malloc(LEN);

            s->coef=coef;

            s->expn=k;

            s->next=pc->next;

            pc->next=s;

            pc=s;

        }

   }

   B = Reverse(B);

   head=Reverse(head);

   return head;    //返回新多项式的头结点



}

int main()

{

    Link P1,P2,P3;    //多项式

    int L1,L2;        //多项式长度

    printf("请输入第一个多项式的项数:");

    scanf("%d",&L1);

    CreatePolyn(P1,L1);

    printf("第一个多项式为:");

    printf("P1(X)=");

    PrintPolyn(P1);

    printf("请输入第二个多项式的项数:");

    scanf("%d",&L2);

    CreatePolyn(P2,L2);

    printf("第二个多项式为:");

    printf("P2(X)=");

    PrintPolyn(P2);

    printf("\n");

  printf("两个一元多项式相乘:   ");

             printf("P1(X)*P2(X)=");

             P3=MultiplyPolyn(P1, P2);

            PrintPolyn(P3);

    return 0;

}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值