一元多项式加减乘实现c/c++

 一、实验题目:

 一元多项式简单的计算器

1.主要功能:

(1)输入并建立多项式;

(2)输出多项式;

(3)两个多项式相加,建立并输出和多项式;

(4)两个多项式相减,建立并输出差多项式。

(5)算法的时间复杂度、另外可以提出算法的改进方法

实现提示:可选择带头结点的单向循环链表或单链表存储多项式,头结点可存放多项式的参数,如项数等。

2.要求:一元多项式简单计算器的基本功能

二、代码 

 1.全局变量和主函数:

#include<iostream>
using namespace std;
const double T= 0.000001;//用于比较两个double类型的数是否相等;

double xs1[1000], xs2[1000], cs1[1000], cs2[1000];//储存两个一元多项式的系数和次数的数组
int n1, n2;//两个一元多项式的项数;
char x;//运算字符(“+”,“-”,“*”)

//储存每一项的系数和项数
struct term {
	double a;//系数
	double b;//次数
	term* next, * prior;
};

int main() {
	int flag = 0;
	while (1) {
		//输入
		input();
		//创建链表
		term *poly1= creat(xs1, cs1, n1);
		term *poly2 = creat(xs2, cs2, n2);
		term* poly=NULL;
		//计算
		loop:switch (x) {
		case '+':poly = add(poly1, poly2);break;
		case '-':poly = subtract(poly1, poly2);break;
		case '*':poly = multiply(poly1, poly2);break;
		case '>':flag = 1;break;
		default:
			cout << "暂时不提供该运算" << endl;
			cin >> x;
			goto loop;
		}
		//输出
		if (flag) {
			output(poly1);
			output(poly2);
		}else
		output(poly);
		
	}
	return 0;
}

2.创建多项式

        用双向链表表示一元多项式:头节点储存一元多项式的项数,创建新节点储存每一项的系数和次数,新节点的插入从头节点开始比遍历,找到次数大于新节点的节点,插入这个节点的前面。

*链表有序:方便后续的运算的实现

*双向链表:在插入时,需要找前驱节点,不用再次遍历链表,减小找时间复杂度。

这里其实还可以改进,找插入点时直接这样找:

while(q->next==NULL&&q->next->b>p->b){
           //……………………………………
}

这样就不用找前驱节点。

/*
目的:创建双向链表储存一元多项式;
输入参数:储存次数和系数的数组,项数;
返回值:有序(按次数小到大)的双向链表的头指针;
*/
term* creat(double xs[], double cs[], int n) {
	term* head, * p = NULL, * q = NULL;
	int i = 0;
	head = new term;
	head->a = n, head->b = 0;
	head->next = NULL;
	head->prior = NULL;
	q = head;
	while (i < n) {
		p = new term;
		p->a = xs[i];
		p->b = cs[i++];
		while (q != NULL && q->b < p->b) {
			q = q->next;
		}
		if (q == NULL) {
			q = head;
			while (q->next != NULL)
				q = q->next;
			p->next = NULL;
			p->prior = q;
			q->next = p;
		}
		else {
			p->next = q;
			q->prior->next = p;
			p->prior = q->prior;
			q->prior = p;
		}

		q = head;
	}
	return head;
}

2.加减乘实现

加法运算:

        创建新链表储存结果,将两个一元多项式的链表从头开始遍历,链表1和链表2比较次数,如果相等,将两个的系数相加的结果和系数按顺序插入新链表。将新节点插入新链表时,如果新链表中有次数与新节点相同,则直接将新节点的系数与该节点的系数相加。如果链表1的系数大,链表2进入下一个节点,直到链表1的系数小于链表2的系数,链表1进入下一个节点。直到有链表遍历完,将另一个链表的节点插入新链表。

其他的运算类似。

/*
目的:将两个一元多项式相加;
输入参数:两个一元多项式的链表头指针;
返回值:相加后的一元多项式的链表头指针;
*/
term* add(term* p1, term* p2) {
	p1 = p1->next, p2 = p2->next;
	term* head, * p, * q;
	head = new term;
	head->a = 0, head->b = 0;
	head->next = NULL;
	head->prior = NULL;
	q = head;
	while (p1 != NULL && p2 != NULL) {
		p = new term;
		if (p1->b- p2->b<T) {
			p->b = p1->b;
			p->a = p1->a + p2->a;
			p1 = p1->next;
			p2 = p2->next;
		}
		else if (p1->b < p2->b) {
			p->b = p1->b;
			p->a = p1->a;
			p1 = p1->next;
		}
		else {
			p->b = p2->b;
			p->a = p2->a;
			p2 = p2->next;
		}
		head = insert(p, head);
	}
	if (p1 == NULL) {
		while (p2 != NULL) {
			p = new term;
			p->b = p2->b;
			p->a = p2->a;
			head = insert(p, head);
			p2 = p2->next;
		}
	}
	if (p2 == NULL) {
		while (p1 != NULL) {
			p = new term;
			p->b = p1->b;
			p->a = p1->a;
			head = insert(p, head);
			p1 = p1->next;
		}
	}
	head->a = 0;
	head->b = 0;
	return head;
}

/*
目的:将两个一元多项式相减
输入参数:两个一元多项式的链表头指针;
返回值:相减后的一元多项式的链表头指针;
*/
term* subtract(term* p1, term* p2) {
	p1 = p1->next, p2 = p2->next;
	term* head, * p, * q;
	head = new term;
	head->a = 0, head->b = 0;
	head->next = NULL;
	head->prior = NULL;
	q = head;
	while (p1 != NULL && p2 != NULL) {
		p = new term;
		if (p1->b - p2->b<T) {
			p->b = p1->b;
			p->a = p1->a - p2->a;
			p1 = p1->next;
			p2 = p2->next;
		}
		else if (p1->b < p2->b) {
			p->b = p1->b;
			p->a = p1->a;
			p1 = p1->next;
		}
		else {
			p->b = p2->b;
			p->a = -p2->a;
			p2 = p2->next;
		}
		head = insert(p, head);
	}
	if (p1 == NULL) {
		while (p2 != NULL) {
			p = new term;
			p->b = p2->b;
			p->a = -p2->a;
			
			head = insert(p, head);
			p2 = p2->next;
		}
	}
	if (p2 == NULL) {
		while (p1 != NULL) {
			p = new term;
			p->b = p1->b;
			p->a = p1->a;
			
			head = insert(p, head);
			p1 = p1->next;
		}	
	}
	head->a = 0;
	head->b = 0;
	return head;
}

/*
目的:将两个一元多项式相乘
输入参数:两个一元多项式的链表头指针;
返回值:相乘后的一元多项式的链表头指针;
*/
term* multiply(term* p1, term* p2) {
	term* P2 = p2;
	p1 = p1->next, p2 = p2->next;
	term* head, * p, * q;
	head = new term;
	head->a = 0, head->b = 0;
	head->next = NULL;
	head->prior = NULL;
	q = head;
	while (p1 != NULL) {
		while (p2 != NULL) {
			p = new term;
			p->a = p1->a * p2->a;
			p->b = p1->b + p2->b;
			head = insert(p, head);
			p2 = p2->next;
		}
		p2 = P2->next;
		p1 = p1->next;

	}
	head->a = 0;
	head->b = 0;

	return head;
}

/*
目的:输入要计算的两个一元多项式的系数、次数和项数;
输入参数:无;
返回值:无;
*/

新节点插入链表:

       重用率最高的模块,极大的缩减代码篇幅。同时该函数也能确保结果链表依然保持有序。能对不同插入位置(链表尾,链表中)进行处理,能判断要插入的链表中是否有次数相同的节点,避免链表出现相同次数的节点。

/*
目的:将节点有序的插入链表;
输入参数:要插入的节点,被插入的链表头节点;
返回值:插入后的链表的头节点;
*/
term* insert(term* p, term* head) {
	term *q = head;
	while (q != NULL && q->b < p->b) {
		q = q->next;
	}
	if (q == NULL) {
		q = head;
		while (q->next != NULL)
			q = q->next;
		p->next = NULL;
		p->prior = q;
		q->next = p;
	}
	else if (q->b - p->b < T) {
		q->a += p->a;
	}
	else {
		p->next = q;
		p->prior = q->prior;
		q->prior->next = p;
		q->prior = p;
	}
	return head;
}

 3.输入输出

        提示输入信息,获取两个一元多项式的次数、系数和项数,次数和项数用数组储存。变量和数组均为全局变量,便于后续数据传递。

        输出时按要求打印输出即可。对一些特殊情况分类讨论,如次数或系数为1或0时输出的处理,结果为0时的输出处理。

/*
目的:输入要计算的两个一元多项式的系数、次数和项数;
输入参数:无;
返回值:无;
*/
void input() {
	cout << "请输入第一个一元多项式的项数:";
	cin >> n1;
	if (n1 >= 1000) {
		cout << "项数过多,请重新输入:";
		cin >> n1;
	}
	cout << "请输入每一项的系数:" << endl;
	for (int i = 0;i < n1;i++) {
		cin >> xs1[i];
	}
	cout << "请输入对应项数的次数:" << endl;
	for (int i = 0;i < n1;i++) {
		cin >> cs1[i];
	}
	cout << endl << "请输入第二个一元多项式的项数:";
	cin >> n2;
	if (n2 >= 1000) {
		cout << "项数过多,请重新输入:";
		cin >> n2;
	}
	cout << "请输入每一项的系数:" << endl;
	for (int i = 0;i < n2;i++) {
		cin >> xs2[i];
	}
	cout << "请输入对应项数的次数:" << endl;
	for (int i = 0;i < n2;i++) {
		cin >> cs2[i];
	}
	cout << "请输入你要进行的运算('+','-','*','>'):" << endl;
	cin >> x;
}

/*
目的:按格式输出结果;
输入参数:结果链表头节点;
返回值;无;
*/
void output(term* p) {
	int flag1 = 0, flag2 = 0;
	p = p->next;
	cout << "结果为:" << endl;
	while (p != NULL) {
		if (p->a != 0) {
			flag2 = 1;
		}
		else {
			p = p->next;
			continue;
		}
		if (p->b <T) {
			cout << p->a;
			flag1 = 1;
		}
		else {
			if (flag1 == 0) {
				if (p->a -1<T && p->b - 1>T)
					cout << "x^" << p->b;
				else if (p->a - 1<T && p->b - 1<T)
					cout << "x";
				else if (p->a - 1>T && p->b- 1<T)
					cout << p->a << "x";
				else
					cout << p->a << "x^" << p->b;
				flag1 = 1;
			}
			else {
				if (p->a - 1<T && p->b - 1>T)
					cout << "+" << "x^" << p->b;
				else if (p->a-1<T && p->b - 1<T)
					cout << "+" << "x";
				else if (p->a - 1>T && p->b - 1<T)
					cout << p->a << "x";
				else
					cout << "+" << p->a << "x^" << p->b;
			}
		}
		p = p->next;
	}
	if (flag2 == 0)
		cout << 0 << endl;
	cout << endl << endl << "----------------------------------" << endl;
}

三、总结

老师评价:

1.作为一个计算器而言,输入界面还不够直观,用户体验感缺乏。

2. 输入需要先输入项数,不能直接输入次数和项数。

3.两个一元多项式计算完再计算其他运算需要再次输入次数和系数。

4.基本功能实现,额外实现乘法。

自我体会:

         应该将这个当成一个项目,而不是一次题目,应该制造一个人能用的计算器,而不是完成题目给定的要求。

  • 1
    点赞
  • 21
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值