PAT乙级1025 比较复杂,不过可以理解的!!

1025 反转链表 (25分)
给定一个常数 K 以及一个单链表 L,请编写程序将 L 中每 K 个结点反转。例如:给定 L 为 1→2→3→4→5→6,K 为 3,则输出应该为 3→2→1→6→5→4;如果 K 为 4,则输出应该为 4→3→2→1→5→6,即最后不到 K 个元素不反转。

输入格式:
每个输入包含 1 个测试用例。每个测试用例第 1 行给出第 1 个结点的地址、结点总个数正整数 N (≤10
​5
​​ )、以及正整数 K (≤N),即要求反转的子链结点的个数。结点的地址是 5 位非负整数,NULL 地址用 −1 表示。

接下来有 N 行,每行格式为:

Address Data Next
其中 Address 是结点地址,Data 是该结点保存的整数数据,Next 是下一结点的地址。

输出格式:
对每个测试用例,顺序输出反转后的链表,其上每个结点占一行,格式与输入相同。

输入样例:

00100 6 4
00000 4 99999
00100 1 12309
68237 6 -1
33218 3 00000
99999 5 68237
12309 2 33218

输出样例:

00000 4 33218
33218 3 12309
12309 2 00100
00100 1 99999
99999 5 68237
68237 6 -1

动手? 来!!

/*憨憨代码来了!!!
 这题搞了一下午,干。自己水平简直在海平面以下
 聊聊我写的思路吧。我开了一个1e5的数组,直接把他当做“内存”。
 然后每个地址放的就是这个节点,包括:数据以及下一个节点的地址
 然后就是翻转,每次翻转我都看成是一个链表的翻转,而不是一部分,
 这样搞的就很复杂了,我先保存第一个结点的地址FirstAddress。
 然后呢,每次翻转都记录翻转链表的尾部,之后让尾部结点的next指向下一次的头结点
 画个图体会一下 例如 1->2->3->4->5->6 k=3,初始尾部是-1,翻转一次后尾部是1,然后让1指向下一次的头就是6
*/
#include<iostream>
#include<cstring>
#include<iomanip>
using namespace std;
const int N = 1e5;
typedef struct Node {
	int data;
	int next;
};
Node Address[N];
int FirstAddress = -1, TailAddress = -1;
bool f = 1;
int Reverse(int pos, int k)
{
	int p = -1, q = -1;
	int FirstPos = pos;
	//链表翻转
	while (k--)
	{
		q = Address[pos].next;
		Address[pos].next = p;
		p = pos;
		pos = q;
	}
	/*因为翻转后第一个结点变成最后一个结点,最后一个结点变成第一个,所以要让第一个结点指向最后一个结点的next
	这样链才不会断*/
	Address[FirstPos].next = pos;
	if(TailAddress!=-1)
	Address[TailAddress].next = p;
	if (f) {//第一次翻转的头是真的头!!
		FirstAddress = p;
		f = 0;
	}
	return TailAddress = FirstPos; //返回翻转链表的最后一个元素
}
void OutPut(int FirstAddress)//输出,没啥好说的。
{
	while (FirstAddress != -1)
	{
		cout << setw(5) << setfill('0') << FirstAddress << " " << Address[FirstAddress].data << " ";
		if (Address[FirstAddress].next == -1)
			cout << "-1" << endl;
		else cout << setw(5) << setfill('0') << Address[FirstAddress].next << endl;
		FirstAddress = Address[FirstAddress].next;
	}
}
int main()
{
	ios::sync_with_stdio(false);
	//freopen("in.txt", "r", stdin);
	int n, k;
	int add, data, next;
	cin >> FirstAddress >> n >> k;
	for (int i = 0;i < n;++i)
	{
		cin >> add >> data >> next;
		if (add == -1) continue;
		Address[add].data = data;
		Address[add].next = next;
	}//存入地址中,方便取出
	int p = -1, pos  = FirstAddress;
	int FIR = pos,sum=0;
	/*这里好坑,开始测试点6一直过不去。后面搜csdn才明白,原来有些结点不在链表上!干。
	所以这里先记录一下实际上一共有多少个结点*/
	while (FIR!=-1)
	{
		sum++;
		FIR = Address[FIR].next;
	}
	//要用实际结点哦,别用n
	while (sum - k >= 0)
	{
		p = Reverse(pos, k);//k位k位一翻转,然后下一次翻转的起点就是尾巴的下一个结点
		pos = Address[p].next;
		sum -= k;
	}
	OutPut(FirstAddress);
	return 0;
}

把我的创作历程写在注释里了,欢迎交流!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值