给定一个链表,比如L1--->L2---->L3---->................----->Ln,把链表调整为L1---->Ln----->L2----->Ln-1------>L3----

本文介绍了一种链表位置调整算法,通过将链表分为前后两部分并翻转后部分,实现节点间的顺序调整。该算法的时间复杂度为O(1),适用于链表操作优化。

给定一个链表,比如L1--->L2---->L3---->................----->Ln,把链表调整为L1---->Ln----->L2----->Ln-1------>L3------>Ln-3...........

要求:

1、间复杂度O(1);

2、节点

class Node

{

int value;

Node next;

}

思路:把链表分为两部分前后两个部分,把后部翻转,然后把后部依次插入前部。

class Node {
	public int value;
	public Node next;

	public Node(int value, Node next) {
		this.value = value;
		this.next = next;
	}
}

public class ListNodePosition{
	public static void printList(Node head)
	{
		   while (head != null) {  
	            System.out.print(head.value+"  ");  
	            head = head.next;  
	        }  
	        System.out.println(); 
	}
	public static void ChangePosition(Node head) {
		if (head == null || head.next == null)
			return;
		Node tmp = head;
		int num = 0;
		while (tmp != null) {
			tmp = tmp.next;
			num++;
		}
		System.out.println(num);
		int n = 0;
		tmp = head;
		Node pre1=null;
		Node next1=null;
		int count;
		if(num%2!=0)count=num/2+1;
		else count=num/2;
			while (n < count) {			
				if(n==(count-1))pre1=tmp;
				tmp = tmp.next;
				n++;
				System.out.println(tmp.value);
			}
		pre1.next=null;
		printList(head);
		printList(tmp);
		Node pre =null;
		Node next=null;
		while(tmp!=null)
		{
			next=tmp.next;
			tmp.next=pre;
			pre=tmp;
			tmp= next;
		}
		tmp=pre;
		next=null;
		printList(pre);
        System.out.println(n);
        pre1=head;
		for(int i=0;i<num/2;i++)
		{
			next1=pre1.next;
			next=tmp.next;
			pre1.next=tmp;
			tmp.next=next1;
			pre1=next1;
			tmp=next;
			
		}
		printList(head);	
	}
	
	public static void main(String[] argv) {
		Node node1 = new Node(0, null);
		Node node2 = new Node(1, null);
		Node node3 = new Node(2, null);
		Node node4 = new Node(3, null);
		Node node5 = new Node(4, null);
		Node node6 = new Node(5, null);
		//Node node7 = new Node(6, null);
		node1.next = node2;
		node2.next = node3;
		node3.next = node4;
		node4.next = node5;
		node5.next = node6;
		//node6.next = node7;
		ChangePosition(node1);
	}
}



/*一元多项式的相加和相乘 描述 一元多项式是有序线性表的典型应用,用一个长度为m且每个元素有两个数据项(系数项和指数项)的线性表((p1,e1),(p2,e2),...,(pm,em))可以唯一地表示一个多项式。 本题实现多项式的相加和相乘运算。本题输入保证是按照指数项递增有序的。 对于%15的数据,有1<=n,m<=15 对于%33的数据,有1<=n,m<=50 对于%66的数据,有1<=n,m<=100 对于100%的数据,有1<=n,m<=2050 本题总分150分,得到100分或以上可视为满分 尚未测试极限数据 从右上角下载p77_data.cpp,编译并运行生成随机测试数据 输入 第1一个整数m,表示第一个一元多项式的长度 第2行有2m个整数,p1 e1 p2 e2 ...,中间以空格分割,表示第1个多项式系数和指数 第3一个整数n,表示第二个一元多项式的项数 第4行有2n个整数,p1 e1 p2 e2 ...,中间以空格分割,表示第2个多项式系数和指数 第5行一个整数,若为0,执行加法运算并输出结果,若为1,执行乘法运算并输出结果;若为2,输出一行加法结果和一行乘法的结果。 输出 运算后的多项式链表,要求按指数从小到大排列 当运算结果为0 0时,不输出。 样例输入 4 7 0 3 1 9 8 5 17 3 8 1 22 7 -9 8 0 样例输出 7 0 11 1 22 7 5 17*/ #include<iostream> #define ADDLINE 100 using namespace std; struct ElemType { int p;//系数 int e;//指数 }; struct OnePloy { ElemType* elem; long int num = 0; long int size = 0; void INIT(long int n) { num = n; size = n; elem = new ElemType[size]; for (int i = 0; i < num; ++i) { cin >> elem[i].p >> elem[i].e; } } void EXPAND() { ElemType* newElem = new ElemType[size + ADDLINE]; for (int i = 0; i < num; i++) { newElem[i] = elem[i]; } delete[] elem; elem = newElem; size += ADDLINE; } }; void ADD(OnePloy L1, OnePloy L2, OnePloy& L3) { L3.size = L1.size + L2.size; L3.elem = new ElemType[L3.size]; int n1 = 0, n2 = 0; while (n1 < L1.num && n2 < L2.num) { if (L1.elem[n1].e == L2.elem[n2].e) { int sum_p = L1.elem[n1].p + L2.elem[n2].p; if (sum_p != 0) { L3.elem[L3.num].e = L1.elem[n1].e; L3.elem[L3.num].p = sum_p; L3.num++; } n1++; n2++; } else if (L1.elem[n1].e < L2.elem[n2].e) { L3.elem[L3.num] = L1.elem[n1]; L3.num++; n1++; } else { L3.elem[L3.num] = L2.elem[n2]; L3.num++; n2++; } } while (n1 < L1.num) { L3.elem[L3.num] = L1.elem[n1]; L3.num++; n1++; } while (n2 < L2.num) { L3.elem[L3.num] = L2.elem[n2]; L3.num++; n2++; } } void MULTIPLY(const OnePloy& L1, const OnePloy& L2, OnePloy& L3) { if (L1.num == 0 || L2.num == 0) { L3.size = 0; L3.num = 0; L3.elem = new ElemType[0]; return; } OnePloy temp; temp.size = L1.num * L2.num; temp.elem = new ElemType[temp.size]; for (int i = 0; i < L1.num; i++) { for (int j = 0; j < L2.num; j++) { temp.elem[temp.num].p = L1.elem[i].p * L2.elem[j].p; temp.elem[temp.num].e = L1.elem[i].e + L2.elem[j].e; temp.num++; } } for (int i = 0; i < temp.num - 1; i++) { for (int j = 0; j < temp.num - i - 1; j++) { if (temp.elem[j].e > temp.elem[j + 1].e) { ElemType swap = temp.elem[j]; temp.elem[j] = temp.elem[j + 1]; temp.elem[j + 1] = swap; } } } L3.size = temp.num; L3.elem = new ElemType[L3.size]; L3.num = 0; if (temp.num > 0) { L3.elem[0] = temp.elem[0]; L3.num = 1; for (int i = 1; i < temp.num; i++) { if (temp.elem[i].e == L3.elem[L3.num - 1].e) { // 合并同类项 L3.elem[L3.num - 1].p += temp.elem[i].p; } else { // 如果系数不为0,添加新项 if (L3.elem[L3.num - 1].p != 0) { L3.elem[L3.num] = temp.elem[i]; L3.num++; } else { // 如果系数为0,替换当前项 L3.elem[L3.num - 1] = temp.elem[i]; } } } if (L3.num > 0 && L3.elem[L3.num - 1].p == 0) { L3.num--; } } delete temp.elem; } int main() { long int m,n,order; OnePloy L1, L2, L3; cin >> m; L1.INIT(m); cin >> n; L2.INIT(n); cin >> order; if (order == 0||order==2) { ADD(L1, L2, L3); if(L3.num != 0){ for (int i = 0; i < L3.num; ++i) cout << L3.elem[i].p << " " << L3.elem[i].e << " "; cout << endl; } } if (order == 1 || order == 2) { MULTIPLY(L1, L2, L3); if (L3.num != 0) { for (int i = 0; i < L3.num; ++i) cout << L3.elem[i].p << " " << L3.elem[i].e << " "; cout << endl; } } }完成第三题的实验报告
最新发布
10-12
# 作业 HW 1 实验报告 姓名: 王文昊 学号: 2450859 日期: 2025 年 10 月 11--- ## 1. 涉及数据结构和相关背景 本题基于**一元多项式**的线性表示法,采用**顺序存储结构**(动态数组)实现多项式的加法与乘法运算。每个项由系数 $p$ 和指数 $e$ 构成,且输入保证按指数递增有序。该模型广泛应用于代数计算、信号处理等领域。 --- ## 2. 实验内容 ### 2.3 一元多项式的相加和相乘 #### 2.3.1 问题描述 给定两个指数递增的一元多项式,支持以下操作: - **加法**:同类项合并,结果仍按指数升序排列; - **乘法**:逐项相乘后合并同类项,最终排序输出; - 根据指令执行单一操作或同时输出加法与乘法结果; - 若结果为零多项式(即无有效项),则不输出任何内容。 --- #### 2.3.2 基本要求 - 输入:两个多项式的项数及其每项的系数和指数; - 操作命令:`0` 加法,`1` 乘法,`2` 同时输出加法和乘法结果; - 输出:运算后的多项式项(系数 指数),以空格分隔,按指数从小到大排列; - 不输出系数为0的项,也不输出全零多项式; - 数据规模最大达 $2050$ 项,需考虑时间与空间效率。 --- #### 2.3.3 数据结构设计 ```cpp struct ElemType { int p; // 系数 int e; // 指数 }; struct OnePloy { ElemType* elem; // 动态数组指针 long int num; // 当前元素个数 long int size; // 分配容量 void INIT(long int n); // 初始化读入 void EXPAND(); // 扩容函数(未在主逻辑中使用) }; ``` > **说明**:使用动态数组存储每一项,`num` 记录实际项数,`size` 为当前分配空间大小;`INIT` 函数用于初始化输入,`EXPAND` 提供扩容能力(备用功能)。 --- #### 2.3.4 功能说明(函数、类) ##### 函数 1:`ADD(OnePloy L1, OnePloy L2, OnePloy& L3)` —— 多项式加法 ```cpp /** * @brief 对两个有序多项式进行加法 * @param L1,L2 输入多项式 * @param L3 结果多项式(引用) * @note 利用归并思想,O(m+n) 时间复杂度 */ void ADD(OnePloy L1, OnePloy L2, OnePloy& L3) ``` - 使用双指针遍历两多项式; - 指数相同则合并系数,非零才保留; - 指数不同则取较小者直接加入结果; - 最终保持升序,无需额外排序。 ##### 函数 2:`MULTIPLY(const OnePloy& L1, const OnePloy& L2, OnePloy& L3)` —— 多项式乘法 ```cpp /** * @brief 实现两个多项式的乘法运算 * @param L1,L2 输入多项式 * @param L3 输出结果 * @note 先生成所有交叉项,再排序+合并同类项 */ void MULTIPLY(const OnePloy& L1, const OnePloy& L2, OnePloy& L3) ``` - 遍历 $L1$ 与 $L2$ 的每一项,生成 $m \times n$ 个乘积项; - 临时存储于 `temp` 中; - 使用冒泡排序将乘积项按指数升序排列; - 遍历排序后序列,合并相邻同指数项; - 跳过系数为0的结果项。 --- #### 2.3.5 调试分析 - **问题 1**:乘法结果未去重导致重复项输出。 **解决**:增加合并同类项逻辑,确保每种指数只出现一次。 - **问题 2**:乘法项未排序导致输出乱序。 **解决**:对所有乘积项执行升序排序(冒泡排序实现)。 - **问题 3**:系数为0的项被错误保留。 **解决**:在加法与乘法中均添加 `if(sum_p != 0)` 判断,避免无效项写入。 - **问题 4**:乘法合并过程中边界访问越界。 **解决**:调整循环条件与索引逻辑,防止对 `L3.num - 1` 的非法访问。 - **测试验证**: - 输入样例: ``` 4 7 0 3 1 9 8 5 17 3 8 1 22 7 -9 8 0 ``` - 加法过程: - $7x^0 + 3x^1 + 9x^8 + 5x^{17}$ - $8x^1 + 22x^7 -9x^8$ - 合并:$7x^0 + (3+8)x^1 + 22x^7 + (9-9)x^8 + 5x^{17} = 7\ 0\ 11\ 1\ 22\ 7\ 5\ 17$ - 输出正确。 --- #### 2.3.6 总结和体会 - **收获**:掌握了多项式作为线性表的应用场景,理解了“先展开、再排序、后合并”的乘法通用策略。 - **难点**:乘法部分涉及大量中间项生成与排序,容易造成性能瓶颈;冒泡排序虽简单但不适合大数据量(改进可用快排)。 - **易错点**: - 忘记跳过系数为0的项; - 合并时未正确更新最后一项状态; - 排序算法实现有误影响整体结果。 - **优化方向**: - 使用优先队列或归并方式避免完全展开; - 改进排序为快速排序或归并排序提升效率; - 引入哈希映射统计同指数项可降低复杂度。 --- ## 3. 实验总结 本次实验完成了基于顺序表的一元多项式加法与乘法系统,实现了从输入解析、运算处理到结果输出的完整流程。加法采用归并策略高效完成,乘法则通过展开+排序+合并的方式稳妥实现。程序能够正确处理各种边界情况(如零项、同指数抵消等),具备较强的鲁棒性。尽管乘法部分时间复杂度较高($O(mn \log mn)$),但在题目限定范围内仍可接受。 --- ### 知识点(列出解答该问题需要的知识点) - **多项式加法的归并策略**:利用指数有序特性,双指针同步移动,实现 $O(m+n)$ 时间内的线性合并。 - **多项式乘法的项展开与合并**:每项相乘生成 $mn$ 个新项,再通过排序和合并同类项得到最终结果。 - **排序与去重结合处理**:先对乘积项按指数升序排序,再遍历合并相同指数项,确保输出有序且无重复。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值