本文是对[数据结构](4)单链表_世真的博客-CSDN博客和[C++数据结构](33)图,图的遍历,最小生成树,最短路径算法详解_世真的博客-CSDN博客_c++实现图及最小路径的补充。
链式前向星
链式前向星就是用数组模拟链表。它的特点是代码简洁,避免了 new 的开销,效率高。适合笔试做题时使用(不需要考虑空间利用率和内存泄漏的问题)。
一个用数组模拟的单链表:
-
head
表示头结点的编号,初始为-1
表示空结点 -
e[i]
表示编号为i
的结点的值 -
nxt[i]
表示编号为i
的结点的下一个结点的编号 -
idx
用于给结点编号
-
add_front
头插 -
add
在编号为 k 的结点后面插入一个结点 -
remove
删除编号为 k 的结点的后一个结点
const int N = 100010;
int head, e[N], nxt[N], idx;
void init() {
head = -1;
idx = -1;
}
void add_front(int x) {
e[++idx] = x;
nxt[idx] = head;
head = idx;
}
void add(int k, int x) {
e[++idx] = x;
nxt[idx] = nxt[k];
nxt[k] = idx;
}
void remove(int k) {
nxt[k] = nxt[nxt[k]];
}
图的领接表存储本质上也是链表,可以使用链式前向星
const int N = 100010, M = 2 * N;
int n, m;
int h[N], e[M], nxt[M], idx;
int q[N];
bool vis[N];
void init() {
memset(h, -1, sizeof(h));
idx = -1;
}
void add(int a, int b) {
e[++idx] = b;
nxt[idx] = h[a];
h[a] = idx;
}
void dfs(int u) {
vis[u] = true;
for (int i = h[u]; i != -1; i = nxt[i]) {
int j = e[i];
if (!vis[j]) dfs(j);
}
}
void bfs(int u) {
q[0] = u;
int hh = 0, tt = 0;
vis[u] = true;
while (hh <= tt) {
int t = q[hh++];
for (int i = h[t]; i != -1; i = nxt[i]) {
int j = e[i];
if (!vis[j]) q[++tt] = j;
}
}
}
对于有向图,插入一条从 a
到 b
的边,则调用 add(a, b)
;对于无向图,插入一条 a
与 b
之间的边,则调用 add(a, b)
add(b, a)
。
另外,由于树也是图的一种,所以我们也可以使用这种存储方式。使用 C++ 的 vector<vector<int>>
也可以模拟邻接表,并且能够简化 add 函数的写法(因为push_back()
函数能够代替我们使用 idx
手动对结点进行编号的过程),但是这些 STL 容器运行速度较慢,做题时谨慎使用。