数据结构之图(1)【邻接矩阵、邻接表】

邻接矩阵创建无向网:

图的邻接矩阵(Adjacency Matrix)存储方式是用两个数组来表示图。一个一维的数组存储图中顶点信息,一个二维数组(称为邻接矩阵)存储图中的边或弧的信息。

设图G有n个顶点,则邻接矩阵是一个n*n的方阵,定义为:

我们来看一个实例,图7-4-2的左图就是一个无向图。

我们再来看一个有向图样例,如图7-4-3所示的左图。

图的术语中,我们提到了网的概念,也就是每条边上都带有权的图叫做网。那些这些权值就需要保存下来。

设图G是网图,有n个顶点,则邻接矩阵是一个n*n的方阵,定义为:

如图7-4-4左图就是一个有向网图。

下面示例无向网图的创建代码:

 1 #include "stdafx.h"
 2 #include<iostream>
 3 #define MaxInt 10000                   //表示权值的无穷
 4 #define MVNum 100                      //最大顶点数,应由用户定义
 5 typedef char VerTexType;               //假设顶点数据类型为字符型
 6 typedef int ArcType;                   //假设边的权值类型为整形
 7 using namespace std;
 8 typedef struct
 9 {
10     VerTexType vexs[MVNum];            //顶点表
11     ArcType arcs[MVNum][MVNum];        //邻接矩阵
12     int vexnum, arcnum;                //图的当前点数和边数
13 }AMGraph;
14
15 void CreateUDN(AMGraph &G)             //采用邻接矩阵表示法,创建无向网&G
16 {
17     int i, j, w;
18     cout << "请输入总顶点数、总边数(空格隔开):" << endl;
19     cin >> G.vexnum >> G.arcnum;       //输入总顶点数、总边数
20     cout << "请输入顶点信息(空格隔开):" << endl;
21     for (i = 0; i < G.vexnum; i++)     //依次输入点的信息
22     {
23         cin >> G.vexs[i];
24     }
25     for (i = 0; i < G.vexnum; i++)     //初始化邻接矩阵,编的权值均为极大值MaxInt
26         for (j = 0; j < G.vexnum; j++)
27             G.arcs[i][j] = MaxInt;
28
29     for (int k = 0; k < G.arcnum; k++) //构造邻接矩阵
30     {
31         cout << "请输入第" << k + 1 << "条边的信息(输入顺序:连接点1编号,连接点2编号,边的权值):" << endl;
32         cin >> i >> j >> w;            //输入一条边依附的顶点及权值
33         G.arcs[i - 1][j - 1] = w;
34         G.arcs[j - 1][i - 1] = G.arcs[i - 1][j - 1];
35     }
36 }
37
38 void coutAMGraph(AMGraph &G)           //无向网的输出
39 {
40     int i, j;
41     cout << "该图的邻接矩阵为:" << endl;
42     cout << "\t";
43     for (i = 0; i < G.vexnum; i++)
44         cout << G.vexs[i] << "\t";
45     cout << endl;
46     for (i = 0; i < G.vexnum; i++)
47     {
48         cout << G.vexs[i] << "\t";
49         for (j = 0; j < G.vexnum; j++)
50         {
51             cout << G.arcs[i][j] << "\t";
52         }
53         cout << endl;
54     }
55 }
56 int main()
57 {
58     AMGraph MG;
59     CreateUDN(MG);
60     coutAMGraph(MG);
61     return 0;
62 }

输出结果:

邻接表创建无向网:

邻接表(Adjacency List) 是图的一种链式存储结构,在邻接表中,对图中每个顶点建立一个单链表,第i个单链表中的节点表示依附于顶点Vi的边(对有向图是以顶点Vi为尾的弧)。每个节点由3个域组成,其中邻接点域(adjvex)指示与顶点vi邻接的点在图中的位置,链域(nextarc)指示下一条边或弧的节点;数据域(info)存储和边或弧相关的信息,如权值等。每个链表上附设一个表头节点。在表头节点中,除了设有链域(firstarc)指向链表中的第一个节点之外,还设有存储顶点Vi的名或者其他有关信息的数据域(data)。

如图:

头节点(存储顶点信息)

表(边)节点(存储两个顶点之间边的信息)

这些表头节点(可以链相接)通常以顺序结构的形式存储,以便随机访问任一个顶点的链表。

上面这一段是严蔚敏版数据结构那本书中对用邻接表法构建图的介绍,说的过于理论化,我第一次看的时候也是不知所云,但是仔细阅读,并且阅读了书中的伪代码,便明白了作者的意思。现在做出简要总结:

在构建图时,需要两个结构体,一个存储图中节点的信息,便是上面介绍的头节点,一个是两个节点之间边的信息,便是上面的表(边)节点。 采用一个一维数组存储头结点信息,然后为每个头结点建立一个链表,让头结点作为这个链表的表头节点(具体实现方法便是让头结点内的指针firstarc 指向链表的首地址),链表中存储的正是和这个头结点相关联的表节点(边的信息),这些边都是尾部和头结点相连。表节点中的adjvex存储的是与这条边关联的另一个头结点在数组中的索引(边的箭头所关联的头节点),表节点中的nextarc则是存储的该链表表头相关联的另一条边的信息。

下图是上图的邻接表:

图2

以第一行为例:V1是图中的头结点,V1后面的链表是所有与V1相连的边

此处需要普及一个概念:我们平时口语所说的边,例如上面的图1中V1 指向 V2的那条边,在图论里面成为“弧”,对于弧来说V1叫“弧尾”,V2是该弧的“弧头”。(虽然不知道名字的来源故事,但是至少人家是专业术语,说出去,让人一听,感觉好高大上的样子,装逼必备利器)。

下面是代码:

 1 #include "stdafx.h"
 2 #include<iostream>
 3 #include<string>
 4 using namespace std;
 5 #define MVNum 100                      //最大顶点值
 6 #define ERROR 1
 7 typedef char VerTexType;
 8 typedef struct ArcNode                 //边结点
 9 {
10     int adjvex;                        //改变所指向的顶点的位置
11     struct ArcNode *nextarc;           //指向下一条边的指针
12     string info;                       //和边相关的信息
13 }ArcNode;
14 typedef struct VNode                   //顶点信息
15 {
16     VerTexType data;
17     ArcNode *firstarc;                 //指向第一条依附该顶点的边的指针
18 }VNode, AdjList[MVNum];                //AdList表示邻接表类型
19 typedef struct                         //邻接表
20 {
21     AdjList vertices;
22     int vexnum, arcnum;                //图的当前顶点数和边数
23 }ALGraph;
24
25 int LocateVex(ALGraph &G, char &v1)    //定位函数
26 {
27     int i;
28     for (i = 0; i < G.vexnum; i++)
29     {
30         if (G.vertices[i].data == v1)
31             return i;
32     }
33     if (i >= G.vexnum)
34         return ERROR;
35     else
36         return 0;
37 }
38 void CreateUDG(ALGraph &G)             //创建无向图
39 {
40     ArcNode *p1, *p2;
41     int i, j, k;
42     char v1, v2;
43     cout << "请输入图的顶点数、弧数:" << endl;
44     cin >> G.vexnum >> G.arcnum;       //输入总顶点数,总边数
45     cout << "请输入顶点:" << endl;
46     for (i = 0; i < G.vexnum; i++)
47     {
48         cin >> G.vertices[i].data;     //输入顶点值
49         G.vertices[i].firstarc = NULL; //初始化表头结点的指针域为NULL
50     }
51     for (k = 0; k < G.arcnum; k++)
52     {
53         cout << "请输入弧尾和弧头:";
54         cin >> v1 >> v2;               //输入各边,构造邻接表
55         i = LocateVex(G, v1);
56         j = LocateVex(G, v2);
57         p1 = new ArcNode;              //生成一个新结点*p1
58         p1->adjvex = j;                //邻接点序号为j
59         p1->nextarc = G.vertices[i].firstarc;
60         G.vertices[i].firstarc = p1;
61         p2 = new ArcNode;
62         p2->adjvex = i;
63         p2->nextarc = G.vertices[j].firstarc;
64         G.vertices[j].firstarc = p2;
65     }
66     cout << "图构建成功!" << endl;
67 }
68
69 void coutUDG(ALGraph G)                //输出函数
70 {
71     int i, j;
72     cout << "输出为:" << endl;
73     for (i = 0; i<G.vexnum; i++)
74     {
75         cout << i;
76         ArcNode *p;
77         p = G.vertices[i].firstarc;
78         while (p != NULL)
79         {
80             cout << "-> " << p->adjvex;
81             p = p->nextarc;
82         }
83         cout << endl;
84     }
85 }
86 int main()
87 {
88     ALGraph MG;
89     CreateUDG(MG);
90     coutUDG(MG);
91     return 0;
92 }

输出结果:

今天就先到这里啦,下一篇再写十字链表和邻接多重表哈!

原文地址:https://www.cnblogs.com/Trojan00/p/8948354.html

时间: 2024-10-11 07:28:04

数据结构之图(1)【邻接矩阵、邻接表】的相关文章

数据结构:图的实现--邻接表

使用邻接表实现图结构 当图中的边数较少时,用邻接表来实现图结构,则会浪费很多内存空间.因此,考虑另一种实现图结构的方法:邻接表.在邻接表中主要有两种节点结构体: 顶点节点 边节点 直接看代码 类定义 #include<iostream> #include<iomanip> using namespace std; //最大权值 #define MAXWEIGHT 100 //边节点 typedef struct edgenode_tag { int adjvex; //邻接点 in

图基本算法 图的表示方法 邻接矩阵 邻接表

要表示一个图G=(V,E),有两种标准的表示方法,即邻接表和邻接矩阵.这两种表示法既可用于有向图,也可用于无向图.通常采用邻接表表示法,因为用这种方法表示稀疏图(图中边数远小于点个数)比较紧凑.但当遇到稠密图(|E|接近于|V|^2)或必须很快判别两个给定顶点手否存在连接边时,通常采用邻接矩阵表示法,例如求最短路径算法中,就采用邻接矩阵表示. 图G=<V,E>的邻接表表示是由一个包含|V|个列表的数组Adj所组成,其中每个列表对应于V中的一个顶点.对于每一个u∈V,邻接表Adj[u]包含所有满

数据结构学习笔记05图 (邻接矩阵 邻接表--&gt;BFS DFS)

数据结构之图 图(Graph) 包含 一组顶点:通常用V (Vertex) 表示顶点集合 一组边:通常用E (Edge) 表示边的集合 边是顶点对:(v, w) ∈E ,其中v, w ∈ V 有向边<v, w> 表示从v指向w的边(单行线) 不考虑重边和自回路 无向图:边是无向边(v, w) 有向图:边是有向边<v, w> 连通:如果从V到W存在一条(无向)路径,则称V和W是连通的 连通图(Connected Graph):如果对于图的任一两个顶点v.w∈V,v和w都是连通的,则称

数据结构----邻接矩阵-邻接表

要表示一个图G=(V,E),有两种标准的表示方法,即邻接表和邻接矩阵.这两种表示法既可用于有向图,也可用于无向图.通常采用邻接表表示法,因为用这种方法表示稀疏图(图中边数远小于点个数)比较紧凑.但当遇到稠密图(|E|接近于|V|^2)或必须很快判别两个给定顶点手否存在连接边时,通常采用邻接矩阵表示法,例如求最短路径算法中,就采用邻接矩阵表示. #include<stdio.h> #include<string.h> #include <stdlib.h> #define

&lt;图论入门&gt;邻接矩阵+邻接表

非本人允许请勿转载. 趁热打铁,学会了邻接表把这个总结一下,以及感谢大佬uncle-lu!!!(奶一波)祝早日进队! 首先,图论入门就得是非常基础的东西,先考虑怎么把这个图读进去. 给定一个无向图,如下 怎么把这个图的数据读入进去呢? 把这个图剖析开来看,1连着的是2和3,2连着4和5,3连着6和7,4连着5,5连着8和6,6连着9. 所以这个图可以用一种神奇的东西----邻接矩阵来存.如下,能联通的制为1,不能联通的制为0. 那么可以看出来,这个邻接矩阵光读入的时间复杂度就是O(N2)的了,在

图的存储-邻接表

图的邻接表之前实现的时候,一直有点小问题 现在才明白 原来头结点是有内容的,之前一直当做一个标志位置来使用 说到底,这就是一种顺式和链式相互结合的储存结构 但还是不知其所以然,这个结构相较于邻接矩阵除了空间储存上面有很大优势,还有访问邻接节点方便 不明白他还有什么非他不可的理由 (其实就是因为自己对链式结构操作不是很熟悉找了个借口.) 邻接表(Adjacency List)是图的一种顺序存储与链式存储结合的存储方法.邻接表表示法类似于树的孩子链表表示法.就是对于图G 中的每个顶点vi,将所有邻接

图的建立——邻接表表示(C语言+VC6.0平台)

图是一种重要而且相对复杂的数据结构,在实际编程中非常有用.邻接表是图的主要表示形式之一,是一种链接表表示方法. #include<stdio.h> #include<stdlib.h> #define MAX 10//令图的最大顶点个数为10 typedef struct node//边表结点(弧) { int adjvex;//相连顶点的编号 int weight;//边权 struct node *pnext;//指向下一个边表结点 }edgenode; typedef str

网络流三大算法【邻接矩阵+邻接表】POJ1273

网络流的基本概念跟算法原理我是在以下两篇博客里看懂的,写的非常好. http://www.cnblogs.com/ZJUT-jiangnan/p/3632525.html http://www.cnblogs.com/zsboy/archive/2013/01/27/2878810.html 网络流有四种算法, 包括 Edmond-Karp(简称EK), Ford-Fulkerson(简称FF), dinic算法以及SAP算法. 下面我会写出前三种算法的矩阵跟邻接表的形式, 对于第四种以后有必要

HDU 1285 确定比赛名次 拓扑排序(邻接矩阵 邻接表

确定比赛名次 Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Description 有N个比赛队(1<=N<=500),编号依次为1,2,3,....,N进行比赛,比赛结束后,裁判委员会要将所有参赛队伍从前往后依次排名,但现在裁判委员会不能直接获得每个队的比赛成绩,只知道每场比赛的结果,即P1赢P2,用P1,P2表示,排名时P1在P2之前.现在请你编程序确定排名. Input 输

数据结构(12) -- 图的邻接矩阵的DFS和BFS

//////////////////////////////////////////////////////// //图的邻接矩阵的DFS和BFS //////////////////////////////////////////////////////// #include <iostream> #include <stdlib.h> #include <queue> #define MaxVertexNum 100 //最大顶点数 //#define INFINI