给定一个单链表 L,我们将每 K 个结点看成一个区块(链表最后若不足 K 个结点,也看成一个区块),请编写程序将 L 中所有区块的链接反转。例如:给定 L 为 1→2→3→4→5→6→7→8,K 为 3,则输出应该为 7→8→4→5→6→1→2→3。
输入格式:
每个输入包含 1 个测试用例。每个测试用例第 1 行给出第 1 个结点的地址、结点总个数正整数 N (≤10^5)、以及正整数 K (≤N),即区块的大小。结点的地址是 5 位非负整数,NULL 地址用 −1 表示。
接下来有 N 行,每行格式为:
Address Data Next
其中 Address
是结点地址,Data
是该结点保存的整数数据,Next
是下一结点的地址。
输出格式:
对每个测试用例,顺序输出反转后的链表,其上每个结点占一行,格式与输入相同。
输入样例:
00100 8 3
71120 7 88666
00000 4 99999
00100 1 12309
68237 6 71120
33218 3 00000
99999 5 68237
88666 8 -1
12309 2 33218
输出样例:
71120 7 88666
88666 8 00000
00000 4 99999
99999 5 68237
68237 6 00100
00100 1 12309
12309 2 33218
33218 3 -1
解题思路:
这题也是链表操作,我在1105写的BuildList和PrintList两个函数可以直接复用,还是先把数据放在一个二维数组里面,再从中提取节点组成初始链表。区块就用一个结构Block来表示,里面两个指针,指向区块的头和尾。这时候一个区块就成了一个大指针,需要三个区块pb1,pb2,pb3来做翻转,pb3在前面带路,pb2的尾指向pb1的头,就完成了一次翻转,再把每个区块依次往前挪。写代码的时候要注意空指针,加一些必要的判断。
#include <stdio.h>
#include <stdlib.h>
#define MAXN 100000
typedef struct node *PtrN;
typedef PtrN List;
struct node {
int address, data, next;
PtrN link;
};
typedef struct Bnode *Block;
struct Bnode {
PtrN front, rear;
};
PtrN ReverseBlock(Block pb1, Block pb2) {
pb2->rear->link = pb1->front;
if ( pb1->front )
pb2->rear->next = pb1->front->address;
return pb2->front;
}
void Follow(Block pb1, Block pb2) {
pb1->front = pb2->front;
pb1->rear = pb2->rear;
}
void Forward(Block pb3, int steps) {
if ( !pb3->rear->link ) return;
pb3->front = pb3->rear->link;
PtrN mv = pb3->rear->link;
while ( mv->link && steps ) {
mv = mv->link;
--steps;
}
pb3->rear = mv;
}
List BuildList(int head, int temp[][MAXN]) {
if ( head == -1 ) return NULL;
List l, p, tmp;
l = (List)malloc(sizeof(struct node));
l->address = head;
l->data = temp[0][head];
l->next = temp[1][head];
p = l;
while ( p->next != -1 ) {
tmp = (List)malloc(sizeof(struct node));
tmp->address = p->next;
tmp->data = temp[0][tmp->address];
tmp->next = temp[1][tmp->address];
p->link = tmp;
p = p->link;
}
p->link = NULL;
return l;
}
void PrintList(List l) {
if ( !l ) return;
while ( l->link ) {
printf("%05d %d %05d\n", l->address, l->data, l->next);
l = l->link;
}
printf("%05d %d -1\n", l->address, l->data);
}
int main(int argc, const char *argv[]) {
int head, N, K, addr, data, next;
int temp[2][MAXN];
if ( scanf("%d%d%d", &head, &N, &K)==EOF ) printf("error\n");
while ( N-- ) {
if ( scanf("%d %d %d", &addr, &data, &next)==EOF ) printf("error\n");
temp[0][addr] = data;
temp[1][addr] = next;
}
List l1 = BuildList(head, temp);
PtrN empty = (PtrN)malloc(sizeof(struct node));
Block pb1 = (Block)malloc(sizeof(struct Bnode));
Block pb2 = (Block)malloc(sizeof(struct Bnode));
Block pb3 = (Block)malloc(sizeof(struct Bnode));
empty->link = l1;
pb3->front = NULL;
pb3->rear = empty;
Follow(pb2, pb3);
Follow(pb1, pb2);
Forward(pb3, K-1);
while ( pb3->rear->link ) {
Follow(pb2, pb3);
Forward(pb3, K-1);
l1 = ReverseBlock(pb1, pb2);
Follow(pb1, pb2);
}
l1 = ReverseBlock(pb2, pb3);
free(empty); free(pb3); free(pb2); free(pb1);
PrintList(l1);
return EXIT_SUCCESS;
}