- 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
- 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载。
- 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
查看更多
Chapte13-贪婪算法-2
Chapter13 贪婪算法 内容提要 13.1 示例问题提出 13.2 贪婪算法的思想 13.3 贪婪算法的应用 货箱装船 拓扑排序 单源最短路径 最小耗费生成树 贪婪算法应用 拓扑排序 单源点最短路径——Dijkstra算法 最小耗费生成树 Kruskal算法 Prime算法 Sollin算法 1、拓扑排序 DAG图:有向无环图 几乎所有的工程(project)都可分为若干个称作“活动”的子工程,并且这些子工程之间通常受着一定条件的约束,例如其中某些子工程必须在另一些子工程完成之后才能开始 对整个工程和系统,主要关心两方面的问题: 工程能否顺利进行——拓扑排序; 完成整个工程所必须的最短时间——求关键路径 顶点表示活动的网络 (Activity On Vertices: AOV 网络) AOV 网络示例:选课问题 表示课程之间优先关系的有向图 检测有向环的方法——拓扑排序 拓扑排序方法 拓扑排序的过程 拓扑排序的过程(续) 课堂练习:学生选课的拓扑序列 拓扑排序用贪婪算法实现 数据结构的选择 补充:AOE网络 用边表示活动的网络 AOE网络示例 课后练习 2、单源点最短路径 边上权值非负情形的单源最短路径问题 单源最短路径示例:源点1 如何求从某一源点到各个终点的路径 ? Dijkstar算法的贪婪准则 算法实现:最短路径的存储 利用数组 p,前驱顶点 p[i]给出从s到达i的路径中顶点i前面的那个顶点。 从s到顶点i的路径可反向创建:从i出发按照p[i], p[p[i]], p[p[p[i]]], …的顺序,直到到达顶点s或0。 辅助数组d[i]:顶点当前最短路径长度 辅助数组d[i]的变化 L表 源点未到达顶点表 采用数据结构:无序链表 VS. 最小堆 初始值:与源点邻接的顶点链表 更新情况:某个顶点j的d[j]发生变化,且不在L中,则加入到链表中 Dijkstar算法伪代码 Dijkstar算法(程序13-5) Dijkstar算法(程序13-5) Dijkstar算法复杂度分析 对于具有n个顶点和e条边的带权有向图, 无论采用邻接矩阵,还是邻接链表,时间复杂度均为O(n2) 原因:必须至少对每一条边检查一次! 邻接矩阵仅能优化最后一个循环 O(e) 【思考】如何求所有顶点之间的最短路径 3、最小生成树 生成树的特点 生成树的类型 最小耗费(代价)生成树及构造原则 最小耗费生成树构造方法 (1)Kruskal算法 Kruskal算法思想 Kruskal算法示例 Kruskal算法伪码描述 利用最小堆和并查集实现Kruskal算法 补充:集合的树形表示方法 并查集 (Union-Find Sets) class UnionFind { public: UnionFind(int Size = 10); ~UnionFind() { delete [] parent; delete [] root; } void Union(int, int); int Find(int); private: int *parent; 保存该树中节点的个数 bool *root; 根节点标志 }; UnionFind::UnionFind(int n) { //初始化,一个元素作为一类或一棵树 root = new bool[n+1]; parent = new int[n+1]; for (int e = 1; e = n; e++) { parent[e] = 1; 节点个数为1 root[e] = true; 为根节点 } } void UnionFind::Union(int i, int j) { if (parent[i] parent[j]) { 将i作为j的子树 parent[j] += parent[i]; root[i] = false; parent[i] = j; } else { 将j作为i的子树 parent[i] += parent[j]; root[j] = false; parent[j] = i; } } int UnionFind::Find(int e) { int j = e; while (!root[j]) j = parent[j]; 找到包含e的树的根 int f = e; while (f !
文档评论(0)