PAT 1025 乙等 (反转链表) c++

1025. 反转链表 (25)

时间限制
300 ms
内存限制
65536 kB
代码长度限制
8000 B
判题程序
Standard
作者
CHEN, Yue

给定一个常数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(<= 105)、以及正整数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


思路: 本题可以使用一个结构体来定义节点Node, 使用c++ 的模板类vector进行封装,就可以类似使用数组一样来遍历vector<Node> 类型的节点向量,需要对链表的基本性质有一定了解,相信大家应该都没有问题(参考数据结构)。 第一次解题时,遗漏了输入节点可能不在链表的情况,这是思维定视所导致的,这个很致命的,是思维上的漏洞。


算法:

1.  输入所有节点,用Node1[address]来存放

2. 从首地址开始,在Node1中依次寻找节点的后继,直到node.next=-1 , 自动跳过不在链表的节点,依次将节点存放在Node2中

3. 将Node2中的节点进行反转,按要求分组进行反转,将反转后的节点存放在Node3中,反转实现看具体代码


4.遍历输出Node3,下面的实现没有改变Node3中节点后继地址,而是取巧进行输出,算是节省了部分时间吧.但是


并不建议这样中,因为在实际问题中一般会对反转后的链表进行新的操作。


#include <iostream> 
#include <cstdio>
#include <vector>
using namespace std;

struct Node{
	int address;  //地址
	int data;   //节点数据
       int next;    //节点后继地址
};

vector<Node> Node1(100000);   //地址为下标的位置存放相应节点
vector<Node>  Node2;   //用来存放反转前的链表节点 
vector<Node> Node3;    //用来存放反转后的链表节点 

//交换a,b的位置 
void swap(Node &a, Node &b){
	Node temp = a;
	a = b;
	b = temp;
}


/*
测试用例
00100 6 2
00000 4 99999
00100 1 12309
68237 6 -1
33218 3 00000
99999 5 68237
12309 2 33218

中间有不在链表上的节点 
00001 6 2
00001 1 00002
00002 2 00003 
00006 3 00007
00003 4 00004
00004 5 00005
00005 6 -1 
*/
int main(){
	
	//接收输入 
	int firstAdd,n,k;
	scanf("%d%d%d", &firstAdd, &n,&k);
	
	Node temp;
	for(int i=0;i<n;i++){
		scanf("%d%d%d", &temp.address, &temp.data, &temp.next);
		Node1[temp.address] = temp;
	} 
	
	//从第一个节点开始,根据next地址寻找所有在链表中的节点 
	int next = firstAdd;
	bool go_on = true;    //记录是否继续进行 
	for(int i=0; go_on ;i++) {
		Node2.push_back(Node1[next]);    //从第一个节点开始顺序将后继节点存入Node2 向量 
		next = Node1[next].next;
		if(next == -1) go_on = false;
	}
	
	
	int  n1= Node2.size();  //可以组成完整链表的节点个数 
	
	int num = (n1 / k);     //需要反转的节点组数
	vector<Node>::iterator it;  //遍历指针
	for(int i=0;i<num;i++){    
		int lo=i*k, hi=(i+1)*k;    //每次反转[lo,hi)区间内的节点,不考虑节点next地址的变化 
		while(lo<hi){
			swap(Node2[lo++],Node2[--hi]);
		}
		
	} 
	
	//输出结果 ,最后一个节点末尾直接输出“-1”,其他的节点按照(本节点首地址,本节点数据,下一个节点首地址)格式输出 
	for(it = Node2.begin(); it!=Node2.end(); it++){
		if(it!= Node2.end() -1 ){
		vector<Node>::iterator temp=it;
		printf("%05d %d %05d\n", (*it).address,(*it).data, (*(++temp)).address);
		}
		else
		{
		
		printf("%05d %d %d\n", (*it).address,(*it).data, -1);
	
	}
	} 
	return 0;
}


  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值