不同于真正的链表,算法笔记上提出了一种静态链表来模拟实际链表,对于解题速度、准确性都有很大帮助。然而受限于原来链表思维,在解决有关链表的题目时虽然使用了静态链表,但解决问题的方式与使用实际链表时并无区别,这样导致解题准确度、速度依然很慢。这篇文章记录自己实现思路与题解思路的区别,以加深自己对静态链表的掌握。
旧思路
-
开一个数组作为静态链表,读入数据,初始化链表
-
从头结点开始遍历链表,记录有效节点数量
-
用一个双层循环,外层循环模拟按照
k
划分的每一组,内存循环用于实现链表逆置链表逆置的主要思想为:用一个指针指向尾结点(原序列的头结点),遍历后面的每个节点,每一个都插入到当前头节点前面,每插入一个节点就更新当前头节点。
此思路的问题在于需要维护大量变量,过程繁琐,容易出错。
新思路
- 开一个数组作为静态链表,读入数据,初始化链表
- 从头结点开始遍历链表,记录有效节点数量,并且为每一个节点的属性
order
(用于表示节点在链表中的位置)赋值。无效节点的该属性为INF
- 以
order
为排序依据,对整个数组排序,有效节点都位于数组左侧 - 按照
k
划分组,组内反转 - 输出节点信息
代码
#include <iostream>
#include <cstdio>
#include <algorithm>
typedef long long LL;
#define INF 1 << 30
LL LLINF = ~(1ll << 63);
using namespace std;
const int maxn = 1000000;
struct Node
{
int address;
int data;
int next;
int ord;
Node(): ord(INF) {}
}nodes[maxn];
bool cmp(Node n1, Node n2)
{
return n1.ord < n2.ord;
}
bool cmp2(Node n1, Node n2)
{
return n1.ord > n2.ord;
}
int main()
{
int head, n ,k;
scanf("%d%d%d", &head, &n, &k);
int pos;
for (int i = 0; i < n; i++)
{
scanf("%d", &pos);
nodes[pos].address = pos;
scanf("%d%d", &nodes[pos].data, &nodes[pos].next);
}
//找到有效节点个数,为ord属性赋值
int cnt = 0;
int p = head;
while (p != -1)
{
nodes[p].ord = cnt++;
p = nodes[p].next;
}
sort(nodes, nodes + maxn, cmp);
//为每一个部分反转
for (int i = 0; i + k <= cnt; i+=k)
{
sort(nodes+i, nodes+i+k, cmp2);
}
//输出
for (int i = 0; i < cnt; i++)
{
printf("%05d %d ", nodes[i].address, nodes[i].data);
if (i != cnt - 1) printf("%05d\n", nodes[i+1].address);
else printf("-1\n");
}
return 0;
}