最小生成树.

Slides:



Advertisements
Similar presentations
阻塞操作. 在 linux 里,一个等待队列由一个 wait_queue_head_t 类型的结构来描述 等待队列的初始化: static wait_queue_head_t testqueue; init_waitqueue_head(&testqueue);
Advertisements

人 工 智 慧 報 告 五子棋AI設計 報告者 : 潘輝銘.
第七章 图 7.1 图的定义和术语 7.2 图的存储结构 7.3 图的遍历 7.4 图的连通性问题 7.5 有向无环图及其应用
复习:树 树的基本概念和术语 二叉树的概念及性质 二叉树的存储结构 遍历二叉树 线索二叉树 树的应用:哈夫曼树 顺序存储 链式存储 递归算法
算法设计与分析 授课教师:王秋芬 办公地点:7307
最大团问题 回溯法应用 作者:余新华 时间:
探索三角形相似的条件(2).
第六章 图(一).
第七章 图 (Graph)
第9章 图 图的基本概念 图的存储结构 图的实现 图的遍历 最小生成树 最短路径 拓扑排序 关键路径 主要知识点.
第七章 图 7.1 图的基本概念 7.2 图的存储表示 7.3 图的遍历 7.4 图的生成树 7.5 最短路径 7.6 拓扑排序
图(一).
第七章 图 1、图的基本概念 2、图的存储表示 3、图的遍历与连通性 4、最小代价生成树 5、最短路径问题 6、AOV网络和AOE网络.
图的遍历.
第八章 图 图的基本概念 图的存储结构 图的遍历与连通性 最小生成树 最短路径 活动网络.
强连通分量 无向图 1、任意两顶点连通称该图为连通图 2、否则将其中的极大连通子图称为连通分量 A D C B E 有向图
·线性表的定义及ADT ·线性表的顺序存储结构 ·线性表的链接存储结构 · 单向循环链表 · 双链表、双向循环链表 · 一元多项式的加法
哈夫曼编码.
第七章 图.
7.1 抽象数据类型图的定义 7.2 图的存储表示 7.3 图的遍历 7.4 最小生成树 7.5 重(双)连通图和关节点
第七章 图.
授课老师:龚涛 信息科学与技术学院 2018年3月 教材: 《Visual C++程序员成长攻略》 《C++ Builder程序员成长攻略》
第七章 图 知识点2:图的存储结构.
第七章 图 东南大学计算机学院 方效林 本课件借鉴了清华大学殷人昆老师 和哈尔滨工业大学张岩老师的课件.
第7章 图 本章主题:图的基本概念、图的存储结构和图的常用算法 教学目的: 教学重点:图的各种存储方式及其运算
数据结构 复习课 王彦 博士,副教授
第七章 图.
五、链 表 1、单链表 2、双向链表 3、链表应用.
第7章 图 7.1 图的定义和术语 7.2 图的存储结构 7.3 图的遍历 7.4 图的连通性问题 7.5 有向无环图的应用
第七章 图.
动态规划(Dynamic Programming)
C++语言程序设计 C++语言程序设计 第七章 类与对象 第十一组 C++语言程序设计.
使用矩阵表示 最小生成树算法.
无向树和根树.
第三章 链表 单链表 循环链表 多项式及其相加 双向链表 稀疏矩阵.
第6章 图 本章中介绍下列主要内容: 图的定义 图的存储结构 图的遍历操作 图的几个典型问题.
C++语言程序设计 C++语言程序设计 第七章 类与对象 第十一组 C++语言程序设计.
知识点回顾 拓扑排序 关键路径 应用领域、求解步骤、算法实现过程 应用领域 求解步骤
第八章 图 图的基本概念 图的存储表示 图的遍历与连通性 最小生成树 最短路径 活动网络.
Graphs.
8.1 图的基本概念 8.2 图的存储结构 8.3 图的遍历 8.4 生成树 8.5 最短路径 8.6 拓扑排序 8.7 关键路径
复习 图的定义和术语 图(Graph)、有向图、无向图、子图、有向完全图 、完全图、稀疏图、稠密图、权、网、邻接点、相关边、度、路径、路径长度、回路、简单路径、简单回路、连通、连通图、连通分量、强连通图、强连通分量、生成树 图的存储方法 给定一个图,画出邻接矩阵、邻接表 图的邻接矩阵和邻接表的存储算法.
算法设计与分析 ——贪心法. 算法设计与分析 ——贪心法 贪心算法 主要内容: 介绍贪心法的基本原理,贪心算法设计的基本方法和应用例子 。
顺序表的删除.
今天, AC 你 了吗? 2019/4/19.
线 性 代 数 厦门大学线性代数教学组 2019年4月24日6时8分 / 45.
C++复习2----类与对象.
第四章 栈和队列 栈 ( Stack ) 队列 ( Queue ) 优先队列 (Priority Queue) 小结.
常宝宝 北京大学计算机科学与技术系 数据结构(六) 常宝宝 北京大学计算机科学与技术系
成绩是怎么算出来的? 16级第一学期半期考试成绩 班级 姓名 语文 数学 英语 政治 历史 地理 物理 化学 生物 总分 1 张三1 115
图论初步 柏钧文.
第二章 Java语法基础.
知识点回顾 图的深度优先和广度优先遍历思想 图的深度优先遍历算法(用邻接表作为存储结构) 图的广度优先遍历算法(用邻接矩阵作为存储结构)
树和图 tree and graph 蔡亚星.
第七、八次实验要求.
目标 流程控制 字符串处理 C# 的类和对象 C# 访问修饰符 C# 构造函数和析构函数.
第六章 图 本章的主要内容是: 图的逻辑结构 图的存储结构及实现 图的连通性 最小生成树 最短路径 AOV网与拓扑排序 AOE网与关键路径.
#include <iostream.h>
第二章 Java基本语法 讲师:复凡.
十二、堆 堆的定义.
第七章 图 £7.1 图的定义和术语 £7.2 图的存储结构 £7.3 图的遍历 £7.4 图的连通性问题 £7.5 有向无环图及其应用
4.2 图的存储结构(cont.) v1 v2 v3 v4 v5 vertex= v1 v2 v3 v4 v5 v
数据结构 第六章 图.
树的基本概念.
创建、启动和关闭Activity 本讲大纲: 1、创建Activity 2、配置Activity 3、启动和关闭Activity
使用Fragment 本讲大纲: 1、创建Fragment 2、在Activity中添加Fragment
1、图的基本概念 2、图的存储结构 3、图的遍历与连通性
最小生成树 最优二叉树.
§2 自由代数 定义19.7:设X是集合,G是一个T-代数,为X到G的函数,若对每个T-代数A和X到A的函数,都存在唯一的G到A的同态映射,使得=,则称G(更严格的说是(G,))是生成集X上的自由T-代数。X中的元素称为生成元。 A变, 变 变, 也变 对给定的 和A,是唯一的.
3.3.2 两点间的距离 山东省临沂第一中学.
Presentation transcript:

最小生成树

最小生成树 ( minimum cost spanning tree ) 使用不同的遍历图的方法,可以得到不同的生成树;从不同的顶点出发,也可能得到不同的生成树。 按照生成树的定义,n 个顶点的连通网络的生成树有 n 个顶点、n-1 条边。 构造最小生成树的准则 必须只使用该网络中的边来构造最小生成树; 必须使用且仅使用 n-1 条边来联结网络中的 n 个顶点; 不能使用产生回路的边。

算法的框架 我们利用最小堆(MinHeap)和并查集(DisjointSets)来实现克鲁斯卡尔算法。 克鲁斯卡尔 (Kruskal) 算法 克鲁斯卡尔算法的基本思想: 设有一个有 n 个顶点的连通网络 N = { V, E },最初先构造一个只有 n 个顶点,没有边的非连通图 T = { V,  }, 图中每个顶点自成一个连通分量。当在 E 中选到一条具有最小权值的边时,若该边的两个顶点落在不同的连通分量上,则将此边加入到 T 中;否则将此边舍去,重新选择一条权值最小的边。如此重复下去,直到所有顶点在同一个连通分量上为止。 算法的框架 我们利用最小堆(MinHeap)和并查集(DisjointSets)来实现克鲁斯卡尔算法。

首先,利用最小堆来存放E中的所有的边, 堆中每个结点的格式为 在构造最小生成树的过程中,最小堆中存放剩余的边,并且利用并查集的运算检查依附于一条边的两个顶点 tail、head 是否在同一个连通分量 (即并查集的同一个子集合) 上, 是则舍去这条边;否则将此边加入 T,同时将这两个顶点放在同一个连通分量上。随着各边逐步加入到最小生成树的边集合中,各连通分量也在逐步合并,直到形成一个连通分量为止。 tail head cost 边的两个顶点位置 边的权值

应用克鲁斯卡尔算法构造最小生成树的过程

最小生成树类定义 const int MAXINT = 机器可表示的, 问题中不可 能出现的大数 class MinSpanTree; class MSTEdgeNode { //生成树边结点类定义 friend class MinSpanTree; private: int tail, head; //生成树各边的两顶点 float cost; //生成树各边的代价 };

class MinSpanTree { //生成树的类定义 public: MinSpanTree ( int sz = NumVertices -1 ) : MaxSize (sz), n (0) { edgevalue = new MSTEdgeNode[MaxSize]; } int Insert ( MSTEdgeNode & item ); //将item加到最小生成树中 protected: MSTEdgeNode *edgevalue; //边值数组 int MaxSize, n; //最大边数,当前边数 };

利用克鲁斯卡尔算法建立最小生成树 void Graph<string, float> :: Kruskal ( MinSpanTree& T ) { MSTEdgeNode e; //边结点辅助单元 MinHeap<MstEdgeNode> H(CurrentEdges); int NumVertices = VerticesList.last; //顶点个数 UFSets F (NumVertices); //并查集F 并初始化 for ( int u = 0; u < NumVertices; u++ ) //邻接矩阵 for ( int v = u +1; v < NumVertices; v++ ) if ( Edge[u][v] != MAXNUM ) { //所有边 e.tail = u; e.head = v; e.cost = Edge[u][v]; H.Insert (e); //插入堆 }

int count = 1; //最小生成树加入边数的计数 while ( count < NumVertices ) { H.RemoveMin ( e ); //从堆中退出一条边 u = F.Find ( e.tail ); //检测两端点的根 v = F.Find ( e.head ); if ( u != v ) { //根不同不在同一连通分量 F.Union ( u, v ); //合并 T.Insert ( e ); //该边存入最小生成树 T count++; }

出堆顺序 (0,5,10) 选中 (2,3,12) 选中 (1,6,14) 选中 (1,2,16) 选中 (3,6,18) 舍弃 出堆顺序 (0,5,10) 选中 (2,3,12) 选中 (1,6,14) 选中 (1,2,16) 选中 (3,6,18) 舍弃 (3,4,22) 选中 (4,6,24) 舍弃 (4,5,25) 选中 0 1 2 3 4 5 6 F 0 1 2 3 4 5 6 0 28    10  0 28 0 16    14 1  16 0 12    2   12 0 22  18 3    22 0 25 24 4 10    25 0  5  14  18 24  0 6 -1 -1 -1 -1 -1 -1 -1 -2 -1 -1 -1 -1 -1 -2 -1 -2 2 -1 -1 -2 -2 -2 2 -1 1 -2 -4 1 2 -1 1 -2 -5 1 2 1 1 1 -7 1 2 1 1 并查集 邻接矩阵表示

在建立最小堆时需要检测邻接矩阵,计算的时间代价为 O(n2)。且做了 e 次堆插入操作, 每次插入调用了一个堆调整算法FilterUp( )算法, 因此堆插入需要的时间代价为 O(elog2e)。 在构造最小生成树时,最多调用了 e 次出堆操作RemoveMin( ),2e 次并查集的Find( )操作,n-1次Union( )操作,计算时间分别为 O(elog2e),O(elog2n)和O(n)。 总的计算时间为 O(elog2e + elog2n + n2 + n )

普里姆(Prim)算法 普里姆算法的基本思想: 从连通网络 N = { V, E }中的某一顶点 u0 出发,选择与它关联的具有最小权值的边(u0, v),将其顶点加入到生成树的顶点集合U中。 以后每一步从一个顶点在U中,而另一个顶点不在U中的各条边中选择权值最小的边(u, v),把它的顶点加入到集合U中。如此继续下去,直到网络中的所有顶点都加入到生成树顶点集合U中为止。 采用邻接矩阵作为图的存储表示。

用普里姆算法构造最小生成树的过程

在构造过程中,还设置了两个辅助数组: 例子 lowcost[ ] 存放生成树顶点集合内顶点到生成树外各顶点的各边上的当前最小权值; nearvex[ ] 记录生成树顶点集合外各顶点距离集合内哪个顶点最近(即权值最小)。 例子

若选择从顶点0出发,即u0 = 0,则两个辅助数组的初始状态为: 然后反复做以下工作: 在 lowcost [ ]中选择 nearvex[i]  -1 && lowcost[i]最小的边 i 用 v 标记它。则选中的权值最小的边为 (nearvex[v], v),相应的权值为 lowcost[v]。 将 nearvex[v] 改为 -1, 表示它已加入生成树顶点集合。将边 ( nearvex[v], v, lowcost[v] ) 加入生成树的边集合。

取 lowcost[i] = min{ lowcost[i], Edge[v][i] },即用生成树顶点集合外各顶点 i 到刚加入该集合的新顶点 v 的距离 Edge[v][i] 与原来它们到生成树顶点集合中顶点的最短距离lowcost[i] 做比较, 取距离近的作为这些集合外顶点到生成树顶点集合内顶点的最短距离。 如果生成树顶点集合外顶点 i 到刚加入该集合的新顶点 v 的距离比原来它到生成树顶点集合中顶点的最短距离还要近,则修改nearvex[i]:nearvex[i] = v。表示生成树外顶点i到生成树内顶点v当前距离最近。

v = 5 顶点5加入生成树顶点集合: v = 4 继续重复得:

最后生成树中边集合里存入得各条边为: (0, 5, 10), (5, 4, 25), (4, 3, 22), (3, 2, 12), (2, 1, 16), (1, 6, 14) 利用普里姆算法建立最小生成树 void Graph<string, float> :: Prim ( MinSpanTree &T ) { int NumVertices = VerticesList.last; //图顶点数 float * lowcost = new float[NumVertices]; int * nearvex = new int[NumVertices]; for ( int i = 1; i < NumVertices; i++ ) { lowcost[i] = Edge[0][i]; //顶点0到各边的代价 nearvex[i] = 0; //及最短带权路径 }

nearvex[0] = -1; //顶点0加到生成树顶点集合 MSTEdgeNode e; //最小生成树结点辅助单元 for ( i = 1; i < NumVertices; i++ ) { //循环n-1次, 加入n-1条边 float min = MAXNUM; int v = 0; for ( int j = 0; j < NumVertices; j++ ) if ( nearvex[j] != -1 && lowcost[j] < min ) { v = j; min = lowcost[j]; } //求生成树外顶点到生成树内顶点具有最小 //权值的边, v是当前具最小权值的边的位置 if ( v ) { //v==0表示再也找不到要求顶点了 e.tail = nearvex[v]; e.head = v;

T.Insert (e); //选出的边加入生成树 nearvex[v] = -1; //作该边已加入生成树标记 e.cost = lowcost[v]; T.Insert (e); //选出的边加入生成树 nearvex[v] = -1; //作该边已加入生成树标记 for ( j = 1; j < NumVertices; j++ ) if ( nearvex[j] != -1 && // j 不在生成树中 Edge[v][j] < lowcost[j] ) { //需要修改 lowcost[j] = Edge[v][j]; nearvex[j] = v; } 分析以上算法,设连通网络有 n 个顶点 ,则该算法的时间复杂度为 O(n2), 它适用于边稠密的网络。