PAT (Basic Level) 1025 反转链表 (25 point(s))

// 正确代码
#include <bits/stdc++.h>
using namespace std;
int Link[100000];
int main() {
	int  Head, N, K, Address, count = 0;
	cin >> Head >> N >> K;
	map<int, int>Data, Next;
	while (N--) {
		cin >> Address;
        // 以Address为key 读取Data和Next
		cin >> Data[Address] >> Next[Address];
	}
	while (Head != -1) {
        // 数组从count = 0开始 按顺序存链表地址 统计链表结点数count
		Link[count++] = Head;
        // 读取下一个结点地址
		Head = Next[Head];
	}
    // 局部反转 当前Data编号i 小于 可完整反转一次的编号时执行
	for (int i = 0; i < count - count % K; i += K)
		reverse(Link + i, Link + i + K);
    
    // 用Address为key(索引)读取Data Next即数组下一个元素储存的地址
	for (int i = 0; i < count - 1; ++i)
		printf("%05d %d %05d\n", Link[i], Data[Link[i]], Link[i + 1]);
    // 最后一个结点 手动 -1
	printf("%05d %d -1", Link[count - 1], Data[Link[count - 1]]);
}
// 错误代码 说明了编号与结点地址的顺序不一定一致
#include <bits/stdc++.h>
using namespace std;

struct Node{
	string address;
	int data;
}node[100000];

int main() {
	string address, next;
	int data, size, k; 
	// 读取首地址 结点数 反转数
	cin >> address >> size >> k;
	
	// 读取结点信息
	for(int i = 0; i < size; i++){
		cin >> address >> data >> next;
		node[i].address = address, node[i].data = data; 
	}
	 
	// 以编号升序排序
	sort(node, node + size, [](Node a, Node b){
		return a.data < b.data;
	});
	
	// 用reverse()函数对结构体数字局部反转 
	// 当前编号+k 不小于 元素个数时停止循环 如当前编号是3 k=4 则 4+4 !< 6 
	for(int i = 0; i + k < size; i += k)
		reverse(node + i, node + i + k);
		
	// 遍历到Size()-1个对象	
	int i = 0;
	for( ; i < size -1; ++i){
		cout << node[i].address << " " << node[i].data << " " << node[i+1].address << endl;
	}
	
	// 最后一个输出下一个地址为 -1 
	cout << node[i].address << " " << node[i].data << " " << -1;
}

这题目的关键,要看到每个结点在反转前后,其自身的地址 Address 和编号 Data 仍然是一致的,改变在指向下一个结点的地址改变了。

而地址跟编号对应,那么一开始就可以用 map,以地址为 key 储存编号为 val。那么后面就可以需要的时候再通过这个容器来读取对应结点的地址。这样我们就解决了编号的问题,再看当前地址和下一个结点地址。

从输出可以看到,虽然编号逆转了,但结点之间的指向仍然是按照顺序方式不断指向下一个,除了最后一个结点指向 -1 不存在,其他可以从排好序的结点中,直接获取下一个结点的地址输出。这样就解决了下一个结点的地址问题。

而关于原始链表的顺序,需要根据结点的下一个地址连起来。所以最开始除了用 map 存储 Data 外还需另一个容器来存储反转前结点与下一地址的关系。来将结点按顺序放入数组里面。

得到正确顺序的数组,就可以用 reverse() 函数将局部 K 个元素反转。最后输出的时候按顺序输出地址和编号,读取下一个结点输出下一位地址,并注意最后一个结点的下一个地址为 -1 即可。

(被输出样例忽悠了,以为编号和原本的结点地址是一一对应,可以直接按编号来排出顺序。比如下面那个错误代码,但只有样例看起来这样,实际输出只能得个及格分。)


data  


迭代器不是想移动到哪就移动到哪,只能够 ++ -- 左右移动,或者重新赋值。

关于set容器的find,如果set的元素是struct结构体对象,那么查找的时候也需要传入一个结构体。

set容器不能局部reverse,参考代码里面局部反转用的是数组。如果全部反转遍历倒是可以用rbegin()和rend()。

按照参考代码的写法,最后输出Next的时候,只需要读取数组的下一位元素输出其地址即可。

参考代码        set::find        ()重载

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值