一、图的概念

1 .图的定义

图 1.3-1所示的 ⑴, ⑵, ⑶均为图 (Graph),它有若干个不同的点 v 1, v 2, …, v n,在其中一些点之间用直线或曲线连接。图中的这些点被称为顶点 (vertex)或结点,连接顶点的曲线或直线称为边 (edge)。通常将这种由若干个顶点以及连接某些顶点的边所组成的图形称为图,顶点通常被称作是图中的数据元素。

图1.3-1

在线性结构中每个元素只有一个前趋和一个后续,而图1.3-1中的各个图则与之不同,它是一种较为复杂的非线性数据结构,在图结构中的任意两个元素之间都可能相互联系,即每个元素都可能有多个前趋或多个后续。图作为一种数据结构,通常又可被定义为: graph=(V, E)或 G=(V,E),即一个图是由顶点的集合 V和边的集合 E组成。

在图 1.3-1中 ⑴图中的边没有方向,这类图称为无向图 (undirected graph)。在记录无向图时, (v 1, v 2 )等价于 (v 2, v 1)。

在图 1.3-1中 ⑵图中的边上有一个箭头,它表示边的方向,这类图称为有向图 (directed graph)。在记录有向图时, <v 1, v 2 >与 <v 2, v 1 >是两条不同的边。

图 1.3-1中 ⑴图的顶点集合为:

V ={ v 1, v 2, v 3, v 4}

边集合为:

E ={( v 1, v 2),( v 1, v 3),( v 2, v 3),( v 2, v 4),( v 3, v 4)}

图 1.3-1中 ⑵图的顶点集合为:

V ={ v 1, v 2, v 3, v 4}

边集合为:

E ={ <v 1, v 2 >, <v 1, v 3 >, <v 1, v 4 >, <v 2, v 1 >, <v 4, v 2 >}

2 .图的常用术语

环 (cycle):图 1.3-1中 ⑶图中的 v 1点本身也有边相连,这种边称为环。

有限图:顶点与边数均为有限的图,如图1.3-1中的三个图均属于有限图。

简单图:没有环且每两个顶点间最多只有一条边相连的图,如图 1.3-1中的 ⑴图。

邻接与关联:当( v 1, v 2) ∈E,或 <v 1, v 2 >∈E,即 v 1, v 2间有边相连时,则称 v1和 v 2是相邻的,它们互为邻接点( adjacent),同时称( v 1, v 2)或 <v 1, v 2 >是与顶点 v 1、 v 2相关联的边。

顶点的度数 (degree):从该顶点引出的边的条数,即与该顶点相关联的边的数目,简称度。图 1.3-1中 ⑴、 ⑵图的各顶点的度见下表:

入度( indegree):有向图中把以顶点 v为终点的边的条数称为是顶点 v的入度。

出度( outdegree):有向图中把以顶点 v为起点的边的条数称为是顶点 v的出度。图 1.3-1中、 ⑵图各顶点的入度和出度见下表(各顶点的入度与出度之和为该顶点的度 ):

终端顶点:有向图中把出度为 0的顶点称为终端顶点,如图 4.3-1中 ⑵图的 v 3。

道路与路长:道路也称路径 (path)。在图 G=( V, E)中,如果存在由不同的边 (v i0, v i1 ), (v i1, v i2 ), …, (v in-1, v in )或是 <v i0, v i1 >, <vi 1, v i 2>, …, < vin-1, v in >)组成的序列,则称顶点 v i0, v in是连通的,顶点序列( v i0, v i1, vi2, …, v in)是从顶点 v i0到顶点 v in的一条道路。路长是道路上边的数目, v i0到 v in的这条道路上的路长为n。

连通图:对于图中任意两个顶点 v i、 v j ∈V, v i、 v j之间有道路相连,则称该图为连通图 (connected graph),如 1.3-1中的 ⑴图。

强连通图(Strongly Connected Graph):是指一个有向图(DirectedGraph)中任意两点v1、v2间存在v1到v2的路径(path)及v2到v1的路径的图。

带权图:给图1.3-1中各图的边上附加一个代表性数据 (比如表示长度、流量或其他 ),则称其为带权图,如图 1.3-2。

网络:带权的连通图,如图 1.3-2所示。

图1.3-2

二、图的存储

图的最常见的存储方式是用邻接矩阵和邻接表。

无向图a 的邻接表b 和邻接矩阵c 表示如下所示:

有向图a 的邻接表b 和邻接矩阵c 表示如下所示:

1.  邻接矩阵存储

⑴ 邻接矩阵

邻接矩阵 (AdjacencyMatrix)是表示顶点间邻接关系的矩阵。在图的邻接矩阵表示法中通常用一个邻接矩阵表示顶点间的相邻关系,另外用一个顺序表来存储顶点信息。

具有 n个顶点的图 G=(V, E)的邻接矩阵可以定义为:

图 1.3-1中 ⑴图和 ⑵图的邻接矩阵表示为:

带权图的邻接矩阵可以定义为:

图 1.3-2邻接矩阵表示为:

⑵ 建立已知图的邻接矩阵

如要建立图 1.3-1中 ⑴、 ⑵的已知图,则可用常量数组直接说明如下:

const  graph1:array[1..4,1..4] ofinteger=((0,1,1,0),(1,0,1,1),(1,1,0,1),(0,1,1,0));

graph2:array[1..4,1..4] ofinteger=((0,1,1,1),(1,0,0,0),(0,0,0,0),(0,1,0,0));

同样图 1.3-2中的图也可用常量数组直接说明如下:

const  graph3:array[1..4,1..4] ofinteger=((0,3,4,0),(3,0,9,2),(4,9,0,6),(0,2,6,0));

⑶ 建立任意带权无向图的邻接矩阵

程序如下:

Program adjmatrix(input,output);

var vi,vj,vn,ei,en,wn:integer;

graph:array[1..20,1..20]of integer;

Begin

read(vn,en);  { 读入顶点数和边数}

forvi:=1 to vn do

for vj:=1 to vn do

graph[vi,vj]:=0;

forei:=1 to en do

begin

read(vi,vj,wn);  { 读入每条边的两个顶点及边上的权值 }

graph[vi,vj]:=wn;

graph[vj,vi]:=wn

end;

forvi:=1 to vn do

begin

for vj:=1 to vn dowrite(graph[vi,vj]:8);  { 输出图 }

writeln

end

End.

2.  邻接表存储

⑴ 邻接表

邻接矩阵采用的是顺序存储的方式,而邻接表 (Adjacency List)采用的是图的一种链式存储方式。邻接表包含了一个顶点顺序表和每个顶点对应的单链表。

顶点顺序表中的顶点与图中的顶点一一对应,每个顶点的单链表中的每个顶点包含了邻接点域(用来指示与该顶点邻接的点在图中的位置),链域(用来指示相邻的另一条边的顶点),数据域(用来存储边的权值等信息)。

三、图的遍历

与树的遍历类似,从图中的某一顶点出发有序访问图中其余的所有顶点,并使每一个顶点恰好被访问一次,这个过程称为是图的遍历(traversinggraph)。在进行图的遍历时,由于图中顶点间是多对多的关系,图中的任一顶点都可能和其余的顶点相邻接。为避免重复访问,在遍历图的过程中,必须对访问过的顶点作上标记。如设置一个辅助的布尔型数组 visited[v1..vn],将该数组的初始值设为假,一旦顶点 vi被访问,便将其值visited[vi]设为真。

常用的图的遍历方法有两种:深度优先遍历和广度优先遍历,它们对有向图和无向图均适用。

1.  深度优先遍历

深度优先遍历 (Depth-firstTraversal)同树的先序遍历比较类似。先假设图中的所有顶点均未被访问,遍历时从图中的某个顶点 v0出发,访问该顶点,然后依次从v0的未被访问的邻接点出发深度优先遍历图,直到图中所有和v0有路径相通的顶点都被访问到。如果这时图中还有顶点未被访问,则另选图中一个未被访问的顶点作起始点,重复上述过程,直到图中所有顶点均被访问到为 止。

根据深度优先遍历的描述我们可以得到图 1.3-4中的 ⑴图遍历的顶点序列为V1→V2→V4→V8→V9→V5→V3→V6→V7, ⑵图遍历的顶点序列为V1→V2→V5→V3→V4→V6。

连通图的深度优先遍历的算法描述如下:(如果不是连通图则需多次使用遍历算法)

proceduredfs(vi:integer);

begin

write(graph[vi].v:4);  {输出顶点数值}

visited[vi]:=true;      { 设置已访问标记 }

last:=graph[vi].link;    { 取边表指针}

while last<>nil do

begin

if not visited[last^.adjv] then dfs(last^.adjv);

last:=last^.next

end

end;

2.  广度优先遍历

广度优先遍历( Breadth-firstTraversal)也要先假设图中的所有顶点均未被访问,遍历时从某个顶点出发,访问该顶点后再依次访问与该顶点邻接的未被访问过的所有顶点。然后再分别从这些顶点出发进行广度优先遍历,直到图中所有未被访问过的顶点的相邻顶点均被访问到。如果这时图中仍有顶点为未被访问,则另选图中一个未被访问的顶点作为起点,再重复上述过程,直到图中所有顶点都被访问到为止。

根据广度优先遍历的描述我们可以得到图 1.3-4中的 ⑴图遍历的顶点序列为V1→V2→V3→V4→V5→V6→V7→V8→V9, ⑵图遍历的顶点序列为V1→V2→V3→V4→V5→V6。

在广度优先搜索过程中,设 Vi是将被访问的未访问过的顶点。它的邻接点记为 Vi1, Vi2, …, Vin。访问了Vi后,将对应的 visit[Vi]值设为真,并将 Vi保存在队列中。当 Vi出队时,搜索其邻接的 Vi1, Vi2, …,Vin顶点,然后将其中未被访问的顶点者作上访问标记后放入队列中。这种方法是将每个已被访问过的顶点入队,保证了每个顶点最多只有一次入队。

四、图的应用

1 .一笔画问题

数学家欧拉曾经解决过著名的七桥问题(七桥图见图 1.3-5 ⑴图)。下面写出七桥问题的描述:城市中有一条河,河中有 A、 D两个岛,河上有七座桥来连接两个岛及河的 B、 C两岸,问: ⑴能否刚好经过每座桥一次,既无重复也无遗漏? ⑵能否经过桥一次后又回到原来出发点上来?

图1.3-5

七桥问题可以画成图 1.3-5中的 ⑵图的形式,这样七桥问题的第一问就转化成了能否一笔画成一个图的问题。

一个图能否一笔画成需要满足以下条件:先根据图的邻接矩阵求出每个顶点的度数。如果没有度数为奇数的顶点,则可以从任一点开始一笔画成一个图。如果有两个度数为奇数的顶点,则可从这两个奇数顶点中的任一点开始一笔画成一个图。如果度数为奇数的顶点超过两个,则这个图不能够一笔画出。

图 1.3-6

对于图 1.3-5的 ⑵图或是 1.3-6所示的无向图,可以用数组 graph存储图的邻接矩阵,用数组 degree存储每个顶点的度数,用变量 Total_d存储总的度数,用变量 Odd_num存储度数为奇数的顶点个数,用变量 start存储一笔画的起始顶点。

一笔画程序如下:

programstroke(input,output);

vargraph:array[1..20,1..20] of 0..1;

degree:array[1..20] of integer;

odd_num,vn,vi,vj,start,total_d:integer;

begin

odd_num:=0;total_d:=0;start:=1;

write('please input the number of vertex:');

readln(vn);

writeln('please input the data:');

for vi:=1 to vn do

begin

degree[vi]:=0;

for vj:=1 to vn do

begin

read(graph[vi,vj]); {读入邻接矩阵}

degree[vi]:=degree[vi]+graph[vi,vj] {求每个顶点的度数}

end;

total_d:=total_d+degree[vi];  {求总的度数}

if odd(degree[vi]) then

begin

odd_num:=odd_num+1; {统计奇数顶点的个数}

start:=vi  {确认从奇数顶点出发}

end

end;

if odd_num>2 then writeln('no solution') {奇数顶点超过两个显示无解}

else

begin

write('the road is: ',start);

vi:=0;

while total_d>2 do

begin

repeat vi:=vi+1 until graph[start,vi]<>0; {找连接的相邻点}

if degree[vi]>1 then  {先画度数大于 1的顶点}

begin

write('->',vi);

graph[start,vi]:=0;

graph[vi,start]:=0;

degree[vi]:=degree[vi]-1;

degree[start]:=degree[start]-1;

total_d:=total_d-2;

start:=vi;

vi:=0

end

end;

repeat vi:=vi+1 until graph[start,vi]<>0;  {确认最后一笔}

writeln('->',vi)

end

end.

输入图 1.3-6所示的无向图,程序运行结果如下:

please input the number of vertex:6

please input the data:

0 1 1 0 0 0

1 0 1 1 0 1

1 1 0 0 1 1

0 1 0 0 1 1

0 0 1 1 0 1

0 1 1 1 1 0

the road is:5->3->1->2->3->6->2->4->5->6->4

源文档 <http://www.ywhs.net/noi/ds/20081204/771.html>

图(有向图、无向图)相关推荐

  1. 【图】什么是图?无向图怎么存储?邻接表和邻接矩阵如何用代码存储图?

    目录 一.概念 图是什么 各种图的定义 二.图的存储结构 邻接矩阵 邻接表 三.代码实现图的存储 1.无向图存储 2.邻接矩阵存储图 核心代码 完整代码 3.邻接表存储有向图(不含权重) 核心代码 完 ...

  2. 数据结构——图-有向图和无向图的邻接表基础

    #include <stdio.h> #include <stdlib.h> #define VertexType char //顶点的数据类型(char) #define V ...

  3. 图——有向图、无向图、有向网、无向网的邻接矩阵表示

    严版数据结构P162 算法7.1 - 7.2 依据此,延伸创建无向图.有向图.有向网 代码如下: #include<stdio.h> #include<iostream> #i ...

  4. 图的几种存储结构与方法(有向图+无向图)

    图的几种存储结构: 1.邻接矩阵 2.链式前向星 3.C++中vector的邻接表 (一)邻接矩阵 邻接矩阵是表示顶点之间相邻关系的矩阵. 基本思想为: S[i][j]S[i][j]S[i][j] 就 ...

  5. 数据结构之图:无向图的介绍与功能实现,Python——22

    无向图(Undigraph)的介绍 引入 生活中的图,有地图,集成电路板的图,可以看类似的看做是数据结构中的图 数据有"一对一","一对多"和"多对多 ...

  6. 数据结构与算法(九)—— 图(无向图)

    在现实生活中,有许多应用场景会包含很多点以及点点之间的连接,而这些应用场景我们都可以用即将要学习的图这种数据结构去解决. 1.图的定义及分类 图是由一组顶点和一组能够将两个顶点相连的边组成的 1 . ...

  7. python无向加权图_图:无向图(Graph)基本方法及Dijkstra算法的实现 [Python]

    一般来讲,实现图的过程中需要有两个自定义的类进行支撑:顶点(Vertex)类,和图(Graph)类.按照这一架构,Vertex类至少需要包含名称(或者某个代号.数据)和邻接顶点两个参数,前者作为顶点的 ...

  8. 邻接表建立图(c语言)

    邻接表建立图 有向图 无向图 邻接表存图进行拓扑排序 不得不说网上的真的是太乱了,看得我脑壳疼 自己写的可以,感觉好的话可以当成模板. 有向图 代码: #include<stdio.h> ...

  9. Java工程师成神之路 | 2022正式版

    基础篇 面向对象 什么是面向对象 面向对象与面向过程 面向对象的三大基本特征 面向对象的五大基本原则 封装.继承.多态 什么是多态 方法重写与重载 Java的继承与实现 Java的继承与组合 构造函数 ...

  10. 学习日志[自我监督与复习用]

    2021/8/24 正式开始学习,写下此日志进行监督和回忆知识点的提醒 今日学习了unity2D的内容有: 1.左上角的五种基本操作 2.新建Tilemap(瓦片地图)-分类- 1.长方形-2.六边形 ...

最新文章

  1. mysql存储过程 delete select insert_mysql常见操作语句,建表,增删改查
  2. 在VS2010中使用wxWidgets 2.9.3
  3. 【Windows编程】系列第三篇:文本字符输出
  4. 语音购票、刷脸进站:上海联手阿里打造全球首个AI地铁之城
  5. 超基础的Android studio的安装教程
  6. RxSwift之深入解析URLSession的数据请求和数据处理
  7. python库怎么学啊最好_最常用的几个python库--学习引导
  8. 微信小程序开发系列五:微信小程序中如何响应用户输入事件
  9. 9个提高代码运行效率的小技巧你知道几个?
  10. 函数计算搭建 Serverless Web 应用(二)- 自定义域名
  11. 【中山市选2009】【BZOJ2463】谁能赢呢?
  12. dataframe 根据条件查找_python – 在pandas DataFrame中查找(仅)满足给定条件的第一行...
  13. 调试经验——Windows10中iTunes不能识别iPad的解决方法
  14. ubuntu手动下载安装软件包
  15. PMP项目管理—项目风险管理(7)
  16. 方差为什么用平方不用绝对值,为什么要对差值求平方而不是取标准偏差的绝对值?...
  17. latex 多张子图,横栏/双栏
  18. css3 图片阴影、翘边效果
  19. 让一维指针指向二维数组空间的方法!
  20. P2P: Tuning Pre-trained Image Models for Point Cloud Analysis with Point-to-Pixel Prompting

热门文章

  1. mysql里all什么意思_mysql中all的用法是什么
  2. java--表格的使用
  3. 读书笔记 《Python灰帽子-黑客与逆向工程师的Python编程之道》
  4. 交换机和路由器有什么区别?
  5. [转载]强大的文件上传插件
  6. java 环境变量的设置
  7. 22届春季校招实习试水之路1(Java后端)
  8. 错误率的计算、离散概率模型下的统计决策举例
  9. 手工删除Windows桌面搜索的方法
  10. Flutter | bloc 之 state 使用优化