有向图的邻接表表示法

图的邻接表表示法类似于树的孩子链表表示法。对于图G中的每个顶点vi,该方法把所有邻接于vi的顶点vj链成一个带头结点的单链表,这个单链表就称为顶点vi的邻接表(Adjacency List)。

1. 邻接表的结点结构

(1)表结点结构
    ┌────┬───┐ 
    │adjvex  │next  │
    └────┴───┘
     邻接表中每个表结点均有两个域:
 ① 邻接点域adjvex
  存放与vi相邻接的顶点vj的序号j。
 ② 链域next
  将邻接表的所有表结点链在一起。
  注意:
     若要表示边上的信息(如权值),则在表结点中还应增加一个数据域。

(2)头结点结构
    ┌────┬─────┐ 
    │vertex  │firstedge │
    └────┴─────┘
     顶点vi邻接表的头结点包含两个域:
 ① 顶点域vertex
  存放顶点vi的信息
 ② 指针域firstedge
  vi的邻接表的头指针。
  注意:
     ① 为了便于随机访问任一顶点的邻接表,将所有头结点顺序存储在一个向量中就构成了图的邻接表表示。
     ② 有时希望增加对图的顶点数及边数等属性的描述,可将邻接表和这些属性放在一起来描述图的存储结构。

2.代码实例

  1. #include<iostream>
  2. using namespace std;
  3. #define MAX_VERTEX_NUM 50//定义图的最大顶点数
  4. typedef char VertexData;
  5. typedef struct EdgeNode//表结点
  6. {
  7. int adjvex;//邻接点域
  8. VertexData data;
  9. EdgeNode *next;//边结点所对应的下一个边结点
  10. } EdgeNode;
  11. typedef struct VertexNode//头结点
  12. {
  13. VertexData data;
  14. EdgeNode *firstedge;//头结点所对应的第一个边结点
  15. }VertexNode;
  16. typedef struct AdjList
  17. {
  18. int VexNum,ArcNum;//定义图的顶点数和边数
  19. VertexNode vertex[MAX_VERTEX_NUM];//定义头结点数组。
  20. }AdjList;
  21. void CreateGraph(AdjList *adj,int *n)
  22. {
  23. int e,s,d;
  24. cout<<"输入顶点数和边数"<<endl;
  25. cin>>*n>>e;//输入顶点数和边数。
  26. adj->VexNum=*n;
  27. adj->ArcNum=e;
  28. EdgeNode *q=NULL;
  29. //初始化表头结点
  30. int i;
  31. for(i=1;i<=*n;i++)
  32. {
  33. cout<<"输入第"<<i<<"个结点的顶点名称"<<endl;
  34. cin>>adj->vertex[i].data;//顶点名称,是一个字符
  35. adj->vertex[i].firstedge=NULL;
  36. }
  37. for(i=1;i<=e;i++)
  38. {
  39. cout<<"输入第"<<i<<"条边的起点和终点"<<endl;
  40. cin>>s>>d;//输入边的起始和终止
  41. // cout<<"输入表结点信息"<<endl;
  42. q=(EdgeNode *)malloc(sizeof(EdgeNode));//创建一个表结点
  43. if(q==NULL)
  44. return;
  45. q->adjvex=d;
  46. //  cin>>q->data;
  47. q->next=adj->vertex[s].firstedge;//新加入的节点都是在头结点之后,原来在头结点之后的节点要后移。
  48. adj->vertex[s].firstedge=q;
  49. }
  50. }
  51. void DisplayGraph(AdjList *adj)
  52. {
  53. int n=adj->VexNum;//顶点个数,后面要遍历每一个点点
  54. EdgeNode *q=NULL;
  55. int i;
  56. for( i=1;i<=n;i++)
  57. {
  58. //  cout<<n<<endl;
  59. q=adj->vertex[i].firstedge;
  60. if(q==NULL)//表示头结点后面没有跟其他结点
  61. {
  62. cout<<"没用从"<<adj->vertex[i].data<<"出发的节点"<<endl;
  63. }
  64. else
  65. {
  66. cout<<"从结点"<<adj->vertex[i].data<<"出发的边有"<<endl;
  67. while(q!=NULL)
  68. {
  69. //  cout<<adj->vertex[i].data<<"->"<<q->data<<endl;
  70. cout<<adj->vertex[i].data<<"->"<<adj->vertex[q->adjvex].data<<endl;
  71. q=q->next;
  72. }
  73. }
  74. }
  75. }
  76. void main()
  77. {
  78. int n;
  79. AdjList *adj=(AdjList *)malloc(sizeof(AdjList));
  80. CreateGraph(adj,&n);
  81. DisplayGraph(adj);
  82. //  cout<<"hello world!"<<endl;
  83. }

输出结果为:

  1. 输入顶点数和边数
  2. 6 6
  3. 输入第1个结点的顶点名称
  4. a
  5. 输入第2个结点的顶点名称
  6. b
  7. 输入第3个结点的顶点名称
  8. c
  9. 输入第4个结点的顶点名称
  10. d
  11. 输入第5个结点的顶点名称
  12. e
  13. 输入第6个结点的顶点名称
  14. f
  15. 输入第1条边的起点和终点
  16. 1 3
  17. 输入第2条边的起点和终点
  18. 2 4
  19. 输入第3条边的起点和终点
  20. 2 1
  21. 输入第4条边的起点和终点
  22. 4 3
  23. 输入第5条边的起点和终点
  24. 3 6
  25. 输入第6条边的起点和终点
  26. 3 5
  27. 从结点a出发的边有
  28. a->c
  29. 从结点b出发的边有
  30. b->a
  31. b->d
  32. 从结点c出发的边有
  33. c->e
  34. c->f
  35. 从结点d出发的边有
  36. d->c
  37. 没用从e出发的节点
  38. 没用从f出发的节点

3.代码实例2(ps:补充于2011-6-14)

总体而言,邻接表表示法中主要含有两种结点,分别是头结点和表结点(也叫做边结点),在头结点(s)到表结点(d)之间存在着一条边。如果头结点后面有多个表结点,即s->d1->d2,则表示存在着两条边,分别是e(s,d1)和e(s,d2)。邻接表表示法中,头结点的数量是固定的,就是图中的顶点数量V,表结点的数量由边的数量来决定。如果是有向图,表结点的数量=边的数量;如果是无向图,则表结点的数量=边的数量*2。

在构造图的时候,如果一个头结点后面有多个表结点,那么表结点按次序添加在头结点后面。比如原先有结构s->d1->d2,现在需要添加表结点d3,那么需要打断s->d1的指针,让d3指向d1,s指向d3。即s->d3->d1->d2。

  1. #include<iostream>
  2. #include<stdlib.h>
  3. using namespace std;
  4. #define MAX_VERTEX_NUM 50//定义图的最大顶点数
  5. typedef char VertexData;//顶点名称是字符型。
  6. typedef struct EdgeNode//表结点
  7. {
  8. int adjvex;//邻接点域
  9. VertexData data;
  10. EdgeNode *next;//表结点所对应的下一个表结点
  11. } EdgeNode;
  12. typedef struct VertexNode//头结点
  13. {
  14. VertexData data;
  15. EdgeNode *firstedge;//头结点所对应的第一个表结点
  16. }VertexNode;
  17. typedef struct AdjList//图的数据结构
  18. {
  19. int VexNum,ArcNum;//定义图的顶点数和边数
  20. VertexNode vertex[MAX_VERTEX_NUM];//定义头结点数组。
  21. }AdjList;
  22. void CreateGraph(AdjList *adj)
  23. {
  24. int s,d;
  25. int i;
  26. cout<<"输入顶点数和边数"<<endl;
  27. cin>>adj->VexNum>>adj->ArcNum;//输入图的顶点数和边数。
  28. EdgeNode *q=NULL;//定义表结点
  29. //初始化表头结点
  30. cout<<"输入"<<adj->VexNum<<"个头结点的名称"<<endl;
  31. for(i=1;i<=adj->VexNum;i++)
  32. {
  33. //adj->vertex[i]是头结点数组
  34. cin>>adj->vertex[i].data;//顶点名称,是一个字符
  35. adj->vertex[i].firstedge=NULL;//初始状态下头结点后面不跟表结点,因此firstedge=null
  36. }
  37. //在初始化头结点以后,就需要开始将表结点添加到头结点后面去。
  38. cout<<"输入"<<adj->ArcNum<<"条边的起点和终点"<<endl;
  39. for(i=1;i<=adj->ArcNum;i++)
  40. {
  41. cin>>s>>d;//输入边的起始和终止,起始s就是头结点位置,终止d就是表结点位置
  42. q=(EdgeNode *)malloc(sizeof(EdgeNode));//创建一个表结点,为其分配空间
  43. if(q==NULL)
  44. return;
  45. /*
  46. 如果原来的链表是s->a->b-c>,现在要加入一个表结点q,那么加入以后就变成了s->q->a->b->c
  47. 因此:
  48. 1.q所指向的应该是当前s所指向的元素。
  49. 2.q的邻接点域是d
  50. 3.s的指针指向q
  51. 操作如以下三行代码
  52. */
  53. q->adjvex=d;//表结点的邻接点域是d
  54. q->next=adj->vertex[s].firstedge;//新加入的节点都是在头结点之后,原来在头结点之后的节点要后移。
  55. adj->vertex[s].firstedge=q;
  56. }
  57. }
  58. void DisplayGraph(AdjList *adj)
  59. {
  60. int n=adj->VexNum;//顶点个数,后面要遍历每一个点点
  61. EdgeNode *q=NULL;
  62. int i;
  63. for( i=1;i<=adj->VexNum;i++)
  64. {
  65. //  cout<<n<<endl;
  66. q=adj->vertex[i].firstedge;//q为头结点i所指向的表结点,i->q之间存在边
  67. if(q==NULL)//表示头结点后面没有跟其他结点
  68. {
  69. cout<<"没用从"<<adj->vertex[i].data<<"出发的节点"<<endl;
  70. }
  71. else
  72. {
  73. cout<<"从结点"<<adj->vertex[i].data<<"出发的边有"<<endl;
  74. while(q!=NULL)
  75. {
  76. //  cout<<adj->vertex[i].data<<"->"<<q->data<<endl;
  77. cout<<adj->vertex[i].data<<"->"<<adj->vertex[q->adjvex].data<<endl;
  78. q=q->next;//链表往后跳
  79. }
  80. }
  81. }
  82. }
  83. void main()
  84. {
  85. int n;
  86. AdjList *adj=(AdjList *)malloc(sizeof(AdjList));
  87. CreateGraph(adj);
  88. DisplayGraph(adj);
  89. system("pause");
  90. }
  91. /*
  92. 输入顶点数和边数
  93. 6 6
  94. 输入6个头结点的名称
  95. a b c d e f
  96. 输入6条边的起点和终点
  97. 1 3
  98. 2 4
  99. 2 1
  100. 4 3
  101. 3 6
  102. 3 5
  103. 从结点a出发的边有
  104. a->c
  105. 从结点b出发的边有
  106. b->a
  107. b->d
  108. 从结点c出发的边有
  109. c->e
  110. c->f
  111. 从结点d出发的边有
  112. d->c
  113. 没用从e出发的节点
  114. 没用从f出发的节点
  115. 请按任意键继续. . .
  116. */

有向图的邻接表描述 c++相关推荐

  1. C/C++二级指针概念及应用(有向图的邻接表(拓扑排序)、有向网图的邻接表、树的孩子表示)

    目录 一.概述 例1: 例2: 代码: 二.实例 1.有向图的邻接表(拓扑排序) 2.有向网图的邻接表 3.树的孩子表示 一.概述 二级指针:指向指针的指针.一般需要修改地址的时候会用到二级指针. 注 ...

  2. C语言建立有向图的邻接表及其遍历操作

    1 /*C语言建立有向图的邻接表及其遍历操作*/ 2 #include"stdio.h" 3 #include"stdlib.h" 4 //图的邻接矩阵储存结构 ...

  3. 无向图有向图的邻接表法建立

    目录 无向图的邻接表法建立 有向图的邻接表法 无向图的邻接表法建立 要求建立一个无向图,采用邻接表做为存储结构. 例如: 输入信息为:第一行给出图的顶点数n和边数e.第二行给出n个字符,表示n个顶点的 ...

  4. 有向图的邻接表表示法

    图的邻接表表示法类似于树的孩子链表表示法.对于图G中的每个顶点vi,该方法把所有邻接于vi的顶点vj链成一个带头结点的单链表,这个单链表就称为顶点vi的邻接表(Adjacency List). 1. ...

  5. 有向图的邻接矩阵和邻接表画法

    本例子展示有向图画邻接表和邻接矩阵,反过来也是如此 大三时自学了了数据结构中的图,发现图中有邻接矩阵和邻接表,作为笔记记录下来 如下图所示,给了一个有向图,求邻接矩阵 怎么做呢? 第一步:和无向图类似 ...

  6. 【转载】邻接表表示法

    图的邻接表表示法 图的邻接表表示法类似于树的孩子链表表示法.对于图G中的每个顶点v i ,该方法把所有邻接于v i 的顶点v j 链成一个带头 结点的单链表,这个单链表就称为顶点v i 的邻接表(Ad ...

  7. 《数据结构与算法》实验报告——无向图邻接表的构造

    <数据结构>实验报告 学号:2018329621200 机器号10-414-28 姓名: 申屠志刚 日期:2019/12/9 程序名:main.cpp 实验内容: 无向图邻接表的构造 一. ...

  8. 数据结构之图(三)——邻接表

    邻接表表示法(链式) 顶点: 按编号顺序将顶点数据存储在一维数组中. 关联同一顶点的边: 用线性链表存储. 如果有边\弧的信息,还可以在表结点中增加一项, 无向图的邻接表 例子: 特点: 邻接表不唯一 ...

  9. 【数据结构】图的存储结构(邻接矩阵、邻接表、十字链表、邻接多重表)及实现(C语言)

    目录 1. 邻接矩阵表示法 1.1 图的邻接矩阵 1.2 创建有向网的邻接矩阵 2. 邻接表表示法 2.1 图的邻接表存储结构 2.2 创建有向图的邻接表 3. 十字链表表示法 3.1 图的十字链表存 ...

最新文章

  1. java quartz 时间配置文件_Spring Quartz如何动态配置时间(3)
  2. python中国大学排名爬虫写明详细步骤-【Python爬虫】从html里爬取中国大学排名...
  3. 第一百五十二期:白话Entity Framework Core数据验证
  4. bower 和 npm 的区别
  5. window下的Django环境搭建
  6. zeromq源码分析笔记之架构
  7. 系列文章-- SSIS学习
  8. NPOI SetColumnHidden隐藏列不起作用的原因
  9. linux中mysql忘记密码
  10. python———两个栈实现一个队列
  11. 解决git 提交报fatal: unable to access ' ': The requested URL returned error: 403 错(亲测可行)
  12. 三、jQuery 中的 DOM 操作(超详细)
  13. php 公众号打开小程序,微信公众号图文消息新增两种进入小程序的方式
  14. 6.PCIe协议分析3-PCIe TLP包详解2
  15. 孙其功陪你学之——OJB文件介绍
  16. 【web前端开发】什么是前端?
  17. powerdesigner自定义实体显示的属性
  18. 评测3款高颜值的安卓epub阅读器
  19. 64个球分到18个盒子里
  20. php读取种子信息,php – 发送获取torrent的种子和同伴的scrape请求

热门文章

  1. easyui label显示不全_easyui 元素遍历问题
  2. bucket sort sample sort 并行_双调排序Bitonic Sort,适合并行计算的排序算法
  3. 归并排序 java_马士兵说之归并排序
  4. JAVA入门级教学之(myeclipse的使用)
  5. 安卓抓包软件_Packet Capture安卓抓包神器介绍及使用教程
  6. if test 多条件_秒懂Python编程中的if __name__ == #39;main#39; 作用和原理
  7. python写选择排序_如何快速掌握python选择排序算法?
  8. vue 分享微信传参_vue实现微信分享链接添加动态参数的方法
  9. 如何ping端口_干货 | 如何正确处理常见的8大网络故障
  10. php注册树模式,php设计模式-注册树模式