目录
3.1 完整的CreatePolyn方法解析(如果这一块难理解可以先跳转五的insert讲解)
前言
干货预警!本期内容将深入探讨一元多项式乘法运算的Java实现,涉及链表操作、算法设计、边界处理等核心技术点。文章内容较为深入,建议大家慢慢观看、动手实践,确保完全掌握每个技术细节。
本期我们将完整实现:
一元多项式的链表表示方法
多项式相乘的核心算法
有序链表的插入与合并优化
完整的用户交互界面
相信通过本文的详细剖析,你将彻底掌握多项式运算的底层实现原理!
代码分享:
import java.util.*;
public class Main {
public static void main(String[] args) {
polynomial_of_one_variable A = new polynomial_of_one_variable();
A.CreatePolyn();
// A.print();
polynomial_of_one_variable B = new polynomial_of_one_variable();
B.CreatePolyn();
// B.print();
polynomial_of_one_variable C = A.multiply(B);
System.out.print("A:");
A.print();
System.out.println();
System.out.print("B:");
B.print();
System.out.println();
System.out.print("C:");
C.print();
}
}
import java.util.Scanner;
public class polynomial_of_one_variable {
float coefficient;
int exponent;
polynomial_of_one_variable next;
polynomial_of_one_variable head;
// 无参构造函数,用于创建哑节点
polynomial_of_one_variable() {
this.coefficient = 0;
this.exponent = -1; // 特殊标记,表示哑节点
next = null;
head = this; // 哑节点自身就是头节点
}
polynomial_of_one_variable(float coefficient, int exponent) {
this.coefficient = coefficient;
this.exponent = exponent;
next = null;
head = null;
}
public void print() {
polynomial_of_one_variable p;
if (next == null) {//这里设计为哑节点
return;
}
p = this.next;
while (p != null) {
System.out.print(p.coefficient + " ");
if (p.exponent != 0) {
System.out.print("*x^" + p.exponent);
}
if (p.next != null && p.next.coefficient > 0) {
System.out.print("+");//负数自带负号
}
p = p.next;
}
}
public void CreatePolyn() {
polynomial_of_one_variable h = head, s, q, p;
Scanner sc = new Scanner(System.in);
while (true) {
System.out.print("Enter coefficient(系数): (指数系数都为0时结束)");
float coefficient2 = sc.nextFloat();
System.out.println("Enter exponent(指数): (指数系数都为0时结束)");
int exponent2 = sc.nextInt();
if ((int) coefficient2 == 0 && exponent2 == 0) {
break;
}
s = new polynomial_of_one_variable(coefficient2, exponent2);
q = h.next;
p = h;
while (q != null && exponent2 < q.exponent) {
p = q;
q = q.next;
}
if (q == null || exponent2 > q.exponent) {
p.next = s;
s.next = q;
} else {
q.coefficient += coefficient2;
}
}
}
public polynomial_of_one_variable multiply(polynomial_of_one_variable other) {
// 1. 创建结果多项式的哑节点
polynomial_of_one_variable result = new polynomial_of_one_variable();
// 2. 如果任意一个多项式为空,返回空结果
if (this.next == null || other.next == null) {
return result;
}
// 3. 遍历当前多项式的每一项
polynomial_of_one_variable p1 = this.next; // 跳过当前多项式的哑节点
while (p1 != null) {
// 4. 遍历另一个多项式的每一项
polynomial_of_one_variable p2 = other.next; // 跳过另一个多项式的哑节点
while (p2 != null) {
// 5. 计算两个项的乘积
float newCoefficient = p1.coefficient * p2.coefficient;
int newExponent = p1.exponent + p2.exponent;
// 6. 将乘积项插入到结果多项式中
insertOrMergeTerm(result, newCoefficient, newExponent);
p2 = p2.next; // 移动到另一个多项式的下一项
}
p1 = p1.next; // 移动到当前多项式的下一项
}
return result;
}
private void insertOrMergeTerm(polynomial_of_one_variable result, float coefficient, int exponent) {
// 1. 如果系数为0,不需要插入
if (coefficient == 0) {
return;
}
// 2. 查找插入位置,其实这部分开始就和上面creat很像了,其实是一模一样,但是为了方便看,改了变量名
polynomial_of_one_variable current = result; // 从哑节点开始
polynomial_of_one_variable nextNode = result.next;
// 找到第一个指数小于或等于新项指数的位置
while (nextNode != null && exponent < nextNode.exponent) {
current = nextNode;
nextNode = nextNode.next;
}
// 3. 处理三种情况
if (nextNode != null && exponent == nextNode.exponent) {
// 情况1:指数相同,合并系数
nextNode.coefficient += coefficient;
// 如果合并后系数为0,删除该节点
if (nextNode.coefficient == 0) {
current.next = nextNode.next;
}
} else {
// 情况2:插入新节点
polynomial_of_one_variable newNode = new polynomial_of_one_variable(coefficient, exponent);
current.next = newNode;
newNode.next = nextNode;
}
// 情况3:nextNode == null 已经在else中处理(插入到链表末尾)
}
}
一、项目架构深度解析
1.1 主程序类(Main.java) - 程序入口
import java.util.*;
public class Main {
public static void main(String[] args) {
// 创建多项式A:使用哑节点技术初始化
polynomial_of_one_variable A = new polynomial_of_one_variable();
A.CreatePolyn(); // 交互式创建多项式,支持实时排序
// 创建多项式B:同样的初始化流程
polynomial_of_one_variable B = new polynomial_of_one_variable();
B.CreatePolyn();
// 核心计算:执行多项式乘法运算
// 算法复杂度:O(m*n),其中m、n分别为两个多项式的项数
polynomial_of_one_variable C = A.multiply(B);
// 格式化输出结果
System.out.print("A:"); A.print(); System.out.println(); // 打印多项式A
System.out.print("B:"); B.print(); System.out.println(); // 打印多项式B
System.out.print("C:"); C.print(); // 打印结果多项式C
}
}
深度解析:
设计模式:采用清晰的"输入-处理-输出"流水线模式
内存管理:每个多项式独立管理,避免内存泄漏
用户体验:分步输入,清晰的结果展示
二、多项式类的核心实现
2.1 链表节点设计:面向对象思维
import java.util.Scanner;
public class polynomial_of_one_variable {
// 节点数据域:存储系数和指数
float coefficient; // 系数:支持浮点数,增强计算精度
int exponent; // 指数:必须为整数,表示x的幂次
// 链表指针域
polynomial_of_one_variable next; // 后继指针:指向下一个多项式项
polynomial_of_one_variable head; // 头指针:始终指向哑节点,维护链表完整性
// 无参构造函数:创建哑节点(Dummy Node)
// 哑节点作用:简化边界条件处理,统一插入删除操作
polynomial_of_one_variable() {
this.coefficient = 0; // 哑节点系数为0
this.exponent = -1; // 特殊标记(-1),与正常节点区分
next = null; // 初始后继为空
head = this; // 自引用:哑节点就是头节点
}
// 带参构造函数:创建数据节点
polynomial_of_one_variable(float coefficient, int exponent) {
this.coefficient = coefficient; // 初始化系数
this.exponent = exponent; // 初始化指数
next = null; // 新节点后继为空
head = null; // 普通节点不维护头指针
}
关键技术点详解:
2.1.1 哑节点设计模式
// 传统链表 vs 带哑节点链表
// 传统链表插入第一个节点需要特殊处理:
if (head == null) {
head = newNode;
} else {
// 正常插入...
}
// 带哑节点链表:所有插入操作统一处理
dummyNode.next = newNode; // 无需特殊判断
2.1.2 数据封装原则
coefficient使用float类型:支持小数系数,如2.5x²
exponent使用int类型:确保幂次为整数,符合数学定义
指针分离:head指针仅哑节点维护,普通节点专注数据存储
三、多项式创建算法:有序插入的智慧
3.1 完整的CreatePolyn方法解析(如果这一块难理解可以先跳转五的insert讲解)
public void CreatePolyn() {
// 初始化指针:h指向哑节点,p、q用于遍历查找插入位置
polynomial_of_one_variable h = head, s, q, p;
Scanner sc = new Scanner(System.in);
while (true) { // 持续输入直到用户主动终止
// 用户交互:输入系数和指数
System.out.print("Enter coefficient(系数): (指数系数都为0时结束)");
float coefficient2 = sc.nextFloat();
System.out.println("Enter exponent(指数): (指数系数都为0时结束)");
int exponent2 = sc.nextInt();
// 终止条件判断:系数和指数同时为0
if ((int) coefficient2 == 0 && exponent2 == 0) {
break; // 退出输入循环
}
// 创建新节点:封装用户输入的数据
s = new polynomial_of_one_variable(coefficient2, exponent2);
q = h.next; // q指向第一个数据节点(哑节点之后)
p = h; // p指向哑节点,用于记录插入位置的前驱
// **核心算法**:查找有序插入位置
// 目标:保持多项式按指数降序排列(从高次到低次)
while (q != null && exponent2 < q.exponent) {
p = q; // p跟随q移动,始终指向q的前驱
q = q.next; // q向后遍历,直到找到合适位置
}
// 循环结束条件:
// 1. q == null:已到达链表末尾,新项指数最小
// 2. exponent2 >= q.exponent:找到插入位置
// **三种情况处理策略**
if (q == null || exponent2 > q.exponent) {
// 情况1:新项指数唯一,直接插入
p.next = s; // 前驱节点指向新节点
s.next = q; // 新节点指向后继节点
// 示例:链表 [x³, x¹] 插入 x² → [x³, x², x¹]
} else {
// 情况2:指数已存在,合并同类项
q.coefficient += coefficient2; // 系数相加
// 合并后系数为0的特殊处理
if (q.coefficient == 0) {
p.next = q.next; // 跳过当前节点,相当于删除
// 注意:这里可以优化为实际删除节点释放内存
}
}
}
}
算法流程图解:
输入新项(coefficient, exponent)
↓
从哑节点开始遍历
↓
while (当前节点存在 且 新指数 < 当前节点指数)
↓ 移动指针继续查找
找到插入位置:当前节点指数 ≤ 新指数
↓
if (指数相等) → 合并系数
else → 创建新节点插入
四、多项式乘法:算法核心实现
4.1 multiply方法:数学原理与代码实现
public polynomial_of_one_variable multiply(polynomial_of_one_variable other) {
// 1. 结果多项式初始化:创建哑节点
polynomial_of_one_variable result = new polynomial_of_one_variable();
// 2. 边界条件检查:空多项式相乘结果为0
if (this.next == null || other.next == null) {
return result; // 返回空多项式(只有哑节点)
}
// 3. 双重循环遍历:多项式A的每一项 × 多项式B的每一项
polynomial_of_one_variable p1 = this.next; // 跳过当前多项式的哑节点
while (p1 != null) {
polynomial_of_one_variable p2 = other.next; // 跳过另一个多项式的哑节点
while (p2 != null) {
// 4. 数学运算规则:
// (a*x^m) × (b*x^n) = (a*b)*x^(m+n)
float newCoefficient = p1.coefficient * p2.coefficient;
int newExponent = p1.exponent + p2.exponent;
// 5. 将乘积项插入结果多项式(自动排序和合并)
insertOrMergeTerm(result, newCoefficient, newExponent);
p2 = p2.next; // 移动B多项式指针
}
p1 = p1.next; // 移动A多项式指针
}
return result; // 返回最终结果
}
数学原理示例:
A = 3x² + 2x¹
B = 4x³ + x¹
计算过程:
3x² × 4x³ = 12x⁵
3x² × x¹ = 3x³
2x¹ × 4x³ = 8x⁴
2x¹ × x¹ = 2x²
结果:12x⁵ + 8x⁴ + 3x³ + 2x²
五、插入与合并优化:性能关键点
5.1 insertOrMergeTerm方法深度优化
private void insertOrMergeTerm(polynomial_of_one_variable result, float coefficient, int exponent) {
// 优化1:零系数过滤 - 数学性质利用
if (coefficient == 0) {
return; // 零项不参与运算,直接返回提升性能
}
// 初始化遍历指针
polynomial_of_one_variable current = result; // 当前指针,初始指向哑节点
polynomial_of_one_variable nextNode = result.next; // 后继指针,指向第一个数据节点
// 优化2:有序查找 - 利用多项式已排序的特性
// 目标:找到第一个指数 ≤ 新项指数的位置
while (nextNode != null && exponent < nextNode.exponent) {
current = nextNode; // 当前指针跟进
nextNode = nextNode.next; // 后继指针前移
}
// 循环终止时:
// - nextNode == null:新项应插入链表末尾
// - exponent >= nextNode.exponent:找到插入位置
// 情况分析处理
if (nextNode != null && exponent == nextNode.exponent) {
// 情况1:指数匹配,合并同类项
nextNode.coefficient += coefficient; // 系数相加
// 优化3:零系数项清理 - 内存优化
if (nextNode.coefficient == 0) {
current.next = nextNode.next; // 从链表中删除零系数项
// 注意:实际项目中应该释放nextNode内存
}
} else {
// 情况2:需要插入新节点
polynomial_of_one_variable newNode = new polynomial_of_one_variable(coefficient, exponent);
// 链表插入操作
current.next = newNode; // 前驱节点指向新节点
newNode.next = nextNode; // 新节点指向原后继节点
// 示例:在 [x⁴, x²] 中插入 x³
// 结果:x⁴ → x³ → x²
}
}
六、完整测试用例与验证


总结:
通过本次一元多项式乘法运算的Java实现,我们成功将数学理论与数据结构完美结合,采用带哑节点的链表结构优雅地解决了多项式表示问题,利用有序插入和实时合并优化确保了运算效率,核心乘法算法通过双重循环遍历实现了完整的多项式相乘逻辑。虽然输出格式化功能尚有优化空间,但整体系统展现了扎实的编程功底和算法设计能力,为后续扩展更复杂的符号运算功能奠定了坚实基础,体现了技术深度与工程价值的完美统一。
致谢:
感谢各位技术爱好者的耐心阅读!由于多项式输出格式化涉及较多的边界情况处理,本文中的print方法确实存在改进空间,欢迎各位读者提出优化建议。
如果本文对你有帮助,请点赞收藏支持。对于多项式输出格式化的优化方案,欢迎在评论区分享你的见解,我们一起完善这个项目!
下期预告:我们将进入第三篇——栈与队列,敬请期待!
3320

被折叠的 条评论
为什么被折叠?



