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
(
≤
1
0
5
)
N(≤10^5)
N(≤105) which is the total number of nodes, and a positive
K
(
≤
N
)
K (≤N)
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 33218
Sample Output:
00000 4 33218
33218 3 12309
12309 2 00100
00100 1 99999
99999 5 68237
68237 6 -1
c语言实现:
#include<stdio.h>
#include<string.h>
typedef struct node{
char addr[6];
int value;
char nextAddr[6];
} node;
node list[100003];
void swap(int a,int b);
int find(int a,int n,char value[]);
void printList(int n);
int main(){
char first[6]; //链表首项的地址
int n,k;
int flag = 0; //记录链表首项在数组中的下标
scanf("%s%d%d",first,&n,&k);
for(int i=0;i<n;i++){
scanf("%s%d%s",list[i].addr,&list[i].value,list[i].nextAddr);
if(!strcmp(list[i].addr,first))
flag = i;
}
int num = n; //记录链表中节点个数,以免输入中不在链表中的节点扰乱输出结果
for(int i=0;i<n;i++){
swap(i,flag);
flag = find(i+1,n,list[i].nextAddr);
if(flag == -2){
num = i+1;
break;
}
if(flag == -1)
break;
}
//逆转
for(int i=0;i+k <= num;i+=k){
for(int j=i;j<(i+k/2);j++){
swap(j,2*i+k-1-j);
}
}
//更改nextAddr,使新链表成链
for(int i=0;i<num-1;i++)
strcpy(list[i].nextAddr,list[i+1].addr);
strcpy(list[num-1].nextAddr,"-1");
printList(num);
return 0;
}
//交换list中下标为a和b的两个元素
void swap(int a,int b){
node temp;
temp = list[a];
list[a] = list[b];
list[b] = temp;
}
//在[a,n)中查找地址为value的元素,找到返回该元素下标,找不到返回-1,若是value是"-1",表明到达链表尾返回-2
int find(int a,int n,char value[]){ //find value form list in range(a,n)
for(int i=a;i<n;i++){
if(!strcmp(value,list[i].addr))
return i;
}
if(!strcmp(value,"-1"))
return -2;
return -1;
}
//输出链表
void printList(int n){
for(int i=0;i<n;i++){
printf("%s %d %s\n",list[i].addr,list[i].value,list[i].nextAddr);
}
}
反思: 一开始我先是建立了一个链表来模拟整个过程,后来发现由于在链表排序等方面的不熟悉导致整个过程过于繁琐,最终难以完成。最后采用一个大的数组来实现。先将数据都读到数组中,然后按照地址关系排序,拍好后再进行逆转。
提交后发现还有有多余节点不在链表上这种情况,这说明可能有一些独立节点虽说读了进来但是从地址关系上看并不是本题中需要翻转的链表上的一个节点。于是再次对程序进行修改新建变量num来表示链表节点个数而不是用一开始读到的n。