第7章 图.

Slides:



Advertisements
Similar presentations
电子成绩单项目实现.
Advertisements

计算机硕士专业基础—C语言 赵海英
Chapter 12 圖形結構 12.1 圖形的一些專有名詞 12.2 圖形資料結構表示法 12.3 圖形追蹤 12.4 擴展樹
Chapter 07 Graph 第七章 图 Prof. Qing Wang.
資料結構與C++程式設計進階 資料結構概論 講師:林業峻 CSIE, NTU 6/ 7, 2010.
第九章 系 统 安 全 性 9.1 结构体 9.2 结构体型数组  9.3 结构体型指针 9.4 内存的动态分配 9.5 共用体
第4章 鏈結串列(Linked Lists) 4-1 動態記憶體配置-(6) 4-2 鏈結串列的基礎-(7)
Linked List Operations
第4章 串 串的基本概念和C语言的串函数 串的存储结构 动态数组实现的顺序串 串的模式匹配算法——BF算法 主要知识点.
第3章 算法与数据结构_c语言描述 3.1 计算机的问题求解模型 3.2 C语言基础 3.3 算法与数据结构的基本概念 3.4 线性结构
第7章 结构体、联合体和枚举类型 本章导读 本章主要知识点 《 C语言程序设计》 (Visual C++ 6.0环境)
C语言程序设计 第十二章 位运算.
第5章 函数与模块化设计 学习目的与要求: 掌握函数的定义及调用方法 理解并掌握参数的传递方法 理解函数的嵌套与递归调用
C语言程序设计 课程 第5章 数组 主讲:李祥 博士、副教授 单位:软件学院软件工程系.
高级语言程序设计 主讲人:陈玉华.
選擇排序法 通訊一甲 B 楊穎穆.
Chap5 Graph.
第11章 查找 主要知识点 查找的基本概念 静态查找表 动态查找表 哈希表.
佇列 (Queue).
資料結構 第5章 佇列.
第8章 圖形結構(Graphs) 8-1 圖形的基本觀念 8-2 圖形的表示法 8-3 圖形的走訪 8-4 擴張樹
补充内容 结构体 概述 定义结构体类型和定义结构体变量 结构体变量的引用 结构体变量的初始化 指针与结构体 用typedef定义类型的别名.
第八章 图 图的基本概念 图的存储结构 图的遍历与连通性 最小生成树 最短路径 活动网络.
复习.
If … else 選擇結構 P27.
STRUCTURE 授課:ANT 日期:2010/5/12.
计算概论 第十八讲 C语言高级编程 结构与习题课 北京大学信息学院.
程式撰寫流程.
C语言程序设计 李祥.
线性表小结 元素之间的线性关系 顺序表 顺序表:元素相邻存储 单链表:后继指针链接 一维数组 给定下标随机存取
第2章 线性表 线性表抽象数据类型 顺序表 主要知识点 单链表 循环单链表 循环双向链表 静态链表 设计举例.
第5章 堆疊(Stacks) 5-1 堆疊的基礎 5-2 堆疊的表示法 5-3 堆疊的應用 - 運算式的計算與轉換
第5章 堆疊(Stacks) 5-1 堆疊的基礎 5-2 堆疊的表示法 5-3 堆疊的應用 - 運算式的計算與轉換
第6章 图 6.2图的存储结构 6.3图的遍历 6.4图的连通性 6.5 最短路径 6.6 AOV网与拓扑排序 6. 7 AOE网与关键路径
作弊是否很有诱惑性? 上堂课已经讲了 作业不一定在两个小时里都能完成 答疑没有一个人? 作弊是有记录的 心理系很多同学集体作弊,让人震惊
第3章 堆栈和队列 堆栈 堆栈应用 队列 队列应用 优先级队列 主要知识点.
C语言 程序设计基础与试验 刘新国、2012年秋.
§7.4.2 最小生成树( Minimum Spanning Tree)
多维数组与指针 用指针变量可以指向一维数组中的元素,也可以指向多维数组中的元素。但在概念上和使用上,多维数组的指针比一维数组的指针要复杂一些。 1. 多维数组元素的地址 先回顾多维数组的性质,可以认为二维数组是“数组的数组”,例 : 定义int a[3][4]={{1,3,5,7},{9,11,13,15},{17,19,21,23}};
THE C PROGRAMMING LANGUAGE
第13章 结构体的应用 13.1 了解由用户构造的数据类型 13.2 结构体类型说明及结构体变量 13.3 结构体数组
第5讲 结构化程序设计(Part II) 周水庚 2018年10月11日.
第4章 顺序程序设计.
第0章作业: 教材P12-练习与实践 1.写出用符号’*’输出描绘汉字”大”的流程图。
自我參考結構 (self-reference – 1)
数据结构概论 第7章 图 董黎刚 浙江工商大学信电学院 2019年4月8日.
算法设计复习 内容提要: 算法设计思想回顾(递归和分治、动态规划、贪心算法、回溯法、分支限界法) 经典例子讲解 2019/4/9.
C语言概述 第一章.
C程序设计.
Main() { Dfas Asdfasf fasdfa } #include <stdio.h> void main( ) {
Chap 5 函数 5.1 计算圆柱体积 5.2 使用函数编写程序 5.3 变量与函数.
C程序设计.
第8章 图 8.1 图的基本概念和基本操作 8.2 图的邻接矩阵存储结构 8.3 图的邻接表存储结构 8.4 图的其他存储结构
第7章 程序的结构 四、生存期与存储属性 五、extern关键字与外部连接属性 六、static关键字与内部连接属性.
鄧姚文 資料結構 第八章:圖(Graph) 鄧姚文
第二章 类型、对象、运算符和表达式.
第三章 基本的輸出與輸入函數 (Basic Output & Input Function)
第3章 最简单的C程序设计 3.1 顺序程序设计举例 3.2 数据的表现形式及其运算 3.3 C语句 3.4 数据的输入输出.
第4章 鏈結串列(Linked Lists) 4-1 動態記憶體配置-(6) 4-2 鏈結串列的基礎-(7)
第1章 数据结构基础概论 本章主要介绍以下内容 数据结构研究的主要内容 数据结构中涉及的基本概念 算法的概念、描述方法以及评价标准.
結構、檔案處理(Structure, File)
Chap 7 数 组 7.1 排序问题 7.2 找出矩阵中最大值所在的位置 7.3 进制转换.
C/C++基礎程式設計班 陣列 講師:林業峻 CSIE, NTU 3/14, 2015.
第六章 图.
圖形結構 Graph Structure chapter 9 德明科技大學資訊科技系.
第四部分 图论 主要内容 图的基本概念:图、通路和回路、图的连通性、图的矩阵表示 图的可行遍性:欧拉图、哈密顿图、带权图及其应用
第三章 流程控制 程序的运行流程 选择结构语句 循环结构语句 主讲:李祥 时间:2015年10月.
Q1(a) 小偉打算編寫一個程序。該程序把兩個44的表內的數字相加。表3內的數字是由表1和表2應格子內的數字相加而成。例如:
函式庫補充資料 1.
C语言基础学习 从外行到入门.
Presentation transcript:

第7章 图

第7章 图 7.1 图的基本概念及术语 7.2 图的存储结构 7.3 图的遍历 7.4 图的应用 7.5 应用举例及分析 习题

7.1 图的基本概念及术语 一、基本概念: 图:图G(Graph)由两个集合构成,记作G=(V,E),V是顶点的有穷非空集合;E是用顶点对表示的边(Edge)的有穷集合。 顶点:图中的数据元素通常称为顶点(vertex)。 无向图:若G中表示边的顶点对是无序的,则称为无向图。 通常用(Vi,Vj)表示顶点Vi和Vj间相连的边,(Vi,Vj)与(Vj,Vi)同边。 有向图:若图中表示边的顶点是有序的,则称G为有向图。 弧:有向边通常称为弧(Arc),用<Vi,Vj>表示从顶点Vi到顶点Vj的一条弧,并称Vi为弧尾(始点),Vj是弧头(终点)。在有向图中,<Vi,Vj><Vj,Vi>表示两条不同的弧。

n个顶点的有向图中,边e的取值范围为0~n(n-1)条, n个顶点的无向图中,边e的取值范围为0~n(n-1)/2条

二.图的基本术语: 1、邻接点,相关边 对于无向图G=(V,E),若边(Vi,Vj)∈E,则称Vi和Vj互为邻接点(Adjacetnt),而边(Vi,Vj)则是与顶点Vi和Vj相关联的边。 对于有向图G=(V,E),若弧<Vi,Vj>∈A,则称顶点Vi邻接到顶点Vj,顶点Vj邻接自顶点Vi,而弧<Vi,Vj>和顶点Vi,Vj相关联。 例如在上页的图中:G1中V3邻接到V1,V1邻接自V3。与V3相关联的弧有:<V2,V3>、<V3,V1>、<V3,V4>。G2中,与V2相关联的边有:<V1,V2> <V2,V3>。

2、 完全图 在无向图中,若每对顶点之间都连有一条边,则称该图为无向完全图。n个顶点的图具有n(n-1)条弧的有向图称为有向完全图。 3、 子图 对于图G=(V,E),G′=(V′,E′),若有V′∈V,E′∈E,则称图G′是G的子图。

4、 顶点的度(degree) 顶点的度是图中和Vi相关联的边的数目,记为TD(Vi)。 在有向图中,要区别顶点的入度与出度。 入度(indegree)指以Vi为头的弧的数目,记为ID(Vi); 出度(outdegree)指以Vi为尾的弧的数目,记为OD(Vi); 故顶点的度TD(Vi)=ID(Vi)+OD(Vi) 有n个顶点,e条边的弧的图中,有2e=∑TD(Vi)

5、 路径,回路 无向图G=(V,E)中,路径是从顶点V到顶点V′间的一个顶点序列(V=Vi0,Vi1,Vi2,Vi3,……,Vim=V′),其中,(Vij-1,Vij)∈E(1≤j≤m)。 若是有向图,路径也是有向的。 路径的起点和终点相同(即V=V),则称此路径为回路或环(cycle) 简单路径:序列中顶点不重复出现的路径。 ★ 路径上边或弧的数目称为路径长度

6、 连通,强连通 若从顶点Vi到Vj(i≠j)有路径,则称Vi和Vj是连通的。 在有向图中,若任意两个顶点Vi和Vj都连通,即从Vi到Vj和Vj到Vi都有路径,则称该有向图为强连通图。有向图中的极大连通子图称为该有向图的强连通分量。

7、 权、网 在一个图的每条边或弧上,标上具有某种含义的数值,这种与图的边相关的数值称为权(weight),这种边或弧上带权的图称为网(network)。

7.2    图的存储结构 7.2.1 邻接矩阵表示法: 1、定义:设G=(V,E)是N个顶点的图(顶点序号依次为0,1,2,3,……n-1)。G的邻接矩阵是表示图中顶点之间相邻关系的n阶方阵。适用于有向图和无向图。

2、n阶方阵A具有如下性质: 1 若(Vi,Vj)或(Vi,Vj)∈E A[i][j]= 0 其他情况 例如,前述G1、G2的邻接矩阵如下: 0 其他情况 例如,前述G1、G2的邻接矩阵如下: 列出图示的邻接矩阵 0 1 0 1 G1.arc= 1 0 1 0 1 0 0 1 0 0 0 0 0 1 1 1 G2.arc= 1 0 1 0 1 1 0 1 0 0 1 0

3、邻接矩阵表示法的性质: 对于无向图: 对于有向图: 1.邻接矩阵一定是对称的 2.第i行(或第i列)非0元素个数正好是第i个顶点的度TD(Vi) 对于有向图: 1.邻接矩阵不一定对称 2.第i行非0元素的个数是顶点i的出度OD(Vi),第i列非0元素的个数是顶点i的入度ID(Vi) 3. 结构说明如下

#define VEXTYPE int #define ADJTYPE int #define MAXLEN 40 type struct {LOXTYPE vex[MAXLEN] ; //顶点信息 ADJTYPE arc[MAXLEN][MAXLEN] //邻接矩阵相邻关系 int vexnum , arcnum ; //顶点数,边数 int kind ; } MGRAPH [matrix]

7.2.2 邻接链表表示法 邻接链表是图的一种链式存储结构。适用于无向图,也适于有向图。在邻接链表中,对图中的每个顶点建立一个单链表。单链表中的结点称为表结点。单链表有一个表头结点。 表头结点的结构为: Vertex Link ★其中,Vertex域存放图中顶点Vi的信息,Link域为指针,指向对应的单链表中的结点。邻接链表将所有表头结点组成一个二维数组。

表结点的结构为: Adjvex Next ★其中,Adjvex域存放与顶点Vi相邻接的顶点在二维数组中的序号, Next域为指针,指向与顶点Vi相邻接的下一个顶点的表结点。

无向图G2的邻接链表示意图如下: VER Link adj next V1 1 2 3 ^ V2 V3 V4

有向图G1的邻接链表示意图如下: VER Link adj next V1 1 3 ^ V2 2 V3 V4

图的邻接链表的结构说明: #define VEXTYPE int #define MAXLEN 40 typedef struct node3 { int adjvex; struct node3 *next; }EDGENODE; typedef struct { VEXTYPE vertex; EDGENODE *link; }VEXNODE; {VEXNODE adjlist[MAXLEN]; int vexnum,arcnum; int kind; }ADJGRAPH;

7.3 图 的 遍 历 图的遍历:从图中某顶点出发对图中每个顶点访问一次,而且只访问一次,这一过程称为图的遍历。 7.3 图 的 遍 历 图的遍历:从图中某顶点出发对图中每个顶点访问一次,而且只访问一次,这一过程称为图的遍历。 图的遍历方法有:深度优先搜索遍历和广度优先搜索遍历。

7.3.1 深度优先搜索遍历 算法描述:从图中某个顶点V出发,首先访问此顶点,然后任选 一个V的未被访问的邻接点W出发,继续进行深度优先搜索,直至图中所有和V有路径相通的顶点都被访问到;若此时图中尚有顶点未被访问,则另选一个图中未曾访问的顶点作始点,重复上面的过程,直至图中所有的顶点都被访问。

无向连通图的深度优先搜索过程 V 1 2 3 4 5 V8 6 7 ① ⑤ ⑥ ② ⑦ ③ ④

7.3.2 广度优先搜索遍历 算法描述:从图中某个顶点V出发,访问此顶点,然后依次V的各个未被访问的邻接点,再分别从这些邻接点出发,依次访问它们的各个未被访问的的邻接点,邻接点出发的次序按“先被访问的先出发”的原则,直至图中前面已被访问的顶点的邻接点都访问到;若此时图中尚有顶点未被访问,则另选一个图中未曾访问的顶点作始点,重复上面的过程,直至图中所有的顶点都被访问。

无向连通图的广度优先搜索过程 V 1 2 3 4 5 V8 6 7 ① ② ③ ④ ⑤ ⑥ ⑦

7.4 图 的 应 用 7.4.1 生成树与最小生成树 生成树:由N-1条边将G中N个顶点连接成G的极小连通子图,该极小连通子图就是G 的一棵生成树。 最小生成树问题:一棵生成树的代价定义为生成树上各边权值之和。要选择一棵代价最小的生成树的过程称为最小生成树问题。最小生成树的构造算法有多种,最著名的是 Prim(普里姆)算法。

求连通网的最小生成树过程示意: 1 2 5 3 6 4 1 3 2 5 4 2 5 3 6 4

7.4.2 拓扑排序 一、概念 无环图:一个无环的有向图称作有向无环图,简称DAG图。 7.4.2 拓扑排序 一、概念 无环图:一个无环的有向图称作有向无环图,简称DAG图。 AOV网:用顶点表示活动,用弧表示活动之间的优先关系的有向图称为AOV网。 在AOV网中,不应该出现有向环路,因为环路表示顶点之间的先后关系进入了死循环。通过对有向图进行拓扑排序来检测图中是否存在环路。

拓扑序列:设G=(V,E)是一个具有n个顶点的有向图,V中顶点的序列必须满足下列条件方可称为有向图的拓扑序列:若在有向图G中,从顶点Vi到Vj有一条路径,则在序列中,顶点Vi排在顶点Vj之前。若从顶点Vi到顶点Vj没有路径,则在序列中给这两个顶点安排一个先后次序。若有向图G所以的顶点都在拓扑序列之中,则AOV网中必定不存在环。 拓扑排序:实现一个有向图的拓扑序列的过程。

二、拓扑排序的算法描述 1)在有向图中选择一个入度为0的顶点,输出该顶点; 2)从图中删除该顶点和所有以它为顶点的弧; 3)重复执行1)2),直到找不到入度为0的顶点时,拓扑排序完成。

7.4.3 最短路径 以带权有向图为数据结构,求最短路径的问题常用于现实生活中的求几个城市之间的交通网络等问题。 迪杰斯特拉算法求最短路径的基本思想: 设有向网络G=(V,E),把网络中所以顶点分成两组,第一组S包括已确定最短路径的顶点,初始时只含有源点;第二组V-S包括尚未确定最短路径的顶点,初始时含有图中除源点外的所有其他顶点。按路径长度递增的顺序计算源点到各顶点的最短路径,逐个把第二组中的顶点加到第一组中去,直至S=V。

7.5 应用举例及分析 C 2 1 6 3 4 5 e1 e5 e7 e4 e3 e2 e6 例7.1拓扑排序实用程序。 对应该有向图,用邻接链表结构存储此图。程序首先调用建立有向图邻接链表的算法,建立有向图的邻接链表,在此邻接链表结构上,实现对有向图的拓扑排序并输出结果。

#include “stdio.h” #include”alloc.h” #define MAXLEN 40 //有向图顶点最大数目 #define VEXTYPE int //有向图顶点类型 typedef struct gnode //每条弧对应一个结点 { int adjvex; struct gnode * next; }EDGENODE; typedef struct { int id; //顶点的入度 VEXTYPE vextex; //顶点的信息 EDGENODE * ;link; //每个顶点对应一单链表 }VEXNODE;

typedef struct {VEXNODE adjlist[MAXLEN]; //邻接链表 int vexnum,arcnum; //有向图的顶点数目、弧数目 int kind; //有向图的 kind = 1 }ADJGRAPH; ADJGRAPH creat_adjgraph() { EDGENODE * p; Int I,s,d;

ADJGRAPH adjg; adjg,kind = 1; printf(“请输入顶点数和边数:”); scanf(“%d %d”,&s,&d); adjg.vexnum = s; adjg.arcnum = d; for(i = 0; j < adjg.vexnum; i++) //邻接链表顶点初始化 {printf(“第 %d个顶点信息:”,i +1); getchar();

scanf(“%d”,&adjg.adjlist[i].vextex); adjg.adjlist[i].link = NULL; adjg.adjlist[i].id = 0;} for(i=0; i< adjg.arcnum; i++) //每条弧的信息初始化 {printf(“第 %d条边的起始顶点编号和终止顶点编号:\n”,i + 1); scanf(“%d,%d”,&s,&d); while(s < 1||s > adjg.vexnum|| d < 1 || d > adjg.vexnum) {printf(“ 编号超出范围,重新输入:”); scanf(“%d,%d”,&s,&d)}

s- -; d- -; p = malloc(sizeof(EDGENODE)); //每条弧对应生成一个结点 p -> adjvex = d; p -> next = adjg.adjlist[s].link; //结点插入对应的链表中 adjg.adjlist[s].link = p; adjg.adjlist[d].id++; //弧对应的终端顶点入度加1 } return adjg;

void topsort(ADJGRAPH ag) //拓扑排序过程 { int i, j, k, m, n, top; EDGENODE * p; n = ag.vexnum; top = -1 for(i = 0; i < n; i++) //将入度为0的顶点压入一个链栈,top指向栈顶结点 If(ag.adjlist[i].id = = 0) //这是一个利用id为0的域链接起来的寄生栈 {ag.adjlist[i].id = top; top = i;}

m = 0; while(top 1 = -1) //当栈不空时,进行拓扑排序 {j = top; printf(“%3c”, ag.adjlist[j].vertex); //输出栈顶元素并删除栈顶元素 m++; p = ag.adjlist[j].link; while(p ! = NULL) { k = p ->adjvex; ag.adjlist[k].id - -; //删除相关的弧 if(ag.adjlist[k].id = 0) //出现新的入度为0的顶点,将其入栈 {ag.adjlist[k].id = top; top = k;} p = p ->next;} }

if(m < n) printf(“\n网中有环!\n”); //拓扑排序过程中输出的顶点数<有向图中的顶点数 } main() { ADJGRAPH ag; Ag = creat_adjgraph(); topsort(ag);

例7.2求最短路径实用程序。 对应右边的有向网,用邻接矩阵结构存储此图。程序首先建立有向图的邻接矩阵,在此邻接矩阵结构上,计算图中从顶点V1出发到其他各顶点的最短路径,并输出结果。 1 2 5 3 4 10 100 30 50 60 20

#include “datastru.h” #include “stdio.h” #include “alloc.h” #define MAX 10000 MGRAPH create_mgraph() { int i, j, k, h; char b, t; MGRAPH mg; mg. kind = 3 printf(“请输入顶点数和边数:”); scanf(“%d,%d”,&i, &j); mg.vexnum = i; mg.arcnum = j; for( i = 0 ;i < mg . vexnum ; i++) { getchar () ; printf ( “第 % d 个顶点信息:”, i + 1); scanf ( “ % c”, & mg . vexs [i]); } for ( i = 0 ; i < mg .vexnum ; i ++) for ( j = 0 ; j < mg . vexnum ; j ++) mg . arcs [i][j] = MAX ;

for ( k = 1 ; k < = mg . arcnum ; k ++) { printf ( “ \ n 第 % d条边的起始顶点编号和终止顶点编号:” , k); scanf (“ %d , %d”, &i , & j); while ( i <1 | | i > mg . vexnum | | j < 1 | | j > mg . vexnum) {printf ( “编号超出范围,重新输入:\ n \ t”); scanf ( “ %d ,%d” ,& i , &j)} printf (“此边的权值:”); scanf (“%d” ,& h); mg . arcs [i - 1] [j - 1] = h; return mg ; } main ( ) { MGRAPH mg ; Int cost [MAXLEN] [MAXLEN] ; Int path [MAXLEN] , s [MAXLEN] ; Int dist [MAXLEN] ; Int i , j , n , v0 , min , u ; Mg = create_mgraph () ; //建立有向图的邻接矩阵结构

Printf (“请输入起始顶点的编号:”) ; //有向图中顶点的编号从 1 编起 Scanf (“%d”, & v0); Vo - - ; n = mg . vexnum ; for ( i = 0 ; i < n ; i ++) //cost 矩阵初始化 {for( j = 0 ; j < n ; j ++) cost [i] [j] = mg .arcs [i][j]; cost [i][j] = 0;} for (i = 0 ; i < n ; i ++) {dist [i] = cost [v0][i]; if (dist[i] < MAX & & dist [i] >0) //dist数组初始化 path [i] =v0 ;} // path数组初始化 s[i] = 0; //s数组初始化 s [v0] =1 ;}

for( i= 0 ; i < n ; i ++) // 按最短路径递增算法计算 {min = MAX ; u= v0; for ( j=0 ; j< n ; j++) if (s[j] = = 0 && dist [j]< min) {min = dist [j]; u=j;} s[u] = 1; //u顶点是求得最短路径的顶点编号 for (j = 0 ; j< n ; j++) if (s[j]= = 0 && dist[u] +cost [u][j]<dist[j]) // 调整dist {dist[j] = dist[u] + cost[u][j]; path[j] = u;} //path记录了路径经过的顶点 }

for(i = 0;i<n ; i++) //打印结果 if (s[i] = = 1) {u=i; while(u! = v0) {printf(“%d < -”,u+1); u= path[u];} printf(“%d”, u+1); printf(“d=%d\n”, dist[i]); //有路径 } else printf(“%d < - %d d=MAX \n”,i +1, v0+1); //无路径

习题 P122 7.2, 7.3, 7.4, 7.5 , 7.12