数据结构之图的邻接表存储方法

图的邻接表是一种顺序分配(如数组)和链式分配(如链表)相结合的存储方法。其中数组(顺序分配)用来存放图的各个顶点的数据信息,链表(链式分配)用来存放依附于相应顶点的边的信息。

数组中的每个顶点的信息都是由两部分组成的:顶点域和指针域。结构如下:

V Link
其中,V表示顶点域,用来存放顶点数据信息,Link表示指针域,用来表示依附于该顶点的第一条边的链结点地址。

网的链表每个节点包含三个要素:顶点位置,权值,指针域。若图不是网络,则可以去掉权值这个要素。结构如下:

Position Weight Next
其中,Position表示与链表中与头结点相连边的另一端点的顶点位置,Weight表示该条边的权值,Next指出与头结点邻接的下一条边对应的边结点的位置。

数据结构之图的邻接表存储方法

通常情况下,我们将n个顶点的数据信息存放在一个V[n]数组中,该数组中的每一个数据均表示链表的头结点,共有n个链表。举个例子,如下图所示:

数据结构之图的邻接表存储方法

该图中共有5个顶点,因此顶点数组下标为0~4。顶点1,2之间存在权值为3的边,顶点2,3之间存在权值为4的边,顶点3,4之间存在权值为9的边,顶点4,5之间存在权值为6的边,顶点5,1之间存在权值为2的边。邻接表如下:

数据结构之图的邻接表存储方法

下面我们通过代码来构建以下上述图中的邻接表。

首先建立顶点与边结点的结构。

  1. //邻接表的边结点类型
  2. typedef struct edge {
  3. int adjvex; //该边的终止顶点在顶点数组中的位置
  4. int weight; //该边的权值
  5. edge* next; //指向下一个边结点
  6. }ELink;
  7. //邻接表的顶点类型
  8. typedef struct ver {
  9. int vertex; //顶点的数据信息
  10. ELink* link; //指向第一条边对应的边结点
  11. }VLink;

然后创建一个邻接表。

  1. void createAdjacencyList( VLink* G, int n, int e )
  2. {
  3. int VInfo; //邻接表的数据信息
  4. int vi, vj, weight;//边结点与权值
  5. ELink *pFirst, *pLast;
  6. cout << "请按顺序输入邻接表顶点的数据信息:" << endl;
  7. for (int i=0; i<n; i++) { //输入顶点数组
  8. cout << "请输入第" << i+1 << "个顶点的数据信息:" << endl;
  9. cin >> VInfo;
  10. G[i].vertex = VInfo;
  11. G[i].link = NULL;
  12. }
  13. cout << "请输入邻接表边结点的数据信息(输入顺序:连接点1的位置编号,连接点2的位置编号,权值):" << endl;
  14. for(int i=0; i<e; i++) { //输入边的信息
  15. cout << "请输入第" << i+1 << "条边的数据信息:" << endl;
  16. cin >> vi >> vj >> weight;
  17. pFirst = new ELink;
  18. pFirst->adjvex = vj;
  19. pFirst->weight = weight;
  20. pFirst->next = NULL;
  21. pLast = new ELink;
  22. pLast->adjvex = vi;
  23. pLast->weight = weight;
  24. pLast->next = NULL;
  25. insertElement(G, vi, pFirst); //该函数用来将边信息pFirst链接在顶点数组G的第vi个顶点后面
  26. insertElement(G, vj, pLast);
  27. }
  28. }

上述代码中的insertElement函数表示如下:

  1. //该函数用来将边信息p插入到顶点数组G的pos位置之后
  2. void insertElement( VLink* G, int pos, ELink * p )
  3. {
  4. ELink *q;
  5. if (G[pos].link == NULL) {
  6. G[pos].link = p;
  7. }
  8. else {
  9. q = G[pos].link;
  10. while(q->next) {
  11. q = q->next;
  12. }
  13. q->next = p;
  14. }
  15. }

然后,我们将该邻接表打印出来,用来测试上述创建邻接表是否正确。

  1. void printAdjacentcyList( VLink* G, int n )
  2. {
  3. cout << "打印邻接表信息如下:" << endl;
  4. ELink* p;
  5. for(int i=0; i<n; i++) {
  6. cout << G[i].vertex;
  7. p = G[i].link;
  8. while (p) {
  9. cout << "---->" << p->adjvex << "|" << p->weight;
  10. p = p->next;
  11. }
  12. cout << endl;
  13. }
  14. }

主函数如下:

  1. int _tmain(int argc, _TCHAR* argv[])
  2. {
  3. int n, e;
  4. cout << "请输入图的顶点数:" << endl;
  5. cin >> n;
  6. cout << "请输入图的边数:" << endl;
  7. cin >> e;
  8. VLink* G = new VLink[n];
  9. createAdjacencyList(G, n, e);
  10. printAdjacentcyList(G, n);
  11. delete G;
  12. return 0;
  13. }

将上述示例中图的信息输入后,控制台输出信息如下图所示。

数据结构之图的邻接表存储方法