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 个元素不反转。
原题链接
代码
#include <iostream>
#include <algorithm>
using namespace std;
int main() {
int firstadd, n, k;
cin >> firstadd >> n >> k;
int nextaddr[100010], data[100010], addrlist[100010];
for (int i = 0; i < n; i++) {
int addrtemp;
cin >> addrtemp;
cin >> data[addrtemp] >> nextaddr[addrtemp];
}
int sum = 0;//在链表中的节点总数
int next = firstadd;
while (next != -1) {
addrlist[sum++] = next;
next = nextaddr[next];
}//循环完成之后,sum就是总的有效节点数
//下面进项列表反转
for (int i = 0; i < (sum - sum%k); i += k) {
// reverse(begin(addrlist)+i, begin(addrlist)+i+k);
reverse(addrlist+i, addrlist+i+k);
}
// 下面进行输出
for (int i = 0; i < sum - 1; i++) {//先输出前sum-1项
printf("%05d %d %05d\n", addrlist[i], data[addrlist[i]], addrlist[i+1]);
}
//再输出最后一项
printf("%05d %d -1", addrlist[sum-1], data[addrlist[sum-1]]);
return 0;
}
题解
-
对于这种线性表,可以优先考虑设置一个较大的数组以下标作为本节点地址,以数组内的数据作为下个节点的地址,即数组
nextaddr[presentaddr]
,空间换时间,不用遍历所有节点就能串起来所有节点。 -
对于反转操作,可以专门用一个数组来存储正常的顺序,即
addrlist[100010]
,这样,data只跟地址有关,与前后地址都没关系,就方便输出了~ -
注意,下面的写法是错误的:
int temp; cin >> temp >> a[temp];
应该拆开来写:
int temp; cin >> temp; cin >> a[temp];
-
刷算法题,能用cin,cout 就用之,代码简洁好看!如果超时了或者输出格式需要控制再用printf。
c++中的reverse()函数
reverse函数多用于字符串、数组、容器。头文件是#include <algorithm>
reverse函数的功能是Reverses the order of the elements in the range [first,last)。
参考:reverse的官方说明
-
对数组反转可以使用
algorithm
下的reverse(begin(), end())
,参数是指针(简单理解为地址)一类的。 -
需要注意的是,reverse中的参数如果是容器,可以写成
reverse(cont.begin(), cont.end())
或者reverse(begin(cont), end(cont))
。但是reverse中的参数如果是数组,则只能写成reverse(begin(arr), end(arr))
。begin()
用于数组时返回数组指针,用于容器时返回cont.begin()
。本题代码中,这两句话是一样的:reverse(begin(addrlist)+i, begin(addrlist)+i+k); reverse(addrlist+i, addrlist+i+k);
-
参考:C++ STL begin()和end()函数用法(推荐)、https://www.cplusplus.com/reference/iterator/begin/