线性结构3 Reversing Linked List ——链表顺序存储实现
题目:
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 33218
Sample Output:
00000 4 33218
33218 3 12309
12309 2 00100
00100 1 99999
99999 5 68237
68237 6 -1
题目大概意思是:给定一个长度为N(N<=100000)的链表L,每K(K<=N)个元素进行一次反转。输入的第一行分别是链表首地址,链表长度N和数值K,后N行为链表元素的地址,存储的数据和下一位地址。
分析:由于给出了链表元素的地址和下一位地址,所以很容易联想到使用链表的顺序结构。题目的难点在于链表的顺序存储结构是使用数组实现的,即链表的前后元素是相邻的,而这里链表的前后元素是不连续的,同时链表的首地址也不是从0开始。因此,要想由顺序结构实现此链表,我们需要重新定义链表结构,增加首地址和下一位地址存储结构。通过记录当前元素的下一位地址就实现的链表的非连续连接。
链表定义:
struct Node
{
int front; //链表首地址
int Data[MaxSize]; //链表数据
int Next[MaxSize]; //下一位地址
};
typedef struct Node *List;
之后就是链表的读入,反转和输出了,其中链表反转由于是当前元素指向上一个元素,然后下一个元素再指向当前元素,因此需要记录当前元素地址,前一位地址和后一位地址,以及链表首地址,具体请看下面完整代码:
#include <stdlib.h>
#include <stdio.h>
#define NULL -1
#define MaxSize 100000
struct Node
{
int front;
int Data[MaxSize];
int Next[MaxSize];
//List Next;
};
typedef struct Node *List;
List LinkRev(List L, int N, int K); //链表反转
void PrintLt(List L ); //链表输出
int main()
{
int Frt, N, K; //第一行输入
int Cur, Dat, Nxt; //后N行输入
List L;
L =(List) malloc(sizeof(struct Node));
scanf("%d %d %d", &Frt, &N, &K);
if(N>100000) { printf("数组超出最大值!"); return 0;}
else L->front = Frt; //队列的头指针
for(int i=0; i< N; i++)
{
scanf("%d %d %d", &Cur, &Dat, &Nxt);
L->Data[Cur] = Dat; L->Next[Cur] = Nxt; //分别将数据和下一位数据地址存入队列
}
L = LinkRev(L ,N , K); //链表反转
PrintLt(L ); //链表输出
system("pause");
return 0;
}
List LinkRev(List L, int N, int K) //链表反转
{
int Fst, Cur, Nxt, head, rear; //要记录初始头位置head,循环需要记录前1,当前,后1位置
int k0,flag = 1;
Nxt = L->front;
while(N/K )
{
k0 = K;
Cur = Nxt; Nxt = L->Next[Cur];
head = Cur;
while(--k0)
{
Fst = Cur; //前一项地址
Cur = Nxt;
Nxt = L->Next[Nxt]; //后一项地址
L->Next[Cur] = Fst;
}
if(flag )
{
flag = 0;
L->front = Cur; //当前位置赋值给表头
L->Next[head] = Nxt; //初始头指向下一项
rear = head; //
}
else
{
L->Next[head] = Nxt; //初始头指向下一项
L->Next[rear] = Cur;
rear = head;
}
N= N-K;
}
return L;
}
void PrintLt(List L)
{
int Cur, Nxt, Dat;
Nxt = L->front;
do
{
Cur = Nxt; Nxt = L->Next[Cur]; Dat = L->Data[Cur];
if(L->Next[Cur] == NULL)
printf("%05d %d %d\n", Cur, Dat, Nxt);
else
printf("%05d %d %05d\n", Cur, Dat, Nxt);
}while(L->Next[Cur] != NULL); //如果下个数据的地址为-1则循环结束
}
代码运行之后有最后一项未通过,但是我没有理解“有多余结点不在链表上”是什么意思,因此不知该如何修改,有知道的请留言告知,感激不尽。同时,我发现如果只让循环运行一次(即只反转前K个元素),最后一项就正确了,但是第1和5就出错了。