题目
思路
由于每个结点的地址都由数字给出,自然考虑使用静态链表;地址由于是5位数,则创建一个容量为100001的l[]数组,0~99999储存结点,100000为头指针;则结点的脚标即为结点的自身地址,要得到下一个节点的指针只需要l[adress].next即可
- 录入数据
使用结构node来储存每个结点的信息,node包含data成员和next成员,其自身地址直接用结点所在的数组脚标表示,不再单独储存;
录入时先录入结点自己的地址,在根据结点自己的地址在对应位置录入data和next数据
这里虽然题目给出的地址都是五位数字,但是可以直接用%d录入,录入时数字前面的0会自动忽略掉; - 翻转链表
(1)首先考虑如何处理边界条件,这里考虑使用限制翻转次数的方式。在链表长度为n,每次翻转k个结点的前提下,总共翻转n/k次,即可满足题目要求
(2)根据上述条件设计翻转函数,形参设计为需要被翻转的部分链表的头指针和需要被翻转的结点个数,函数内部使用头插法翻转链表并保证不断链。主函数则只需要从整个链表的头指针开始,反复调用n/k次翻转函数即可。
注意,这里有一个题中没有说的隐含条件,用例给出的所有结点并不是都在链表上的,会有一些无效结点,所有链表长度n不能直接使用给出的结点个数,而是要在链表构建好后自己统计一次; - 打印数据
从头指针开始依次打印即可,这里再次用到%05d这个转换说明,很有用,另外注意最后的尾指针-1要单独打印;
#include<stdio.h>
typedef struct
{
int data;
int next;
}node;
void reverse(node l[], int low, int k)//逆转low之后的k个结点,low相当于被逆转链表的头结点
{
int i, high, p = l[low].next, pro;
for (i = 0, high = low; i < k; i++)
high = l[high].next;
int stop = l[high].next;
l[low].next = l[high].next;
while (p != stop)
{
pro = l[p].next;
l[p].next = l[low].next;
l[low].next = p;
p = pro;
}
}
int main(void)
{
int ad, n, k, i, fir = 100000;//fir为头指针
int p, q;
scanf("%d%d%d", &ad, &n, &k);
node l[100001];
l[fir].next = ad;
for (i = 0; i < n; i++)
{
scanf("%d", &ad);
scanf("%d%d", &l[ad].data, &l[ad].next);
}
for (n = -1, p = fir; p != -1; p = l[p].next, n++);//确定链表有效结点的个数
p = fir;
if (k != 0)
{
for (i = 0; i < n / k; i++)
{
q = l[p].next;//q为下一段需要逆转的链表的头指针
reverse(l, p, k);
p = q;
}
}
for (p = l[fir].next; p != -1; p = l[p].next)
{
printf("%05d ", p);
printf("%d ", l[p].data);
if (l[p].next != -1)
printf("%05d\n", l[p].next);
else
printf("-1");
}
return 0;
}