收藏 分享(赏)

数据结构与算法分析-11.ppt

上传人:hwpkd79526 文档编号:10057240 上传时间:2019-10-02 格式:PPT 页数:47 大小:436.50KB
下载 相关 举报
数据结构与算法分析-11.ppt_第1页
第1页 / 共47页
数据结构与算法分析-11.ppt_第2页
第2页 / 共47页
数据结构与算法分析-11.ppt_第3页
第3页 / 共47页
数据结构与算法分析-11.ppt_第4页
第4页 / 共47页
数据结构与算法分析-11.ppt_第5页
第5页 / 共47页
点击查看更多>>
资源描述

1、DATA STRUCTURE,第九章 图,数据结构,第九章 图9.1 图的基本概念 9.2 图的存储结构 9.3 图的遍历 9.4 拓扑排序和关键路径 9.5 最小代价生成树 9.6 最短路径,内容提要:1 图的基本概念 2 图的存储结构 3 图的遍历 4 拓扑排序和关键路径 5 最小代价生成树 6 最短路径,9.1 图的基本概念,与线性表、树和集合不同,在图结构中,每个数据元素都可以与任何其它数据元素相关。图在许多方面都有所应用。见图9.1。,第九章 图9.1 图的基本概念 9.2 图的存储结构 9.3 图的遍历 9.4 拓扑排序和关键路径 9.5 最小代价生成树 9.6 最短路径,(b)

2、与(a)对应的图,(a) 电路示例,图9.1 电路示例及对应的图,图(graph):是数据结构 G=(V,E),其中V(G)是G中结点的有限非空集合,结点的偶对称为边(edge);E(G)是G中边的集合。 图中的结点又称为顶点(vertex)。 有向图(directed graph):指图中代表边的偶对是有序的。用代表一条有向边(又称为弧arc),则v1称为弧尾(tail),v2称为弧头(head)。 无向图(undirected graph):指图中代表边的偶对是无序的。 在无向图中边(v1,v2 )和(v2,v1)是同一条边。,9.1.1 图的定义与术语,图中 V(G1)=V(G2)=v0

3、,v1,v2,v3,v4 E(G1)=(v0,v1),(v0,v2),(v0,v4),(v1,v2),(v2,v3),(v2,v4),(v3,v4) E(G2)=,自回路:如果图中存在无向边(vi,vi)或有向边,则称这样的边为自回路。 多重图:指图中两个顶点间允许有多条相同的边。,邻接:如果(vi,vj)是无向图中的一条边,则称顶点vi和vj相邻接。 例如:顶点v1和v2是相邻接的。,完全图:顶点数目相同的图中边的数目最多的图称为完全图。无向完全图有n(n-1)/2条边,有向完全图有n(n-1)条边。 例如:右图是一个完全图。有6条边。,图9.4 完全图,如果是有向图中的一条边,则称顶点vi

4、邻接到vj;称顶点vj邻接自vi ,并称顶点vj和vi相关联。,子图:图G的一个是图G=(V,E),其中V(G)V(G), E(G)E(G).,1,0,2,3,4,1,0,2,3,4,G1,G2,路径:在无向图G中,若从顶点vp到vq之间存在顶点序列vp, v1,v2,vn,vq,使得(vp,v1),(v1,v2),(vn , vq )都是图G中的边。对于有向图顶点序列vp,v1,v2,vn,vq,应使, ,都是图G中的边。,路径长度: 指路径上边的数目。,简单路径: 指路径上所有顶点各不相同,起点和终点除外。,回路: 起点和终点相同的简单路径。,v0,v1,v2,v3; v0,v1,v2,v

5、3,v4,v2,v0; v0,v1,v2,v3,v4,v0都是路径,它们的路径长度分别为3,6,5。 其中v0,v1,v2,v3和v0,v1,v2,v3,v4,v0是简单路径, v0,v1,v2,v3,v4,v0又是回路。,无向图中如果两个顶点v0和v1之间存在一条路径,则称顶点v0和v1是连通的,否则是不连通的。 连通图:无向图中如果任意两个顶点之间是连通的,则称该无向图为连通图。 连通分量:无向图的极大连通子图称为该无向图的连通分量。,v0和v3是连通的。实际上该图任意两个顶点都是连通的,故该图是连通图。,v0和v6是不连通的。该图是非连通图,但它存在两个连通分量。 注意极大的含义:如果某

6、个连通子图再加上一个顶点后,仍是连通的,则它不是连通分量。,1,0,2,3,4,强连通图:有向图中如果任意两个顶点v0和v1之间,存在一条从v0到v1的路径,同时存在一条从v1到 v0的路径,则称该有向图为强连通图。(任意两个顶点是连通的) 强连通分量:有向图的极大连通子图称为该有向图的强连通分量。,1,0,2,3,4,1,0,2,3,4,1,0,2,3,4,顶点的度:与该顶点相关联的边的数目。 入度:有向图中顶点v的入度指以v为弧头的弧的数目; 出度:有向图中顶点v的出度指以v为弧尾的弧的数目。有向图中,顶点的度=入度+出度。 例如左图中,v1,v2的度分别为2和3。右图中,v0的入度和出度

7、分别为3和1,v0的度为4。,生成树:无向图的生成树是一个极小连通子图,它包含图中所有顶点,但只有足以构成一棵树的(n-1)条边。再加上一条边将构成回路。,有根有向树:是一个有向图,它恰有一个顶点的入度为0,其余顶点的入度为1。如果略去边的方向,处理成无向图后,则图是连通的。,网:在图的每条边上加上一个数字称为权, 带权的图称为网。,生成森林:是一个子图,由若干棵互不相交的有根有向树组成,包含图中所有的顶点。,9.1.2 图的抽象数据类型,ADT 9.1 图抽象数据类型 Data: 顶点的非空集合V和边集E,每条边由E中偶对(u,v)表示。Operations:Create(n): 创建一个有

8、n顶点没有边的图Add(u,v): 向图中添加一条边(u,v)Delete(u,v): 从图中删除一条边(u,v)Vertices(): 返回图中顶点数Edges(): 返回图中边数Exist(u,v):如果存在边(u,v),返回true,否则返回false ,template class Graph public:Graph (int vertices=10) n= vertices; e=0; Graph() ;virtual bool Add(int u,int v,const T ,图的摸板抽象类Graph,所有图的类均由该抽象类派生而来,对于图的操作,还有其它成员函数,将在以后陆续介

9、绍。主要有: 1. void DFS( ); /深度优先搜索图 2. void BFS( ); /广度优先搜索图 3. void Toposort( ); /拓扑排序 4. void CriticalPath( ); /关键路经 5. void Prim(int k); /普里姆算法求最小代价生成树 6. void Kruskal(int edges);/克鲁斯卡尔算法求最小代价生成树 7. void Dijkstra(int k,T d,int p);/迪杰斯特拉算法求单源最短路经 8. void Fload(T */弗洛伊德算法求所有顶点之间的最短路经,1 矩阵表示法 2 邻接表表示法 3

10、 邻接多重表表示法,9.2 图的存储结构,9.2.1 矩阵表示法,一、邻接矩阵,一个有n个顶点的图G=(V,E)的邻接矩阵是一个n*n的矩阵A,A的每个元素是0或1。,第九章 图9.1 图的基本概念 9.2 图的存储结构 9.3 图的遍历 9.4 拓扑排序和关键路径 9.5 最小代价生成树 9.6 最短路径,设V=0,1,2,n-1,如果G是无向图,则A的元素定义为:,如果G是有向图,则A的元素定义为:,如果G是带权的图,则邻接矩阵中值为1的元素应替换为权值,有时需要将0替换为 。,图9.7 图的邻接矩阵,二、关联矩阵,图9.1中的电路图,按克希霍夫定律,节点电流方程如下:,将上述方程组写成矩

11、阵形式, 便得到关联矩阵:,关联矩阵,支路电流向量,图G=(V,E)的关联矩阵A定义如下:,L1 C2 L2 R1 C1 C3 R2 n1 1 0 0 1 0 0 0 n2 -1 1 0 0 1 0 0 n3 0 -1 1 0 0 1 0 n4 0 0 -1 0 0 0 1,程序9.2 邻接矩阵表示的图的C+类 template class MGraph : public Graph public:MGraph (int vertices=10, T NoEdge=0); MGraph() ;bool Add(int u,int v,const T,三、邻接矩阵表示的图的C+类,1 图的C+类

12、声明,程序9.2 是从程序9.1给出的抽象类派生出来的。,2 构造函数和析构函数,template /构造函数 MGraph:MGraph(int vertices, T noEdge) n=vertices; NoEdge= noEdge; /0或a=new T *n;for (int i=0;in;i+) ai=new T n; aii=0;for (int j=0;jn;j+)if (i-j) aij= NoEdge; ,template /析构函数 MGraph : MGraph ( ) for (int i=0;in;i+) delete ai;delete a; ,template

13、 /判边是否存在 bool MGraph:Exist(int u,int v) if (un-1|vn-1|u=v|auv=NoEdge)return false; return true; ,3、边的插入、删除和判其是否存在,template /边的插入 bool Mgraph:Add(int u,int v,const T ,/边的删除 bool Mgraph : Delete(int u,int v) if (un-1|vn-1|u=v|auv= =NoEdge) cerr“Bad Input! “endl;return false; auv= NoEdge; /对无向图,则加语句:av

14、u= NoEdge; e-;return true; ,9.2.2 邻接表表示法,一、邻接表,要点:1 为图中每一个顶点建立一个单链表;2 顶点u的单链表中,每一个结点v表示一个邻接点,即代表一条边(u,v) 或 3 结点和边的结构如下:,4 每个单链表的头指针存入一个一维数组,以表示一个图。,0,1,3,2,0,1,3,2,1 1 5,43,0,1,3,2,二、 邻接表表示的图的C+类,程序9.5 邻接表表示的图的C+类声明 template class LinkGraph ; template class Enode /邻接表的单链表结点类 public:Enode nextarc=NUL

15、L; Enode(const int vertex,const T,1 C+类声明,程序9.5 表示的图的邻接表类声明 template class LinkGraph:public Graph public:LinkGraph(int vertices, T MaxNum); LinkGraph();bool Add(int u,int v,const T ,/构造函数 template LinkGraph:LinkGraph(int Vertices, T MaxNum) n=Vertices;maxnum=MaxNum;a=new ENode *n;for (int i=0;in;i+)

16、 ai=NULL; ,2 构造函数和析构函数,/析构函数 template LinkGraph : LinkGraph() delete a; ,0 1 .n-1,.,搜索、插入或删除从顶点u发出的边,只在au所指向的单链表中操作。程序如下:,3 边的搜索、插入和删除,/搜索边的函数 template LinkGraph:Exist(int u,int v)const if (un-1) return false;Enode *p=au;while (p ,/插入边的函数 template bool LinkGraph : Add(int u,int v,const T ,/删除边的函数 te

17、mplate bool LinkGraph:Delete(int u,int v) if (u-1 ,当用邻接表存储无向图时,一条边(u,v) 在顶点u和顶点v的单链表中都要出现,增加了时间和空间的开销。而且在有些问题中,需要对已经处理过的表加上标记,而这两条边又不在同一个单链表中,给操作带来了麻烦。邻接多重表表示法可以使问题简化,其结点结构如下:,9.2.3 邻接多重表表示法,边结点中mark是标记域,说明是否处理过vertex1和vertex2是顶点域,指示相关联的2个顶点指针域path1指示与顶点vertex1相关联的下一条边指针域path2指示与顶点vertex2相关联的下一条边,图9

18、.9 无向图的多重表表示,0,1,2,3,(c) 无向图的例子,0 1,0 2,0 3 ,1 2,1 3 ,2 3 ,(d) 无向图的多重表表示,六条边,有六个边结点。 例 从顶点2出发搜索与其相邻的顶点和边。,9.3 图的遍历,第九章 图9.1 图的基本概念 9.2 图的存储结构 9.3 图的遍历 9.4 拓扑排序和关键路径 9.5 最小代价生成树 9.6 最短路径,数据结构,DATA STRUCTURE,图的遍历: 指从图G的任意一个顶点v出发,访问图中所有结点且每个结点仅访问一次的过程。,图遍历的方法:深度优先搜索(类似于树的先序遍历)和广度优先搜索(类似于树的按层次遍历),一、深度优先

19、搜索算法,与树遍历的差异:1 从图中任意一个顶点出发未必能到达其它所有顶点;2 图中存在回路时,又可能多次经过同一个顶点,故访问过的顶点要打上标记。,9.3.1 深度优先搜索,从图G中某个顶点v出发,深度优先搜索图的DFS算法如下:1 访问顶点v并打上标记。2 依次从v的未访问过的邻接点出发,深度优先搜索图G.,对有向图G,从A出发DFS,访问的次序是A,B,D,C; 另选一个顶点出发搜索图G的其余部分;结果得到一个生成森林。,思考: 图的深度优先搜索序列是否唯一?(指从同一顶点出发程序),template void LinkGraph:DFS(int v,bool visited) Enod

20、e *w; visited v=true; cout nextarc)if (! visitedw-adjvex) DFS(w-adjvex,visited); ,template void LinkGraph:DFS() bool visited =new bool n;for(int i=0; in; i+) visitedi=false;for(int i=0;in;i+)if(! visitedi) DFS(i,visited);delete visited; ,二、深度优先搜索的C+程序,分析:1 从上面深度优先搜索算法的描述中可以看出,从递归函数DFS外部调用该递归函数与在递归函数

21、DFS内部自己调用自己,所起作用不同。2 深度优先搜索算法对有向图的每条边只查看1次,而对于无向图,每查看2次。3 n个顶点、e条边的图采用邻接表存储,DFS算法的时间为O(n+e),而采用邻接矩阵表示,时间为 O(n2)。,9.3.2 广度优先遍历,从图中任一顶点v出发遍历图的BFS算法的描述:1 访问顶点v并打上标记;2 依次访问顶点v的未访问的邻接点,再访问与这些 邻接点相邻接且未访问的顶点。3 若图中还有顶点未被访问,则另选一个未访问的顶点,重新开始上述过程。,一、 广度优先搜索算法BFS,图9.11 图的G广度优先搜索,例: 对下图,从顶点0出发BFS遍历,其遍历序列是: 0,1,1

22、1,10,2,5,6,9,3,4,7,8。,广度优先搜索算法要实现按层次访问,需要一个队列来保存已访问过但其邻接点尚未考察的顶点。(1)访问0,0入队,(0)。(2)0出队,(),访问与0相关联的未访问顶点,访问一个入队一个,(1,11,10)。(3)重复,直到队列空。若图中还有顶点未被访问,则另选一个未访问的顶点,重新开始上述过程。图中顶点以及遍历时生成的边所构成的子图称为广度优先搜索生成树。,程序9.9 BFS的C+程序 template void LinkGraph:BFS() bool visited =new bool n;for (int i=0;in;i+) visitedi=f

23、alse;for (int i=0;in;i+)if(! visitedi) BFS(i,visited); delete visited; ,二、广度优先搜索的C+程序,采用邻接表作为图的存储结构,其广度优先搜索的程序如下:,template void LinkGraph:BFS(int v,bool visited) ENode *w; int n;SeqQueue q(n);cout nextarc)if(! visitedw-adjvex) cout adjvex=true; q.EnQueue(w-adjvex); ,BFS算法的特点: 1 每个顶点进出队列各一次。2 对于每个出队的顶点,都要检查其所有的邻接点,故每条边被检查2次。3 n个顶点,e条边的图采用邻接表存储,BFS算法的时间为O(n+e),而采用邻接矩阵表示,时间为O(n2)。,如同二叉树的遍历算法,图的DFS和BFS算法是最重要、最基本的算法,许多有关图的算法都可以对它们稍加修改得到。例如,求无向图的连通分量、有向图的强连通分量、生成树(森林)等。,

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 企业管理 > 管理学资料

本站链接:文库   一言   我酷   合作


客服QQ:2549714901微博号:道客多多官方知乎号:道客多多

经营许可证编号: 粤ICP备2021046453号世界地图

道客多多©版权所有2020-2025营业执照举报