(二)1.4_一元稀疏多项式计算器

一.问题描述

(1)设Pn(x)和Qm(x)为两个一元稀疏多项式,利用单链表存储Pn(x)和Qm(x).
(2)从键盘输入一元多项式的信息,建立一元稀疏多项式Pn(x)和Qm(x),并输出.
(3)实现Pn(x)和Qm(x)相加,并输出两者的和Pn(x)+Qm(x).
(4)实现Pn(x)和Qm(x)相减,并输出两者的和Pn(x)-Qm(x).
(5)就地逆置两者的差Pn(x)-Qm(x).



二.思路分析

  这和上回我写的"(二)1.1_线性表求集合的并集"这篇博客中的算法可以说是一个算法,就是稍微改了一点.那下面还是再详细说说本篇文章的算法

一.加法运算的算法
  1.有两个有序链表(按指数递增排列)La和Lb分别存储多项式Pn(x)和Qm(x),.要计算他们的和,我们要再创建一个链表Lc,用来存储他们的和,然后我们分别用两个指针pa,pb分别指向La,和Lb对他们进行遍历
  2.是这样遍历的:我们对pa,pb指向的项进行指数的比较,
①如果是pa指向的项的指数更小,就在Lc中创建一个新节点存储这个项的元素,然后pa指针下移.
②同理,如果pb指向的项的指数更小,就在Lc中创建一个新节点存储这个项的元素,然后pb指针下移.
③如果pa和pb指向的项的指数相等,那么就在Lc中创建一个新节点,存储这两项相加得到的项,
也就是两项系数相加,指数不变(注意,如果相加系数是0,Lc就不要创建新节点存储了)

二.减法运算的算法
  减法的算法和加法同理,但也有一点改变
  1.有两个有序链表(按指数递增排列)La和Lb分别存储多项式Pn(x)和Qm(x),.要计算他们的差,我们要再创建一个链表Lc,用来存储他们的差,然后我们分别用两个指针pa,pb分别指向La,和Lb对他们进行遍历
  2.是这样遍历的:我们对pa,pb指向的项进行指数的比较,
①如果是pa指向的项的指数更小,就在Lc中创建一个新节点存储这个项的元素,然后pa指针下移.
②同理,如果pb指向的项的指数更小,就在Lc中创建一个新节点,存储pb指向的项的相反数,也就是系数取相反数,指数不变,然后pb指针下移.
③如果pa和pb指向的项的指数相等,那么就在Lc在创建一个新节点,存储这两项相减得到的项,
也就是两项系数相减,指数不变(注意,如果相减系数是0,Lc就不要创建新节点存储了)

三.差Pn(x)-Qm(x)的多项式的逆置算法
  其实这个简单,把存储多项式差的链表Lc的所有元素利用前插法依次存到新的链表L中,
得到的新链表L就是逆置了的多项式



三代码实现

#include"stdio.h"
#include"stdlib.h"
typedef struct
{
	float coef;  //系数
	int expn;   //指数
}ElemType;

typedef struct  Polynomial          //多项式链表
{
	ElemType elem;                  //项
	int length;                     //项数
	struct Polynomial* next;	   //下一节点指针
}*LinkList,LNode;

void InitList(LinkList* L)          //链表初始化
{
	*L=(LinkList)malloc(sizeof(LNode));
	(*L)->next=NULL;
	(*L)->length=0;
}

void PrintPolyn(LinkList L)        //显示多项式
{
	L=L->next;
	while(L!=NULL)
	{
		if(L->elem.coef>0)
		printf(" + %0.0fX^%d",L->elem.coef,L->elem.expn);

		else if(L->elem.coef<0)
		printf(" %0.0fX^%d",L->elem.coef,L->elem.expn);

		L=L->next;
	}
}
void SortPolyn(LinkList L)      //多项式排序,按指数大小递增排序
{
	LinkList head=L;
	LNode *p,*q,*temp;
	for(int i=head->length;i>=1;i--)
	{
		for(q=L;q->next->next!=NULL;q=q->next)
		{
			if(q->next->elem.expn>q->next->next->elem.expn)     //如果第n项比第n+1项指数大
			{
				temp=q->next;                                   //则第n项与第n+1项交换位置
				q->next=q->next->next;
				temp->next=q->next->next;
				q->next->next=temp;
			}

			else if(q->next->elem.expn==q->next->next->elem.expn)   //如果第n项与第n+1项指数相等
			{
				temp=q->next;                                      //则第n项累加至第n+1项,并删除第n项
				q->next->next->elem.coef+=temp->elem.coef;
			    q->next=q->next->next;
				free(temp);
				head->length--;
				i--;
			}
		}

	}
}
void CreatePolyn(LinkList L)                 //添加项
{
	LNode* node;
	LinkList head=L;
	float coef;
	int expn;
	scanf("%f",&coef);
	while(coef!=0)                           //输入0系数则输入操作结束
	{
		scanf("%d",&expn);
        node=(LNode*)malloc(sizeof(LNode));              //创建新节点
		node->elem.coef=coef;
		node->elem.expn=expn;
		node->next=NULL;
		L->next=node;                          //用后接法把新节点插入链表
		L=node;
		head->length++;
		scanf("%f",&coef);
	}
	SortPolyn(head);                         //排序,避免非指数递增项的输入
}
void AddPolyn(LinkList L1,LinkList L2,LinkList L3)     //多项式相加算法
{
	LinkList head=L3;
	while(L1->next&&L2->next)                                      //用指针遍历L1和L2各项,并相互比对
	{
		if(L1->next->elem.expn==L2->next->elem.expn)               //项指数相等
		{
			LNode* node=(LNode*)malloc(sizeof(LNode));
            node->elem.coef=L1->next->elem.coef+L2->next->elem.coef;         //则系数相加,指数不变,存入L3
            node->elem.expn=L1->next->elem.expn;
            node->next=NULL;
            if(node->elem.coef!=0)
            {
            L3->next=node;
            L3=node;
            head->length++;
            }
            else
            free(node);

			L1=L1->next;
			L2=L2->next;
		}
		else	if(L1->next->elem.expn<L2->next->elem.expn)          //L1中该项指数更小
		{
			LNode* node=(LNode*)malloc(sizeof(LNode));
			node->elem.expn=L1->next->elem.expn;
			node->elem.coef=L1->next->elem.coef;                     //将L1中该项该项存入L3 ,并且L1指针下移
			node->next=NULL;
			L3->next=node;
			L3=node;
			head->length++;
			L1=L1->next;
		}
		else                                                        //L2中该项指数更小
		{
			LNode* node=(LNode*)malloc(sizeof(LNode));
			node->elem.expn=L2->next->elem.expn;
			node->elem.coef=L2->next->elem.coef;                   //将L2中该项该项存入L2 ,并且L1指针下移
			node->next=NULL;
			L3->next=node;
			L3=node;
			head->length++;
			L2=L2->next;
		}
	}
		while(L1->next)                                         //L1还有项剩余则按顺序加入L3
	{
			LNode* node=(LNode*)malloc(sizeof(LNode));
			node->elem.expn=L1->next->elem.expn;
			node->elem.coef=L1->next->elem.coef;
			node->next=NULL;
			L3->next=node;
			L3=node;
			head->length++;
			L1=L1->next;
	}
	while(L2->next)                                           //L2还有项剩余则按顺序加入L3
	{
			LNode* node=(LNode*)malloc(sizeof(LNode));
			node->elem.expn=L2->next->elem.expn;
			node->elem.coef=L2->next->elem.coef;
			node->next=NULL;
			L3->next=node;
			L3=node;
			head->length++;
			L2=L2->next;
	}
}
void SubractPolyn(LinkList L1,LinkList L2,LinkList L3)            //多项式相减算法
{
	LinkList head=L3;
	while(L1->next&&L2->next)                                              //用指针遍历L1和L2各项,并相互比对
	{
		if(L1->next->elem.expn==L2->next->elem.expn)                       //项指数相等
		{
			LNode* node=(LNode*)malloc(sizeof(LNode));
            node->elem.coef=L1->next->elem.coef-L2->next->elem.coef;          //则系数相加,指数不变,存入L3
            node->elem.expn=L1->next->elem.expn;
            node->next=NULL;
            if(node->elem.coef!=0)
            {
            L3->next=node;
            L3=node;
            head->length++;
            }
            else
            free(node);

			L1=L1->next;
			L2=L2->next;
		}
		else	if(L1->next->elem.expn<L2->next->elem.expn)             //L1中该项指数更小
		{
			LNode* node=(LNode*)malloc(sizeof(LNode));
			node->elem.expn=L1->next->elem.expn;
			node->elem.coef=L1->next->elem.coef;                       //将L1中该项存入L3 ,并且L1指针下移
			node->next=NULL;
			L3->next=node;
			head->length++;
			L3=node;
			L1=L1->next;
		}
		else                                                             //L1中该项指数更小
		{
			LNode* node=(LNode*)malloc(sizeof(LNode));
			node->elem.expn=L2->next->elem.expn;
			node->elem.coef=-L2->next->elem.coef;                        //将L1中该项的系数取相反数并将该项存入L3 ,并且L2指针下移
			node->next=NULL;
			L3->next=node;
			L3=node;
			head->length++;
			L2=L2->next;
		}
	}

		while(L1->next)                                         //L1还有项剩余则按顺序加入L3
	{
			LNode* node=(LNode*)malloc(sizeof(LNode));
			node->elem.expn=L1->next->elem.expn;
			node->elem.coef=L1->next->elem.coef;
			L3->next=node;
			node->next=NULL;
			L3=node;
			head->length++;
			L1=L1->next;
	}
	while(L2->next)                                           //L1还有项剩余则将其系数取相反数并按顺序加入L3
	{
			LNode* node=(LNode*)malloc(sizeof(LNode));
			node->elem.expn=L2->next->elem.expn;
			node->elem.coef=-L2->next->elem.coef;
			L3->next=node;
			node->next=NULL;
			L3=node;
			head->length++;
			L2=L2->next;
	}
}
void InversePolyn(LinkList L)              //多项式逆置
{
	LNode *p,*q;
	p=L->next;
	L->next=NULL;                        //用前插法逆置节点
	while(p)
	{
	   q=p->next;
	   p->next=L->next;
	   L->next=p;
	   p=q;
	}

}
void DestoryList(LinkList L)                   //销毁链表
{
	LNode *p;
	p=L;
	while(L!=NULL)                            //遍历链表节点释放存储空间
	{
		L=L->next;
		free(p);
		p=L;
	}
}

int main()
{
    LinkList L1,L2,L3,L4;
    InitList(&L1);
    InitList(&L2);
    InitList(&L3);
    InitList(&L4);

    printf("输入多项式f1(x)\n");
    CreatePolyn(L1);
    printf("输入多项式f2(x)\n");
    CreatePolyn(L2);

    printf("\n\nf1(x)= ");
    PrintPolyn(L1);
    printf("\n\nf2(x)= ");
    PrintPolyn(L2);

    //多项式相加
    AddPolyn(L1,L2,L3);
    printf("\n\nf1(x)+f2(x)= ");
    PrintPolyn(L3);

    //多项式相减
    SubractPolyn(L1,L2,L4);
    printf("\n\nf1(x)-f2(x)= ");
    PrintPolyn(L4);

    //多项式逆置
    InversePolyn(L4);
    printf("\n\n逆置f1(x)-f2(x)= ");
    PrintPolyn(L4);

    //销毁链表释放存储空间
    DestoryList(L1);
    DestoryList(L2);
    DestoryList(L3);
    DestoryList(L4);

    return 0;
}

操作结果
在这里插入图片描述



四.相关提示

1.代码里我加了一个排序和合并相同指数项的函数,所以输入多项式时可以无序
2.这里的加法和减法算法的正常使用前提是在保证链表是有序的情况下,如果没有加入排序功能函数,那么输入时就要按指数递增的顺序来输入多项式了,否则运算出错.

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值