Given a constant K and a singly linked list L, you are supposed to reverse the links of every K elements on L. For example, given L being 1→2→3→4→5→6, if K = 3, then you must output 3→2→1→6→5→4; if K = 4, you must output 4→3→2→1→5→6.
Input Specification:
Each input file contains one test case. For each case, the first line contains the address of the first node, a positive N (<= 105) which is the total number of nodes, and a positive K (<=N) which is the length of the sublist to be reversed. The address of a node is a 5-digit nonnegative integer, and NULL is represented by -1.
Then N lines follow, each describes a node in the format:
Address Data Next
where Address is the position of the node, Data is an integer, and Next is the position of the next node.
Output Specification:
For each case, output the resulting ordered linked list. Each node occupies a line, and is printed in the same format as in the input.
Sample Input:00100 6 4 00000 4 99999 00100 1 12309 68237 6 -1 33218 3 00000 99999 5 68237 12309 2 33218Sample Output:
00000 4 33218 33218 3 12309 12309 2 00100 00100 1 99999 99999 5 68237 68237 6 -1
#include<stdio.h>
#include<stdlib.h>
typedef struct Node
{
int curadd; //当前地址
int data;
int nextadd; //下个节点地址
}Node;
int main()
{
int n,k,firstadd,i,num,j; //n为输入节点个数,k为逆序位元
Node *a,temp;
int c; // 保存逆序的组数
while(scanf("%d%d%d",&firstadd,&n,&k)!=EOF)
{
//创建一个节点数组
a=(Node *)malloc(n*sizeof(Node));
//对数组元素进行赋值
for(i=0;i<n;i++)
scanf("%d%d%d",&a[i].curadd,&a[i].data,&a[i].nextadd);
num=0;
//将输入节点按地址顺序化
while(firstadd!=-1)
{
j=num;
//找到第一个节点
while(a[j].curadd!=firstadd)
j++;
firstadd=a[j].nextadd;
//交换num与j所在的节点位置
temp=a[num];
a[num]=a[j];
a[j]=temp;
num++;
}
if(k>num) //逆序位元大于节点数直接输出
{
for(i=0;i<num-1;i++)
printf("%05d %d %05d\n",a[i].curadd,a[i].data,a[i+1].curadd);
printf("%05d %d -1\n",a[i].curadd,a[i].data);
}
else if(k==num) //逆序位元等于节点数全部逆序输出
{
for(i=num-1;i>0;i--)
printf("%05d %d %05d\n",a[i].curadd,a[i].data,a[i-1].curadd);
printf("%05d %d -1\n",a[0].curadd,a[0].data);
}
else //进行前k个逆序的逆序
{
c=num/k;
//调整顺序
//逆序组的循环
for(i=0;i<c;i++)
{
//组内循环交换k*i+j(组内第一个)和k*i+k-j-1(组内最后一个)对应的节点
for(j=0;j<k/2;j++)
{
temp=a[k*i+j];
a[k*i+j]=a[k*i+k-j-1];
a[k*i+k-j-1]=temp;
}
}
for(i=0;i<num-1;i++)
printf("%05d %d %05d\n",a[i].curadd,a[i].data,a[i+1].curadd);
printf("%05d %d -1\n",a[i].curadd,a[i].data);
}
}
return 0;
}
下面给出C++的代码实现,此算法优于上面的算法:
#include <vector>
#include <iostream>
#include <string.h>
#include <algorithm>
using namespace std;
struct Node{
int addr;
int a;
int next;
};
int main(){
// 输入
// 读入第一行
int root;
int n;
int k;
cin >> root >> n >> k;
// 读入其余行
vector<Node> inLst;
<span style="white-space:pre"> </span>int posOf[100005];//下标代表地址测试地址为5位,故100000则够用,数组元素为各个节点在inLst中的位置
int cnt = 0;
memset(posOf, -1, sizeof(posOf)); //方便以后的处理,将数组所有元素置为-1
for (int i = 0; i < n; i++) {
Node node;
cin >> node.addr >> node.a >> node.next;
inLst.push_back(node);
posOf[node.addr] = cnt++;
}
// 遍历
vector<Node> linkLst; //用于保存按顺序排好的链表;
int p = root;
for (int i = 0; i < n; ++i) {
Node node = inLst[posOf[p]];
linkLst.push_back(node);
p = node.next;
if (p == -1) {
break;
}
}
// 逆置
int time = (int)linkLst.size() / k;//time为需要逆置的组数
for (int i = 0; i < time; i++) {
reverse(linkLst.begin() + i * k, linkLst.begin() + (i + 1) * k);//分别代入逆置头和尾的迭代器
}
// 输出
int size = (int)linkLst.size();
for (int i = 0; i < linkLst.size(); i++){
if (i == size - 1) {
printf("%05d %d -1\n",linkLst[i].addr,linkLst[i].a);
}else{
printf("%05d %d %05d\n",linkLst[i].addr,linkLst[i].a,linkLst[i+1].addr);
}
}
return 0;
}