开始前说些走流程的废话,由于是第一次发博客,表达和讲解方法都不是那么成熟,
如果有什么地方有待改正,欢迎并感谢亲们在评论区留言
(让我感受一下捏你们对萌新的善意,谢谢谢谢)
那么,我们正式开始
单链表的基础概念
利用单链表解决多项式的加法和乘法,实际上就是利用简单的单链表结构体存储数据并进行运算,在解决这个问题之前,我们首先得知道,什么是单链表:
链表是一种数据结构(存储的数据分散在内存中,每个结点只能也只有它能知道下一个结点的存储位置),而单链表是链表的一种(特点是链表的链接方向是单向的),单链表由不定数量的节点构成,开始于对外暴露的头结点,结束于终端节点(引用为NULL)。
而节点的组成则包括节点自身存储的对象,以及下一节点的引用next(如下图图1),由于对外暴露的都只有头节点,所以对链表的所有操作,都是直接或者间接地通过其头节点来进行的。
(图1)
利用单链表解决多项式运算的算法流程
从算法思路开始说起
(此段为详细说明,整体代码在文末,只想看代码可以直接跳过)
一,设计多项式
不管是单项式加法还是乘法,第一步都是设计多项式,
我的想法是将多项式分解为一个个单项式,设计一个单项式类做节点,再设计链表,将各个单项式连接起来就形成了多项式。
(单项式类中应含有系数和指数这两种参数,同时还需要有对应的处理方法)
1,设置单项式节点
先建立单项式节点,使单项式可以表达出来
具体代码如下
package example;
public class PolymialNode {//建立一个多项式节点,包含系数和指数
private double coef;//系数
private int index;//指数
public PolymialNode next;//下一节点的引用
public PolymialNode() { //初始默认值设置为0
this(0, 0);
}
public PolymialNode(double coef, int index) {
this.coef = coef;
this.index = index;
}
public double getCoef() {
return coef;
}
public void setCoef(double coef) {
this.coef = coef;
}
public int getindex() {
return index;
}
public void setindex(int index) {
this.index = index;
}
}
2,连接单项式形成多项式
设置完单项式节点之后,我们就需要把单项式连接起来形成多项式,
此时就运用到了单链表,如图
代码部分如下
package example;
public class PolyList {
PolymialNode head;//头节点
PolymialNode current; //当前单项式节点
public PolyList(){
head = new PolymialNode();
current = head;
head.next = null;//设置下一节点头文件默认为空
}
public boolean isEmpty() {
return head.next == null;
}//判断多项式是否为空
public void insert(PolymialNode node) {
current.next = node;
current = node;
} //把数据插入多项式链表
public String express(){ //设置一个函数表达多项式
StringBuilder pl = new StringBuilder();
PolymialNode node = head.next;
while (node != null) {
pl.append(node.getCoef() + "x^"+node.getindex());
pl.append(" + ");
node = node.next;
}
return pl.substring(0, pl.length() - 2); //头尾皆无数据,故-2
}
}
可以看到,代码部分通过单链表,将各个单项式连接起来,这样就形成了多项式
二,多项式加法
因为多项式的加法运算与乘法运算不同,于是先解决多项式加法的问题
匹配指数相同的单项式,并使系数相加
要使系数相加直接加就完了,需要思考的是如何匹配指数相同的单项式。
我们知道,单链表是顺序存储的,要找到一个元素,必须找到所在单链表的前一位元素(例如找第n位元素必须先找到第n-1位元素,这是由单链表的结构决定的)。
所以我们要匹配指数相同的项,不能直接按指数相加系数,而需要从头节点开始,统计指数相同的项,并在结果中将系数相同的项相加并保存起来。
那么由于两个多项式项的数量不一定相等,所以我们在创建多项式时除了两个用于计算的多项式外,还需要再新建一个多项式用于统计结果。
以下是加法部分的所有代码,我将它放在多项式链表类PolyLIst中
/*加法*/
public static PolyList addPoly(PolyList p, PolyList q) {
PolymialNode pnext = p.head.next;
PolymialNode qnext = q.head.next;
PolyList result = new PolyList();
while (pnext != null && qnext != null) {
int pindex = pnext.getindex();
int qindex = qnext.getindex();
double pcoef = pnext.getCoef();
double qcoef = qnext.getCoef();
if (pindex == qindex) {
if (pcoef+qcoef != 0) {//指数相同时系数相加并保存到结果多项式result中
PolymialNode node = new PolymialNode(pcoef + qcoef, pindex);
result.insert(node);
}
pnext = pnext.next;
qnext = qnext.next;
}
else if(pindex < qindex){
PolymialNode node = new PolymialNode(pnext.getCoef(), pnext.getindex());
result.insert(node);
pnext = pnext.next;
}
else{
PolymialNode node = new PolymialNode(qnext.getCoef(), qnext.getindex());
result.insert(node);
qnext = qnext.next; }
}
while (pnext != null) {
PolymialNode node = new PolymialNode(pnext.getCoef(), pnext.getindex());
result.insert(node);
pnext = pnext.next;
}
//p多项式已经完成统计
while (qnext != null) {
PolymialNode node = new PolymialNode(qnext.getCoef(), qnext.getindex());
result.insert(node);
qnext = qnext.next;
}
//q多项式已经完成统计
return result;
}
因为多项式表达式是从指数小的项开始排列到指数大的项,在遍历单链表时,用指数为参照物比较节点,会有指数相等和不等两种情况,若是相等,则将系数相加指数不变插入到结果链表,若是不等,则将较小的一项添加至结果链表,较大项暂不作处理,继续下一轮比较,如图。 需要注意的是,因为链表下一节点指数必比前一节点大,故不用担心运算错误。
多项式加法就完成了
三,多项式乘法
话不多述,直接上代码
/*乘法*/
public static PolyList mulPoly(PolyList p, PolyList q) {
PolymialNode pnext = p.head.next;
PolymialNode qnext = q.head.next;
PolyList result = new PolyList();//一共产生p*q个子项(不合并同类项时),由如下两层循环得出
while (qnext != null) {
while (pnext != null) {
double coef = pnext.getCoef() * qnext.getCoef();
int index = pnext.getindex() + qnext.getindex();
result.insert(new PolymialNode(coef, index));
pnext = pnext.next;
}
qnext = qnext.next; //移动到下一节点
pnext = p.head.next;//恢复至链表开头,在进行p次相乘
}
//合并同类项
PolymialNode current = result.head.next;
PolymialNode preCurrent = result.head;
while (current != null) {
PolymialNode nextNode = current.next; //结果链表当前节点的下一节点
while (nextNode != null) {
if (nextNode.getindex() == current.getindex()) {//判断指数是否相同
current.setCoef(current.getCoef() + nextNode.getCoef()); //设置对应系数的新指数
}
nextNode = nextNode.next;//传下一个节点的值,
}
//删除系数为0的项
if (current.getCoef() == 0) {
preCurrent.next = current.next;
}
current = current.next;
}
return result;
}
我们来回忆一下多项式乘法的数学定义,多项式乘法首先就是粗暴的将多项式的所有项进行两两相乘,假设多项式p有m个单项式,多项式q有n个单项式,则有相乘得到的多项式有m*n个单项式,然后再合并同类项,即可得到答案。
得到m*n个单项式
那么链表中如何做m×n次运算呢,截取上方代码的m×n次运算部分如下
while (qnext != null) {
while (pnext != null) {
double coef = pnext.getCoef() * qnext.getCoef();
int index = pnext.getindex() + qnext.getindex();
result.insert(new PolymialNode(coef, index));
pnext = pnext.next;
}
qnext = qnext.next;
pnext = p.head.next;//恢复初始状态,在进行p次相乘
}
很简单,就是利用头结点将p链表不断循环至链表首部,分别与q链表节点进行运算。
合并同类项
同上,截取相关代码
PolymialNode current = result.head.next;
while (current != null) {
PolymialNode nextNode = current.next; //结果链表当前节点的下一节点
while (nextNode != null) {
if (nextNode.getindex() == current.getindex()) {//判断指数是否相同
current.setCoef(current.getCoef() + nextNode.getCoef()); //设置对应系数的新指数
}
nextNode = nextNode.next;//传下个节点的值,
}
return result;
}
可以看到,这部分的操作就和加法其实挺相似的,就是从头开始,复制结果链表的当前节点,与其他所有节点进行比较,指数相同则累加,然后传下一个节点的数据进行比较,若不同,则直接传下一节点值进行比较。
测试
package example;
public class Main {
public static void main(String[] args) {
PolyList p1=new PolyList(); //多项式p1
p1.insert(new PolymialNode(2,0));
p1.insert(new PolymialNode(-1,1));
p1.insert(new PolymialNode(1,2));
System.out.println("p1="+p1.express());
PolyList p2=new PolyList(); //多项式p2
p2.insert(new PolymialNode(-1,0));
p2.insert(new PolymialNode(1,1));
p2.insert(new PolymialNode(-1,2));
p2.insert(new PolymialNode(10,4));
System.out.println("p2="+p2.express());
PolyList resultList1= PolyList.addPoly(p1, p2); //相加
System.out.println("p1+p2="+resultList1.express());
PolyList resultList2= PolyList.mulPoly(p1, p2); //相乘
System.out.println("p1*p2="+resultList2.express());
}
}
运行结果
全部代码
最后附上全部代码
PolymialNode类
package example;
public class PolymialNode {//建立一个多项式,包含系数和指数
private double coef;//系数
private int index;//指数
public PolymialNode next;
//储存该节点下一个借点
public PolymialNode() {
this(0, 0);
}
//初始默认值设置为0
public PolymialNode(double coef, int index) {
this.coef = coef;
this.index = index;
}
public double getCoef() {
return coef;
}
public void setCoef(double coef) {
this.coef = coef;
}
public int getindex() {
return index;
}
public void setindex(int index) {
this.index = index;
}
}
PolyList类
package example;
public class PolyList {
PolymialNode head;//头节点
PolymialNode current; //当前单项式节点
public PolyList(){
head = new PolymialNode();
current = head;
head.next = null;//设置下一节点头文件默认为空
}
public boolean isEmpty() {
return head.next == null;
}//判断多项式是否为空
public void insert(PolymialNode node) {
current.next = node;
current = node;
} //把数据插入多项式链表
public String express(){ //设置一个函数表达多项式
StringBuilder pl = new StringBuilder();
PolymialNode node = head.next;
while (node != null) {
pl.append(node.getCoef() + "x^"+node.getindex());
pl.append(" + ");
node = node.next;
}
return pl.substring(0, pl.length() - 2); //头尾皆无数据,故-2
}
/*加法*/
public static PolyList addPoly(PolyList p, PolyList q) {
PolymialNode pnext = p.head.next;
PolymialNode qnext = q.head.next;
PolyList result = new PolyList();
while (pnext != null && qnext != null) {
int pindex = pnext.getindex();
int qindex = qnext.getindex();
double pcoef = pnext.getCoef();
double qcoef = qnext.getCoef();
if (pindex == qindex) {
if (pcoef+qcoef != 0) {//指数相同时系数相加并保存到结果多项式result中
PolymialNode node = new PolymialNode(pcoef + qcoef, pindex);
result.insert(node);
}
pnext = pnext.next;
qnext = qnext.next;
}
else if(pindex < qindex){
PolymialNode node = new PolymialNode(pnext.getCoef(), pnext.getindex());
result.insert(node);
pnext = pnext.next;
}
else{
PolymialNode node = new PolymialNode(qnext.getCoef(), qnext.getindex());
result.insert(node);
qnext = qnext.next; }
}
while (pnext != null) {
PolymialNode node = new PolymialNode(pnext.getCoef(), pnext.getindex());
result.insert(node);
pnext = pnext.next;
}
//p多项式已经完成统计
while (qnext != null) {
PolymialNode node = new PolymialNode(qnext.getCoef(), qnext.getindex());
result.insert(node);
qnext = qnext.next;
}
//q多项式已经完成统计
return result;
}
/*乘法*/
public static PolyList mulPoly(PolyList p, PolyList q) {
PolymialNode pnext = p.head.next;
PolymialNode qnext = q.head.next;
PolyList result = new PolyList();//一共产生p*q个子项(不合并同类项时),由如下两层循环得出
while (qnext != null) {
while (pnext != null) {
double coef = pnext.getCoef() * qnext.getCoef();
int index = pnext.getindex() + qnext.getindex();
result.insert(new PolymialNode(coef, index));
pnext = pnext.next;
}
qnext = qnext.next; //移动到下一节点
pnext = p.head.next;//恢复至链表开头,在进行p次相乘
}
//合并同类项
PolymialNode current = result.head.next;
PolymialNode preCurrent = result.head;
while (current != null) {
PolymialNode nextNode = current.next; //结果链表当前节点的下一节点
while (nextNode != null) {
if (nextNode.getindex() == current.getindex()) {//判断指数是否相同
current.setCoef(current.getCoef() + nextNode.getCoef()); //设置对应系数的新指数
}
nextNode = nextNode.next;//传下一个节点的值,
}
//删除系数为0的项
if (current.getCoef() == 0) {
preCurrent.next = current.next;
}
current = current.next;
}
return result;
}
}
Main类
package example;
public class Main {
public static void main(String[] args) {
PolyList p1=new PolyList(); //多项式p1
p1.insert(new PolymialNode(2,0));
p1.insert(new PolymialNode(-1,1));
p1.insert(new PolymialNode(1,2));
p1.insert(new PolymialNode(-9,4));
p1.insert(new PolymialNode(2,7));
p1.insert(new PolymialNode(-7,9));
System.out.println("p1="+p1.express());
PolyList p2=new PolyList(); //多项式p2
p2.insert(new PolymialNode(-1,0));
p2.insert(new PolymialNode(1,1));
p2.insert(new PolymialNode(-1,2));
p2.insert(new PolymialNode(10,4));
p2.insert(new PolymialNode(3,8));
p2.insert(new PolymialNode(5,10));
p2.insert(new PolymialNode(9,11));
System.out.println("p2="+p2.express());
PolyList resultList1= PolyList.addPoly(p1, p2); //相加
System.out.println("p1+p2="+resultList1.express());
PolyList resultList2= PolyList.mulPoly(p1, p2); //相乘
System.out.println("p1*p2="+resultList2.express());
}
}