图有多种表示方法,最简单的是邻接矩阵。但是邻接矩阵占用空间很大。对于稀疏图,邻接矩阵会浪费大量空间,遍历邻接矩阵时也会浪费大量时间。而邻接表就解决了这个问题。下面我们就要用链表实现邻接表,也就是需要使用指针了。邻接表是实现拓扑排序、关键路径、Dijkstra算法的优化、Prim算法的优化、Bellman-Ford算法的优化的关键。
如果使用邻接矩阵,下面这个图就需要用右边的6 * 6 = 36个数据的矩阵表示。例如,与0号结点直接相连的结点只有3个,但是却不得不遍历n个结点,并判断权重 < inf (inf表示无穷大) 之后才能确定哪些点与0号结点直接相连。
用邻接表表示是这样的:
我们先直观的看一下邻接表的输出情况:
1、左边的一列结点都存放在一个数组中;
2、数组中的结点可以有多个子节点,例如0号结点可以同时指向1、2、3号结点。虽然在邻接表中1-3号之间有指向关系,但实际上这些结点是平级的。仅仅是用指针将它们链接到0号结点罢了。
3、一共只需要26个数据即可。如果对于稀疏图,占用的空间更少。如果需要遍历,遍历的时间复杂度也要小很多。
邻接表的指针方式实现如下:
#include <stdio.h>
#include <stdlib.h>
int size = 6;
//声明结点的结构体
struct LinkNode{
int index = 0; //结点的编号
int weight = 0;
struct LinkNode * next = NULL; //结点指向下一个结点
};
struct ArrayNode{
struct LinkNode * next = NULL; //结点指向第一个链表结点
};
//用一个数组存放首元素。每个首元素后面用指针连接各个结点
struct ArrayNode arrNode[6];
//头插法添加数据,得到的结果的次序是反的
void addNode(int parentIndex, int nodeIndex, int weight)
{
struct ArrayNode * myArrayNode;
myArrayNode = &arrNode[parentIndex];
//要向操作系统申请空间
struct LinkNode *temp = (struct LinkNode *)(malloc(sizeof