草庐IT

数据结构 C++实现一元多项式运算(链式存储)

82年苏打 2023-04-11 原文

文章目录

一、实验目的

1、 了解线性表的特性,以及它在实际问题中的应用。
2、掌握线性表的链式存储的实现方法以及它的基本操作,学会运用单链表来解决问题。

二、实验内容

题目:用带头节点的单链表存储一元多项式的每一项,实现求一元多项式的加法、减法和乘法。具体要求为:用五个函数分别实现一元多项式的创建、输出、加法、减法和乘法;然后在主函数中调用这些函数实现这些功能的展示,以菜单的形式呈现。

三、代码内容

1、多项式创建

可以乱序输入多项式,在创建时自动会升序排序

void creatlist(polynomial &p) {
	//输入n项的系数和指数,建立表示多项式的有序链表p
	p = new PNode;	//为链表P1申请一个空间;
	int n;
	cout << "请输入多项式项数:";
	cin >> n;
	p->next = NULL;	//建立一个带头节点的单链表
	polynomial t,q;	//用于标记位置
	for (int i = 1; i <= n; i++) {//依次输入n个非0项,并将他们排序
		polynomial s = new PNode;	//生成一个新节点,用于存储输入的系数和指数
		cout << "请分别输入系数和指数: " ;
		cin >> s->coef >> s->expn;	//输入系数和指数
		t = p;	//t用于保存q的前驱,初值为头节点,为了让p只表示头节点
		q = p->next;	//q初始化,指向首元节点
		while (q && q->expn < s->expn) {//从头到尾开始比较指数找到第一个大于输入指数的项*q
			t = q;
			q = q->next;	//q指向下一个节点
		}	//while
		s->next = q;	//将输入项s插入到q和其他前驱节点pre之间
		t->next = s;
	}	//for
}

2、输出函数

最后一项的输出带有“+”而我用’\b’并没有消除加号,我只好先遍历出多项式系数再单独输出最后一项

void printout(polynomial p) {
	int n = 0;
	polynomial t = p;
	while (t=t->next) {
		n++;	//多项式项数
	}	//while
	p = p->next;
	for (int i = 1; i < n; i++) {
		if (p->coef != 0 && p->expn == 0) //判断是否为常数项
			cout << p->coef << "+";
		else if (p->coef < 0) {
			cout << "\b";
			cout << p->coef << "x^" << p->expn << "+";
		}
		else
			cout << p->coef << "x^" << p->expn << "+";
		p = p->next;
	}
	//单独输出最后一项
	if (p->coef < 0) {
		cout << "\b";
		cout << p->coef << "x^" << p->expn;
	}
	else
		cout << p->coef << "x^" << p->expn;
}

3、多项式加减法

加法和减法的实现没有太大变化
这里我为了节约空间没有创建储存空间,把结果保存到的p1的空间中
这也导致了后续想要进行加减法运算需要重建输入多项式

//多项式加法
void add_polynomial(polynomial p1,polynomial p2) {
	//多项式加法:p1=p1+p2,利用两个多项式的节点构成“和多项式”
	polynomial t = p1;	//t指向p1的头节点
	polynomial flag = t;	//用来标记p1的头节点
	p1 = p1->next;
	p2 = p2->next;	//p1,p2分别指向首元节点
	while (p1 && p2) {	//p1,p2均非空时运行
		if (p1->expn == p2->expn) {	//指数相等时
			p1->coef += p2->coef;	//系数相加,存的p1里
			if (p1->coef) {	//coef不等于0时
				t->next = p1;	//将修改后的p1当前节点链在t之后
				t = p1;	//t指向p1
				p1 = p1->next;	//p1指向下一项
				polynomial r = p2;	//临时存储p2节点
				p2 = p2->next;	//p2后移
				delete r;	//删除原p2节点
			}
			else {	//系数和为0
				polynomial r = p1;	//临时存储p1节点
				p1 = p1->next;	//p1后移
				delete r;	//删除原p1节点
				polynomial rr = p2;	//临时存储p2节点
				p2 = p2->next;	//p2后移
				delete rr;	//删除原p2节点
			}
		}
		else if (p1->expn < p2->expn) {	//p1指数小于p2指数
			t->next = p1;	//将修改后的p1当前节点链在t之后,
			t = p1;	//t指向p1
			p1 = p1->next;	//指向下一项
		}
		else {	//p1的指数大于p2的指数
			t->next = p2;	//将修改后的p2当前节点链在t之后,
			t = p2;	//t指向p2
			p2 = p2->next;	//指向下一项
		}
	}	//while
	t->next = p1 ? p1 : p2;	//插入非空多项式的剩余片段
	cout << "相加的结果为:" << endl;
	printout(flag);	//输出结果
	delete p2;	//释放p2空间
}

//多项式减法
void subtruct_polynomial(polynomial p1,polynomial p2) {
	//多项式减法:p1=p1-p2,利用两个多项式的节点构成“和多项式”
	polynomial t = p1;	//t指向p1的头节点
	polynomial flag = t;	//用来标记p1的头节点
	p1 = p1->next;
	p2 = p2->next;	//p1,p2分别指向首元节点
	while (p1 && p2) {	//p1,p2均非空时运行
		if (p1->expn == p2->expn) {	//指数相等时
			p1->coef -= p2->coef;	//系数相减,存的p1里
			if (p1->coef) {	//coef不等于0时
				t->next = p1;	//将修改后的p1当前节点链在t之后,
				t = p1;	//t指向p1
				p1 = p1->next;	//p1指向下一项
				polynomial r = p2;	//临时存储p2节点
				p2 = p2->next;	//p2后移
				delete r;	//删除原p2节点
			}
			else {	//系数差为0
				polynomial r = p1;	//临时存储p1节点
				p1 = p1->next;	//p1后移
				delete r;	//删除原p1节点
				polynomial rr = p2;	//临时存储p2节点
				p2 = p2->next;	//p2后移
				delete rr;	//删除原p2节点
			}
		}
		else if (p1->expn < p2->expn) {	//p1指数小于p2指数
			t->next = p1;	//将修改后的p1当前节点链在t之后,
			t = p1;	//t指向p1
			p1 = p1->next;	//指向下一项
		}
		else {	//p1的指数大于p2的指数
			p2->coef *= -1;	//系数要乘-1变成相反数
			t->next = p2;	//将修改后的p2当前节点链在t之后,
			t = p2;	//t指向p2
			p2 = p2->next;	//指向下一项
		}
	}	//while
	if (p1)
		t->next = p1;	//插入剩余片段
	if (p2) 
		while (p2) {
			p2->coef *= -1;	//系数要乘-1变成相反数
			t->next = p2;	//将修改后的p2当前节点链在t之后,
			t = p2;	//t指向p2
			p2 = p2->next;	//指向下一项
		}
	cout << "相减的结果为:" << endl;
	printout(flag);	//输出结果
	delete p2;	//释放p2空间
}

4、冒泡排序

为了后续乘法运算做铺垫

//排序函数
void sort(polynomial p,polynomial head) {
	p = head;
	polynomial t1 = p->next;
	polynomial t2 = p->next;
	polynomial t3 = NULL;
	float ct;
	int et;
	//冒泡排序
	while (t2!=t3) {	//t1非空
		while (t1->next!=t3) {
			if ((t1->expn) > (t1->next->expn)) {
				ct = t1->coef;
				t1->coef = t1->next->coef;
				t1->next->coef = ct;
				et = t1->expn;
				t1->expn=t1->next->expn;
				t1->next->expn = et;
			}//if
			t1 = t1->next;
		}	//while
		t3 = t1;
		t1 = p->next;	//t1重置
	}//while
}	

5、多项式乘法

乘法运算:先相乘,然后再排好序,最后再合并同类项

void multiply_polynomial(polynomial& p1, polynomial& p2) {
	//先相乘,再排序,后合并
	polynomial head2 = p2;	//标记p2头结点
	polynomial head = new PNode;
	polynomial flag;
	flag = head;
	//先相乘
	p1 = p1->next;
	p2 = p2->next;
	while (p1) {//为NULL时退出循环
		while (p2) {//为NULL时退出循环
			polynomial t = new PNode;
			t->coef = p1->coef * p2->coef;	//系数相加,存到t中
			t->expn = p1->expn + p2->expn;	//指数相加
			flag->next = t;
			t->next = NULL;
			flag = t;
			p2 = p2->next;
		}
		p1 = p1->next;
		p2 = head2->next;	//重置p2
	} 	//while
	//再排序
	sort(flag, head);
	//合并
	for (polynomial q = head->next; q && q->next;) {
		if (q->expn == q->next->expn) {
			q->coef += q->next->coef;	//系数相加
			q->next = q->next->next;	//后一位插入
		}
		else q = q->next;
	}	//for
	cout << "相乘的结果为:" << endl;
	printout(head);	//输出结果
}

6、总代码

#include<iostream>
using namespace std;

//定义多项式结构体
typedef struct PNode{
	float coef;	//系数
	int expn;	//指数
	struct PNode *next;	//指针域
}PNode,*polynomial;

//创建多项式
void creatlist(polynomial &p) {
	//输入n项的系数和指数,建立表示多项式的有序链表p
	p = new PNode;	//为链表P1申请一个空间;
	int n;
	cout << "请输入多项式项数:";
	cin >> n;
	p->next = NULL;	//建立一个带头节点的单链表
	polynomial t,q;	//用于标记位置
	for (int i = 1; i <= n; i++) {//依次输入n个非0项,并将他们排序
		polynomial s = new PNode;	//生成一个新节点,用于存储输入的系数和指数
		cout << "请分别输入系数和指数: " ;
		cin >> s->coef >> s->expn;	//输入系数和指数
		t = p;	//t用于保存q的前驱,初值为头节点,为了让p只表示头节点
		q = p->next;	//q初始化,指向首元节点
		while (q && q->expn < s->expn) {//从头到尾开始比较指数找到第一个大于输入指数的项*q
			t = q;
			q = q->next;	//q指向下一个节点
		}	//while
		s->next = q;	//将输入项s插入到q和其他前驱节点pre之间
		t->next = s;
	}	//for
}

//输出多项式
void printout(polynomial p) {
	int n = 0;
	polynomial t = p;
	while (t=t->next) {
		n++;	//多项式项数
	}	//while
	p = p->next;
	for (int i = 1; i < n; i++) {
		if (p->coef != 0 && p->expn == 0) //判断是否为常数项
			cout << p->coef << "+";
		else if (p->coef < 0) {
			cout << "\b";
			cout << p->coef << "x^" << p->expn << "+";
		}
		else
			cout << p->coef << "x^" << p->expn << "+";
		p = p->next;
	}
	//单独输出最后一项
	if (p->coef < 0) {
		cout << "\b";
		cout << p->coef << "x^" << p->expn;
	}
	else
		cout << p->coef << "x^" << p->expn;
}

//多项式加法
void add_polynomial(polynomial p1,polynomial p2) {
	//多项式加法:p1=p1+p2,利用两个多项式的节点构成“和多项式”
	polynomial t = p1;	//t指向p1的头节点
	polynomial flag = t;	//用来标记p1的头节点
	p1 = p1->next;
	p2 = p2->next;	//p1,p2分别指向首元节点
	while (p1 && p2) {	//p1,p2均非空时运行
		if (p1->expn == p2->expn) {	//指数相等时
			p1->coef += p2->coef;	//系数相加,存的p1里
			if (p1->coef) {	//coef不等于0时
				t->next = p1;	//将修改后的p1当前节点链在t之后
				t = p1;	//t指向p1
				p1 = p1->next;	//p1指向下一项
				polynomial r = p2;	//临时存储p2节点
				p2 = p2->next;	//p2后移
				delete r;	//删除原p2节点
			}
			else {	//系数和为0
				polynomial r = p1;	//临时存储p1节点
				p1 = p1->next;	//p1后移
				delete r;	//删除原p1节点
				polynomial rr = p2;	//临时存储p2节点
				p2 = p2->next;	//p2后移
				delete rr;	//删除原p2节点
			}
		}
		else if (p1->expn < p2->expn) {	//p1指数小于p2指数
			t->next = p1;	//将修改后的p1当前节点链在t之后,
			t = p1;	//t指向p1
			p1 = p1->next;	//指向下一项
		}
		else {	//p1的指数大于p2的指数
			t->next = p2;	//将修改后的p2当前节点链在t之后,
			t = p2;	//t指向p2
			p2 = p2->next;	//指向下一项
		}
	}	//while
	t->next = p1 ? p1 : p2;	//插入非空多项式的剩余片段
	cout << "相加的结果为:" << endl;
	printout(flag);	//输出结果
	delete p2;	//释放p2空间
}

//多项式减法
void subtruct_polynomial(polynomial p1,polynomial p2) {
	//多项式减法:p1=p1-p2,利用两个多项式的节点构成“和多项式”
	polynomial t = p1;	//t指向p1的头节点
	polynomial flag = t;	//用来标记p1的头节点
	p1 = p1->next;
	p2 = p2->next;	//p1,p2分别指向首元节点
	while (p1 && p2) {	//p1,p2均非空时运行
		if (p1->expn == p2->expn) {	//指数相等时
			p1->coef -= p2->coef;	//系数相减,存的p1里
			if (p1->coef) {	//coef不等于0时
				t->next = p1;	//将修改后的p1当前节点链在t之后,
				t = p1;	//t指向p1
				p1 = p1->next;	//p1指向下一项
				polynomial r = p2;	//临时存储p2节点
				p2 = p2->next;	//p2后移
				delete r;	//删除原p2节点
			}
			else {	//系数差为0
				polynomial r = p1;	//临时存储p1节点
				p1 = p1->next;	//p1后移
				delete r;	//删除原p1节点
				polynomial rr = p2;	//临时存储p2节点
				p2 = p2->next;	//p2后移
				delete rr;	//删除原p2节点
			}
		}
		else if (p1->expn < p2->expn) {	//p1指数小于p2指数
			t->next = p1;	//将修改后的p1当前节点链在t之后,
			t = p1;	//t指向p1
			p1 = p1->next;	//指向下一项
		}
		else {	//p1的指数大于p2的指数
			p2->coef *= -1;	//系数要乘-1变成相反数
			t->next = p2;	//将修改后的p2当前节点链在t之后,
			t = p2;	//t指向p2
			p2 = p2->next;	//指向下一项
		}
	}	//while
	if (p1)
		t->next = p1;	//插入剩余片段
	if (p2) 
		while (p2) {
			p2->coef *= -1;	//系数要乘-1变成相反数
			t->next = p2;	//将修改后的p2当前节点链在t之后,
			t = p2;	//t指向p2
			p2 = p2->next;	//指向下一项
		}
	cout << "相减的结果为:" << endl;
	printout(flag);	//输出结果
	delete p2;	//释放p2空间
}
//排序函数
void sort(polynomial p,polynomial head) {
	p = head;
	polynomial t1 = p->next;
	polynomial t2 = p->next;
	polynomial t3 = NULL;
	float ct;
	int et;
	//冒泡排序
	while (t2!=t3) {	//t1非空
		while (t1->next!=t3) {
			if ((t1->expn) > (t1->next->expn)) {
				ct = t1->coef;
				t1->coef = t1->next->coef;
				t1->next->coef = ct;
				et = t1->expn;
				t1->expn=t1->next->expn;
				t1->next->expn = et;
			}//if
			t1 = t1->next;
		}	//while
		t3 = t1;
		t1 = p->next;	//t1重置
	}//while
}	

//多项式乘法
void multiply_polynomial(polynomial& p1, polynomial& p2) {
	//先相乘,再排序,后合并
	polynomial head2 = p2;	//标记p2头节点
	polynomial head = new PNode;
	polynomial flag;
	flag = head;
	//先相乘
	p1 = p1->next;
	p2 = p2->next;
	while (p1) {//为NULL时退出循环
		while (p2) {//为NULL时退出循环
			polynomial t = new PNode;
			t->coef = p1->coef * p2->coef;	//系数相加,存到t中
			t->expn = p1->expn + p2->expn;	//指数相加
			flag->next = t;
			t->next = NULL;
			flag = t;
			p2 = p2->next;
		}
		p1 = p1->next;
		p2 = head2->next;	//重置p2
	} 	//while
	//再排序
	sort(flag, head);
	//合并
	for (polynomial q = head->next; q && q->next;) {
		if (q->expn == q->next->expn) {
			q->coef += q->next->coef;	//系数相加
			q->next = q->next->next;	//后一位插入
		}
		else q = q->next;
	}	//for
	cout << "相乘的结果为:" << endl;
	printout(head);	//输出结果
}

//菜单函数
void display() {
	cout << "========================" << endl;
	cout << "1.创建多项式" << endl;
	cout << "2.多项式加法" << endl;
	cout << "3.多项式减法" << endl;
	cout << "4.多项式乘法" << endl;
	cout << "0.退出" << endl;
	cout << "========================" << endl;
}

int main() {
	int n;
	polynomial p1 = new PNode;	//为链表P1申请一个空间;
	polynomial p2 = new PNode;	//为链表P2申请一个空间;
	display();
	while (true) {
		cout << "请输入要执行的操作:";
		cin >> n;
		switch (n) {
		case 1:
			creatlist(p1);
			cout << "第一个多项式为:";
			printout(p1);
			cout << endl;
			creatlist(p2);
			cout << "第二个多项式为:";
			printout(p2);
			cout << endl;
			break;
		case 2:
			//多项式相加
			add_polynomial(p1,p2);
			cout << endl;
			break;
		case 3:
			//多项式减法
			subtruct_polynomial(p1,p2);
			cout << endl;
			break;
		case 4:
			//多项式相乘
			multiply_polynomial(p1,p2);
			cout << endl;
			break;
		case 0:
			exit(1);
		default:
			cout << "输入不合法,请重新输入!" << endl;
			cout << endl;
			break;
		}
	}
	return 0;
}

四、运行结果

测试内容:

五、总结

这个程序还有很多不足之处,输出多项式时最后一项的“+”为什么不能用‘\b’删除,多项式的加减乘没有使用储存空间导致每次运算都需要重新输入等等,如果有人知道为什么输出多项式时最后一项的“+”为什么不能用‘\b’删除,希望能教教我。

有关数据结构 C++实现一元多项式运算(链式存储)的更多相关文章

  1. ruby - 使用 ruby​​ 将 HTML 转换为纯文本并维护结构/格式 - 2

    我想将html转换为纯文本。不过,我不想只删除标签,我想智能地保留尽可能多的格式。为插入换行符标签,检测段落并格式化它们等。输入非常简单,通常是格式良好的html(不是整个文档,只是一堆内容,通常没有anchor或图像)。我可以将几个正则表达式放在一起,让我达到80%,但我认为可能有一些现有的解决方案更智能。 最佳答案 首先,不要尝试为此使用正则表达式。很有可能你会想出一个脆弱/脆弱的解决方案,它会随着HTML的变化而崩溃,或者很难管理和维护。您可以使用Nokogiri快速解析HTML并提取文本:require'nokogiri'h

  2. ruby - 解析 RDFa、微数据等的最佳方式是什么,使用统一的模式/词汇(例如 schema.org)存储和显示信息 - 2

    我主要使用Ruby来执行此操作,但到目前为止我的攻击计划如下:使用gemsrdf、rdf-rdfa和rdf-microdata或mida来解析给定任何URI的数据。我认为最好映射到像schema.org这样的统一模式,例如使用这个yaml文件,它试图描述数据词汇表和opengraph到schema.org之间的转换:#SchemaXtoschema.orgconversion#data-vocabularyDV:name:namestreet-address:streetAddressregion:addressRegionlocality:addressLocalityphoto:i

  3. ruby - 触发器 ruby​​ 中 3 点范围运算符和 2 点范围运算符的区别 - 2

    请帮助我理解范围运算符...和..之间的区别,作为Ruby中使用的“触发器”。这是PragmaticProgrammersguidetoRuby中的一个示例:a=(11..20).collect{|i|(i%4==0)..(i%3==0)?i:nil}返回:[nil,12,nil,nil,nil,16,17,18,nil,20]还有:a=(11..20).collect{|i|(i%4==0)...(i%3==0)?i:nil}返回:[nil,12,13,14,15,16,17,18,nil,20] 最佳答案 触发器(又名f/f)是

  4. ruby - 如何根据特征实现 FactoryGirl 的条件行为 - 2

    我有一个用户工厂。我希望默认情况下确认用户。但是鉴于unconfirmed特征,我不希望它们被确认。虽然我有一个基于实现细节而不是抽象的工作实现,但我想知道如何正确地做到这一点。factory:userdoafter(:create)do|user,evaluator|#unwantedimplementationdetailshereunlessFactoryGirl.factories[:user].defined_traits.map(&:name).include?(:unconfirmed)user.confirm!endendtrait:unconfirmeddoenden

  5. ruby - Ruby 有 `Pair` 数据类型吗? - 2

    有时我需要处理键/值数据。我不喜欢使用数组,因为它们在大小上没有限制(很容易不小心添加超过2个项目,而且您最终需要稍后验证大小)。此外,0和1的索引变成了魔数(MagicNumber),并且在传达含义方面做得很差(“当我说0时,我的意思是head...”)。散列也不合适,因为可能会不小心添加额外的条目。我写了下面的类来解决这个问题:classPairattr_accessor:head,:taildefinitialize(h,t)@head,@tail=h,tendend它工作得很好并且解决了问题,但我很想知道:Ruby标准库是否已经带有这样一个类? 最佳

  6. ruby - 是否有用于序列化和反序列化各种格式的对象层次结构的模式? - 2

    给定一个复杂的对象层次结构,幸运的是它不包含循环引用,我如何实现支持各种格式的序列化?我不是来讨论实际实现的。相反,我正在寻找可能会派上用场的设计模式提示。更准确地说:我正在使用Ruby,我想解析XML和JSON数据以构建复杂的对象层次结构。此外,应该可以将该层次结构序列化为JSON、XML和可能的HTML。我可以为此使用Builder模式吗?在任何提到的情况下,我都有某种结构化数据-无论是在内存中还是文本中-我想用它来构建其他东西。我认为将序列化逻辑与实际业务逻辑分开会很好,这样我以后就可以轻松支持多种XML格式。 最佳答案 我最

  7. ruby - 我如何添加二进制数据来遏制 POST - 2

    我正在尝试使用Curbgem执行以下POST以解析云curl-XPOST\-H"X-Parse-Application-Id:PARSE_APP_ID"\-H"X-Parse-REST-API-Key:PARSE_API_KEY"\-H"Content-Type:image/jpeg"\--data-binary'@myPicture.jpg'\https://api.parse.com/1/files/pic.jpg用这个:curl=Curl::Easy.new("https://api.parse.com/1/files/lion.jpg")curl.multipart_form_

  8. 世界前沿3D开发引擎HOOPS全面讲解——集3D数据读取、3D图形渲染、3D数据发布于一体的全新3D应用开发工具 - 2

    无论您是想搭建桌面端、WEB端或者移动端APP应用,HOOPSPlatform组件都可以为您提供弹性的3D集成架构,同时,由工业领域3D技术专家组成的HOOPS技术团队也能为您提供技术支持服务。如果您的客户期望有一种在多个平台(桌面/WEB/APP,而且某些客户端是“瘦”客户端)快速、方便地将数据接入到3D应用系统的解决方案,并且当访问数据时,在各个平台上的性能和用户体验保持一致,HOOPSPlatform将帮助您完成。利用HOOPSPlatform,您可以开发在任何环境下的3D基础应用架构。HOOPSPlatform可以帮您打造3D创新型产品,HOOPSSDK包含的技术有:快速且准确的CAD

  9. ruby - Rack:如何将 URL 存储为变量? - 2

    我正在编写一个简单的静态Rack应用程序。查看下面的config.ru代码:useRack::Static,:urls=>["/elements","/img","/pages","/users","/css","/js"],:root=>"archive"map'/'dorunProc.new{|env|[200,{'Content-Type'=>'text/html','Cache-Control'=>'public,max-age=6400'},File.open('archive/splash.html',File::RDONLY)]}endmap'/pages/search.

  10. 华为OD机试用Python实现 -【明明的随机数】 2023Q1A - 2

    华为OD机试题本篇题目:明明的随机数题目输入描述输出描述:示例1输入输出说明代码编写思路最近更新的博客华为od2023|什么是华为od,od薪资待遇,od机试题清单华为OD机试真题大全,用Python解华为机试题|机试宝典【华为OD机试】全流程解析+经验分享,题型分享,防作弊指南华为o

随机推荐