02-线性结构3 Reversing Linked List

在这里插入图片描述在这里插入图片描述
分析:

  1. 用结构体数组来模拟实现链表,每个元素的下标代表其地址
  2. 新开一个数组,按顺序存储一个完整链表中的所有结点
  3. 再开一个数组,将2中数组的元素按每K个反向存储的方式存储,最后输出

代码如下

#include <iostream>
using namespace std;

struct Node{
	int ad, data, next;
};
struct Node Nd[100003];				//Nd数组的每一个元素模拟Node结点,包括值和下一个结点的地址 ,元素下标是该结点的地址值
struct Node Temp1[100005];			//记录完整链上的结点 
struct Node Temp2[100005];			//记录要输出的结点 

int main() {
	int Ad, N, K;
	scanf("%d %d %d", &Ad, &N, &K);
	for(int i = 0;  i< N; i++) {
		int a, b, c; scanf("%d %d %d", &a, &b, &c);
		Nd[a].ad = a; Nd[a].data = b; Nd[a].next = c;
	}
	struct Node p = Nd[Ad];					//遍历链表,p表示当前链表
	int cnt = 0;							//cnt记录放进Temp中的结点数,到达K时倒着输出 
	while(1) {								//遍历链表
		Temp1[++cnt].ad = p.ad; Temp1[cnt].data = p.data; Temp1[cnt].next = p.next;
		if(-1 == p.next) {					//添加一个地址为-1的尾结点 
			Temp1[++cnt].ad = -1; Temp1[cnt].data = -1; Temp1[cnt].next = -1; break;
		}  	
		else p = Nd[p.next];
	} 
	int x = 1, y = x+K-1, z = 0;			//x,y表示反转链的首尾结点下标,z表示当前存储结点下标 
	while(1) {
		if(x+K-1 <= cnt-1) {					//倒转 
			for(int i = y; i >= x; i--)
				Temp2[++z] = Temp1[i];
			x = y + 1; 
			if(x+K-1 <= cnt-1) y = x+K-1;
		}
		else { 
			Temp2[++z] = Temp1[++y];
		}
		if(y > cnt-1) break;
	}
	Temp2[++z] = Temp1[++y];				//加上地址为-1的最后一个结点
	for(int i = 1; i < cnt; i++) {
		printf("%05d %d ", Temp2[i].ad, Temp2[i].data);
		if(-1 == Temp2[i+1].ad) printf("-1\n");
		else printf("%05d\n", Temp2[i+1].ad);
	}
}

细节处理:

  1. 为了将最后一个数据常规化,在存储链表结点时,新增了一个地址为1的尾结点,便于判断和输出,最后并不输出该结点
  2. 虽然开3个数组有点浪费空间,不过这样处理逻辑上便于理解

反思(很多不该犯的错误):

  1. 第一遍提交有样例反馈运行超时,遂怀疑算法思路有问题,自闭;
    然而其实是我循环条件没写对,导致了无限循环
  2. 曾经想过在按顺序统计链表结点的过程中顺带每K个元素倒着输出;
    然而这样在倒着输出最后一个元素时,它的next值无法确定,因为根本就不知道下一个元素是否又包含在另外一个K中
  3. 最主要的问题还是因为没有仔细考虑直接动手的原因,在做题前还是要多想想可能出现的情况,再动手
  4. debug过程中,if条件明明正确却不执行,这里卡了我很久,最后发现是数组多声明了一次,且最后声明的时候开的空间很小,if判断时已经越界了(太傻)

PS:

  1. 本题如果采用一些库函数就非常好做了
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值