笔者写下这篇文章的契机是,前两天在上机课用纯链式存储写题,累的够呛。于是痛定思痛,在此梳理一遍链式前向星,也希望能给有同样困扰的同学们提供一点帮助。
在进入正题之前,我们先用邻接矩阵和邻接表引入。
-
邻接矩阵表示图
邻接矩阵的存储原则为:
第i个结点指向第j个结点。则将矩阵中matrix[i][j]=w
,w为边的权值
可以很好的将链式存储结构转化为一个矩阵来存储。缺点是浪费空间。 -
邻接表表示图
邻接表常用vector,但是vector的隐藏常数太大,空间复杂度高。
由此我们在邻接表的基础上引入了链式前向星 -
链式前向星
存储结构
#define MaxSize 100
typedef struct Edge {
int to, w, next;
} Edge;
int tot;
int head[MaxSize];
Edge edge[MaxSize];
to为被指向的当前结点编号。w为权值,next被定义为,与上一元素父节点相同的兄弟结点。(比如图中,1->2 1->4 1->3;则结点2的next=4;结点4的next=3)
head[i]为父结点i指向的第一个子结点。(head[i]只要求互不相同即可。)
遍历函数
for (int i = 1; i <= MaxSize; i++) { //从1开始
for (int j = head[i]; j != -1; j = edge[j].next;) {
printf("结点%d->结点%d的权值为%d", i, edge[j].to; edge[j].w);
}
}
拿i=1的遍历举例
加边函数
特别的是,与普遍链表不同,在链式前向星中,是在头部插入新结点,而非NULL处
void add_edge(int u, int v, int w) { //u为起点,v为终点,w为权值
edge[tot].to = v; //tot为空结点指针
edge[tot].w = w;
edge[tot].next = head[u];
head[u] = tot++;//tot为任一个未被使用的空节点指针。
}
注意:此时tot不一定为其指向结点的to值。