对于一个有向图,有邻接矩阵和邻接表等存储方式,而其中邻接表的实现方式无疑让人很纠结。
邻接表的优点在于,对于节点为n的有向图,邻接矩阵需要耗费的空间为n2,而邻接表仅需耗费m的空间。使用邻接表存储图,无疑大大降低了存储所必须的空间。
这里主要讲解邻接表的数组实现。
对于邻接表,一般包含两个部分:第一部分用于存储有向边的信息,第二部分拥有存储节点的起始边编号,如下:
在这里我们使用结构体数组来存储有向边的信息,代码如下:
struct LINE{ int p; int next; }; LINE l[MAX * 2];
使用一个一维数组来存储节点的起始边编号,如下:
int h[MAX];
举这样一个例子,对于以下有向图:
起始点 | 1 | 2 | 3 | 4 | 2 |
结束点 | 2 | 4 | 2 | 4 | 5 |
我们可以将其存储为如下形式:
对于一维数组h部分有:
h[1] | h[2] | h[3] | h[4] | h[5] |
1 | 5 | 3 | 4 | 0 |
对于结构体数组l部分有:
l[1] | l[2] | l[3] | l[4] | l[5] | |||||
p | next | p | next | p | next | p | next | p | next |
2 | 0 | 4 | 0 | 2 | 0 | 3 | 0 | 5 | 2 |
值得注意的是,对于每一个新加入链表的边节点,我们都将其插入到链表头部,而不是将其插入到链表尾部。
具体的存储过程实现代码如下:
void add(int n) //有向图中节点个数 { int a, b; for(int i = 1; i <= n; i++) { cin>>a>>b; l[i].p = b; l[i].next = h[a]; h[a] = i; } }
当我们需要对第i号节点进行遍历时,只需如下操作:
void search(int i) //需要遍历的节点编号 { int k = h[i]; while(k != 0) { cout<<l[k].p<<' '; k = l[k].next; } }
圆满完成。