C语言数据结构:一元多项式运算器

一元多项式运算器的分析与实现

  • 首先,需要解决一元多项式在计算机中的存储问题。对于一元多项式: P = p0 + p1x + …+pnx^n ;在计算机中,可以用一个线性表来表示: P = (p0,p1,…,pn), 但是对于形如 S(x) = 1 + 5x^10 000 -12x^15 000 的多项式,上面的方法显然不合适,会有很多的项系数为0,造成存储空间的浪费,因此只需要存储非0系数项。

  • 为了实现任意多项式的运算,考虑到运算时有较多的插入、删除操作,选择单链表作为存储结构比较方便,每个结点有三个域:系数、指数和指针。其数据结构如下所示:**

    typedef struct DuoXiangShi{
    	int xi_shu;  //系数
    	int zhi_shu; //指数
    	struct DuoXiangShi *next;  //指向下一个结点的指针
    	 
    }Polyn, *LinkPolyn;
    

一、建立多项式

  • 通过键盘输入一组多项式的系数和指数,用尾插法建立一元多项式的链表。以输入系数0为结束标志,并约定建立一元多项式链表时,总是按指数从小到大的顺序排列。

    /*用尾插法创建链表*/
    LinkPolyn CreatePolyn(){
    	LinkPolyn head,p,tail;
    	 
    	float x;      //存储输入的系数 
    	int   e;      //存储输入的指数
    	head = (LinkPolyn)malloc(sizeof(Polyn));     //生成头结点
    	head->next = NULL;                   //生成空表
    	tail = head;
    	scanf("%d,%d",&x,&e);
    	while(x!=0)                  //当x=0时,多项式输入结束 
    	{
    		p = (LinkPolyn)malloc(sizeof(Polyn));
    		p->xi_shu = x;
    		p->zhi_shu = e;
    		tail->next = p;     //在表尾进行插入操作 
    		tail = p;           //tail始终指向表尾 
    		scanf("%f,%d",&x,&e);	
    	}
    	tail->next = NULL;          //将表中最后一个结点的next置为NULl 
    	
    	return head;
    } 
    

二、输出多项式

  • 从单链表第一个元素开始,逐项读出系数和指数,按多项式的形式进行输出即可。

    /*打印多项式*/
    void PrintPolyn(LinkPolyn LA)
    {
    	LinkPolyn p = LA->next;      //LA有头结点,让p指向LA的第一元素结点
    	int flag = 1;
    	
    	if(!p)       //如果链表为空,没有项 
    	{
    		putchar('0');
    		printf("\n");
    		//return;
    	}
    	
    	while(p)
    	{
    		if(p->xi_shu > 0 && flag != 1)  putchar('+');
    		//if(p->xi_shu == 0) continue;
    		if(p->xi_shu != 1 && p->xi_shu != -1 && p->xi_shu != 0)
    		{
    			printf("%d",p->xi_shu);
    			if(p->zhi_shu == 1)
    			{
    				putchar('X');
    			}
    			else if(p->zhi_shu)
    			{
    				printf("X^%d",p->zhi_shu);
    			}
    			else               /*系数为1或系数为-1的情况*/
    			{
    				if(p->xi_shu == 1)
    				{
    					//如果指数为0
    					if(!p->zhi_shu)   putchar('1');
    					else if(p->zhi_shu == 1)  putchar('X');
    					else        printf("X^%d",p->zhi_shu); 
    				}
    				if(p->xi_shu == -1) 
    				{
    					//如果指数为0
    					if(!p->zhi_shu)   printf("-1");
    					else if(p->zhi_shu == 1)  printf("-X");
    					else        printf("-X^%d",p->zhi_shu);
    				}
    			}
    			
    			p = p->next;
    			flag++;
    		}
    		else{
    			p = p->next;
    		}
    	}
    	printf("\n");
    }
    

三、两个多项式相加

  • 以单链表LA和LB分别表示两个一元多项式A和B,A+B的求和运算就等同于单链表的插入,设一个单链表LC来存放LA+LB的和。

    /*两个多项式相加------返回的还是一个多项式*/
    LinkPolyn AddPolyn(LinkPolyn LA,LinkPolyn LB)
    {
    	LinkPolyn pa = LA->next;      //指向LA的第一元素结点
    	LinkPolyn pb = LB->next;      //指向LB的第一元素结点	
    	
    	LinkPolyn LC,pc,qc;     //LC存储LA+LB
    	pc = (LinkPolyn)malloc(sizeof(struct DuoXiangShi));
    	pc->next = NULL;
    	LC = pc;        //保留原链的头指针 
    	
    	//当两个多项式均未扫描结束时 
    	while(pa != NULL && pb != NULL) 
    	{
    		qc = (LinkPolyn)malloc(sizeof(struct DuoXiangShi));
    		if(pa->zhi_shu < pb->zhi_shu)
    		{
    			qc->xi_shu = pa->xi_shu;
    			qc->zhi_shu = pa->zhi_shu;
    			pa = pa->next;
    		}
    		else if(pa->zhi_shu == pb->zhi_shu)
    		{
    			qc->xi_shu = pa->xi_shu + pb->xi_shu;
    			qc->zhi_shu = pa->zhi_shu;
    			pa = pa->next;
    			pb = pb->next; 
    		}
    		else
    		{
    			qc->xi_shu = pb->xi_shu;
    			qc->zhi_shu = pb->zhi_shu;
    			pb = pb->next; 
    		}
    		if(qc->xi_shu != 0)
    		{
    			qc->next = pc->next;
    			pc->next = qc;
    			pc = qc;
    		}
    		else free(qc);
    	} 
    	/*如果LA中有余项,将剩余项插入LC*/
    	while(pa != NULL)
    	{
    		qc = (LinkPolyn)malloc(sizeof(struct DuoXiangShi));
    		qc->xi_shu = pa->xi_shu;
    		qc->zhi_shu = pa->zhi_shu;
    		pa = pa->next;
    		qc->next = pc->next;
    		pc->next = qc;
    		pc = qc;
    	} 
    	/*如果LB中有余项,将剩余项插入LC*/
    	while(pb!= NULL)
    	{
    		qc = (LinkPolyn)malloc(sizeof(struct DuoXiangShi));
    		qc->xi_shu = pb->xi_shu;
    		qc->zhi_shu = pb->zhi_shu;
    		pb = pb->next;
    		qc->next = pc->next;
    		pc->next = qc;
    		pc = qc;
    	} 
    	return LC;	
    } 
    

四、两个多项式相减

  • 将减数LB多项式的所有系数变为其相反数,然后使用两个多项式相加的思想进行处理。

    /*两个多项式相减------返回的还是一个多项式*/
    LinkPolyn SubstractPolyn(LinkPolyn LA,LinkPolyn LB)
    {
    	LinkPolyn b = LB;
    	LinkPolyn p = LB->next;
    	LinkPolyn LD;
    	while(p)
    	{
    		p->xi_shu *= -1;
    		p = p->next;
    	}
    	
    	LD = AddPolyn(LA,b);
    	
    	for(p = b->next; p ;p = p->next)
    	{
    		p->xi_shu *= -1;
    	}
    	return LD;
    } 
    
    

五、多项式乘法

  • 多项式乘法类似于两个多项式相加,需要使用一个多项式的每一项和另一个多项式的每一项进行相乘,然后进行多项式相加操作

    /*多项式相乘*/
    LinkPolyn MultiplyPolyn(LinkPolyn LA,LinkPolyn LB)
    {
    	LinkPolyn pa = LA->next;
    	LinkPolyn pb = LB->next;
    	LinkPolyn LC,pc,qc;
    	LinkPolyn LD; 
    	LD = (LinkPolyn)malloc(sizeof(Polyn));
    	LD->next = NULL;        //建立一个空表 
    	
    	while(pa != NULL)
    	{
    		
    		pc = (LinkPolyn)malloc(sizeof(struct DuoXiangShi));
    		pc->next = NULL;
    		LC = pc; 
    		while(pb != NULL)
    		{
    			qc = (LinkPolyn)malloc(sizeof(struct DuoXiangShi));
    			qc->xi_shu = pa->xi_shu * pb->xi_shu;
    			qc->zhi_shu = pa->zhi_shu + pb->zhi_shu;
    			qc->next = pc->next;
    			pc->next = qc;
    			pc = qc; 
    			pb = pb->next; 
    		}
    		LD = AddPolyn(LD,LC);
    		pa = pa->next;
    		pb = LB->next;
    	}
    	return LD;
    } 
    

六、求多项式的值

  • 需要输入变量x的值,然后进行求值运算

    /*多项式求值*/
    int EvaluatePolyn(LinkPolyn polyn,int x)
    {
    	LinkPolyn p = polyn->next;
    	int sum = 0;
    	while(p != 0)
    	{
    		sum += p->xi_shu*pow(x,p->zhi_shu);
    		p = p->next;
    	}
    	return sum;
    }
    

七、多项式的导数

  • 需要根据导数公式对多项式的每一个结点求导,具体过程如下:多项式的当前结点指数为0,则其导数为0;当前结点指数不为0,则其导数的系数为当前结点指数乘以系数,指数为当前结点的指数减1。

    /*多项式的导数,返回值仍然为一个多项式*/
    LinkPolyn DaoPolyn(LinkPolyn polyn)
    {
    	LinkPolyn dao = polyn;
    	LinkPolyn p = polyn->next;
    	while(p!=NULL)
    	{
    		if(p->zhi_shu != 0)
    		{
    			p->xi_shu = p->zhi_shu * p->xi_shu;
    			p->zhi_shu = p->zhi_shu - 1;
    			p = p->next; 
    		}
    		else
    		{
    			p->xi_shu = 0;	
    			p = p->next;
    		}
    		
    	 
    	}
    	return dao;
    } 
    
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值