第七十七课 最小生成树(Kruskal)
添加kruskal算法:
- #ifndef GRAPH_H
- #define GRAPH_H
- #include "Object.h"
- #include "SharedPointer.h"
- #include "Array.h"
- #include "DynamicArray.h"
- #include "LinkQueue.h"
- #include "LinkStack.h"
- #include "Sort.h"
- namespace DTLib
- {
- template < typename E >
- struct Edge : public Object
- {
- int b;
- int e;
- E data;
- Edge(int i=-, int j=-)
- {
- b = i;
- e = j;
- }
- Edge(int i, int j, const E& value)
- {
- b = i;
- e = j;
- data = value;
- }
- bool operator == (const Edge<E>& obj)
- {
- return (b == obj.b) && (e == obj.e); //在这里不关注权值大小
- }
- bool operator != (const Edge<E>& obj)
- {
- return !(*this == obj);
- }
- bool operator < (const Edge<E>& obj)
- {
- return (data < obj.data);
- }
- bool operator > (const Edge<E>& obj)
- {
- return (data > obj.data);
- }
- };
- template < typename V, typename E >
- class Graph : public Object
- {
- protected:
- template < typename T >
- DynamicArray<T>* toArray(LinkQueue<T>& queue)
- {
- DynamicArray<T>* ret = new DynamicArray<T>(queue.length());
- if( ret != NULL )
- {
- for(int i=; i<ret->length(); i++, queue.remove())
- {
- ret->set(i, queue.front());
- }
- }
- else
- {
- THROW_EXCEPTION(NoEnoughMemoryException, "No memory to create ret object...");
- }
- return ret;
- }
- SharedPointer< Array<Edge<E> > > getUndirectedEdges()
- {
- DynamicArray<Edge<E>>* ret = NULL;
- if( asUndirected() )
- {
- LinkQueue<Edge<E>> queue;
- for(int i=; i<vCount(); i++)
- {
- for(int j=i; j<vCount(); j++)
- {
- if( isAdjacent(i, j) )
- {
- queue.add(Edge<E>(i, j, getEdge(i, j)));
- }
- }
- }
- ret = toArray(queue);
- }
- else
- {
- THROW_EXCEPTION(InvalidOperationException, "This function is for undirected graph only...");
- }
- return ret;
- }
- int find(Array<int>& p, int v)
- {
- while( p[v] != -)
- {
- v = p[v];
- }
- return v;
- }
- public:
- virtual V getVertex(int i) = ;
- virtual bool getVertex(int i, V& value) = ;
- virtual bool setVertex(int i, const V& value) = ;
- virtual SharedPointer< Array<int> > getAdjacent(int i) = ;
- virtual bool isAdjacent(int i, int j) = ;
- virtual E getEdge(int i, int j) = ;
- virtual bool getEdge(int i, int j, E& value) = ;
- virtual bool setEdge(int i, int j, const E& value) = ;
- virtual bool removeEdge(int i, int j) = ;
- virtual int vCount() = ;
- virtual int eCount() = ;
- virtual int OD(int i) = ;
- virtual int ID(int i) = ;
- virtual int TD(int i)
- {
- return ID(i) + OD(i);
- }
- bool asUndirected()
- {
- bool ret = true;
- for(int i=; i<vCount(); i++)
- {
- for(int j=; j<vCount(); j++)
- {
- if( isAdjacent(i, j) )
- {
- ret = ret && isAdjacent(j, i) && (getEdge(i, j) == getEdge(j, i));
- }
- }
- }
- return ret;
- }
- SharedPointer< Array< Edge<E > > > prim(const E& LIMIT, const bool MINIUM = true) //参数为理论上的最大权值
- {
- LinkQueue< Edge<E> > ret;
- if( asUndirected() )
- {
- DynamicArray<int> adjVex(vCount());
- DynamicArray<bool> mark(vCount());
- DynamicArray<E> cost(vCount());
- SharedPointer< Array<int> > aj = NULL;
- bool end = false;
- int v = ;
- for(int i=; i<vCount(); i++)
- {
- adjVex[i] = -;
- mark[i] = false;
- cost[i] = LIMIT;
- }
- mark[v] = true;
- aj = getAdjacent(v);
- for(int j=; j<aj->length(); j++)
- {
- cost[(*aj)[j]] = getEdge(v, (*aj)[j]);
- adjVex[(*aj)[j]] = v;
- }
- for(int i=; (i<vCount()) && !end; i++)
- {
- E m = LIMIT;
- int k = -;
- for(int j=; j<vCount(); j++)
- {
- if( !mark[j] && (MINIUM ? (cost[j] < m) : (cost[j] > m)))
- {
- m = cost[j];
- k = j;
- }
- }
- end = (k == -);
- if( !end )
- {
- ret.add(Edge<E>(adjVex[k], k, getEdge(adjVex[k], k)));
- mark[k] = true;
- aj = getAdjacent(k);
- for(int j=; j<aj->length(); j++)
- {
- if( !mark[(*aj)[j]] && (MINIUM ? (getEdge(k, (*aj)[j]) < cost[(*aj)[j]]) : (getEdge(k, (*aj)[j]) > cost[(*aj)[j]])) )
- {
- cost[(*aj)[j]] = getEdge(k, (*aj)[j]);
- adjVex[(*aj)[j]] = k;
- }
- }
- }
- }
- }
- else
- {
- THROW_EXCEPTION(InvalidOperationException, "Prim operator is for undirected graph only...");
- }
- if( ret.length() != (vCount() - ) )
- {
- THROW_EXCEPTION(InvalidOperationException, "No enough edge for prim operation...");
- }
- return toArray(ret);
- }
- SharedPointer< Array<Edge<E> > > kruskal(const bool MINMUM = true)
- {
- LinkQueue< Edge<E> > ret;
- SharedPointer< Array< Edge<E> > > edges = getUndirectedEdges();
- DynamicArray<int> p(vCount()); //前驱标记数组
- for(int i=; i<p.length(); i++)
- {
- p[i] = -;
- }
- Sort::Shell(*edges, MINMUM);
- for(int i=; (i<edges->length()) && (ret.length() < (vCount() - )); i++)
- {
- int b = find(p, (*edges)[i].b);
- int e = find(p, (*edges)[i].e);
- if( b != e )
- {
- p[e] = b;
- ret.add((*edges)[i]);
- }
- }
- if( ret.length() != (vCount() - ) )
- {
- THROW_EXCEPTION(InvalidOperationException, "No enough edges for Kruskal operation...");
- }
- return toArray(ret);
- }
- SharedPointer< Array<int> > BFS(int i)
- {
- DynamicArray<int>* ret = NULL;
- if( ( <= i) && (i < vCount()) )
- {
- LinkQueue<int> q;
- LinkQueue<int> r;
- DynamicArray<bool> visited(vCount());
- for(int i=; i<visited.length(); i++)
- {
- visited[i] = false;
- }
- q.add(i);
- while( q.length() > )
- {
- int v = q.front();
- q.remove();
- if( !visited[v] )
- {
- SharedPointer< Array<int> > aj = getAdjacent(v);
- for(int j=; j<aj->length(); j++)
- {
- q.add((*aj)[j]);
- }
- r.add(v);
- visited[v] = true;
- }
- }
- ret = toArray(r);
- }
- else
- {
- THROW_EXCEPTION(InvalidParameterException, "Index i is invalid...");
- }
- return ret;
- }
- SharedPointer< Array<int> > DFS(int i)
- {
- DynamicArray<int>* ret = NULL;
- if( ( <= i) && (i < vCount()) )
- {
- LinkStack<int> s;
- LinkQueue<int> r;
- DynamicArray<bool> visited(vCount());
- for(int j=; j<visited.length(); j++)
- {
- visited[j] = false;
- }
- s.push(i);
- while( s.size() > )
- {
- int v = s.top();
- s.pop();
- if( !visited[v] )
- {
- SharedPointer< Array<int> > aj = getAdjacent(v);
- for(int j=aj->length() - ; j>=; j--)
- {
- s.push((*aj)[j]);
- }
- r.add(v);
- visited[v] = true;
- }
- }
- ret = toArray(r);
- }
- else
- {
- THROW_EXCEPTION(InvalidParameterException, "Index i is invalid...");
- }
- return ret;
- }
- };
- }
- #endif // GRAPH_H
测试程序如下:
- #include <iostream>
- #include "MatrixGraph.h"
- #include "ListGraph.h"
- using namespace std;
- using namespace DTLib;
- template< typename V, typename E >
- Graph<V, E>& GraphEasy()
- {
- static MatrixGraph<, V, E> g;
- g.setEdge(, , );
- g.setEdge(, , );
- g.setEdge(, , );
- g.setEdge(, , );
- g.setEdge(, , );
- g.setEdge(, , );
- g.setEdge(, , );
- g.setEdge(, , );
- g.setEdge(, , );
- g.setEdge(, , );
- return g;
- }
- template< typename V, typename E >
- Graph<V, E>& GraphComplex()
- {
- static ListGraph<V, E> g();
- g.setEdge(, , );
- g.setEdge(, , );
- g.setEdge(, , );
- g.setEdge(, , );
- g.setEdge(, , );
- g.setEdge(, , );
- g.setEdge(, , );
- g.setEdge(, , );
- g.setEdge(, , );
- g.setEdge(, , );
- g.setEdge(, , );
- g.setEdge(, , );
- g.setEdge(, , );
- g.setEdge(, , );
- g.setEdge(, , );
- g.setEdge(, , );
- g.setEdge(, , );
- g.setEdge(, , );
- g.setEdge(, , );
- g.setEdge(, , );
- g.setEdge(, , );
- g.setEdge(, , );
- g.setEdge(, , );
- g.setEdge(, , );
- g.setEdge(, , );
- g.setEdge(, , );
- g.setEdge(, , );
- g.setEdge(, , );
- g.setEdge(, , );
- g.setEdge(, , );
- return g;
- }
- int main()
- {
- Graph<int, int>& g = GraphComplex<int, int>();
- SharedPointer< Array< Edge<int> > > sa = g.kruskal();
- int w = ;
- for(int i=; i<sa->length(); i++)
- {
- w += (*sa)[i].data;
- cout << (*sa)[i].b << " " << (*sa)[i].e << " " << (*sa)[i].data << endl;
- }
- cout << "Weight: " << w << endl;
- return ;
- }
结果如下:
小结:
第七十七课 最小生成树(Kruskal)的更多相关文章
- python六十七课——网络编程(基础知识了解)
网络编程: 什么是网络编程? 网络:它是一种隐形的媒介:可以将多台计算机使用(将它们连接到一起) 网络编程:将多台计算机之间可以相互通信了(做数据交互) 一旦涉及到网络编程,划分为两个方向存在,一方我 ...
- NeHe OpenGL教程 第四十七课:CG顶点脚本
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
- NeHe OpenGL教程 第三十七课:卡通映射
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
- NeHe OpenGL教程 第二十七课:影子
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
- NeHe OpenGL教程 第十七课:2D图像文字
转自[翻译]NeHe OpenGL 教程 前言 声明,此 NeHe OpenGL教程系列文章由51博客yarin翻译(2010-08-19),本博客为转载并稍加整理与修改.对NeHe的OpenGL管线 ...
- 第三百七十七节,Django+Xadmin打造上线标准的在线教育平台—apps目录建立,以及数据表生成
第三百七十七节,Django+Xadmin打造上线标准的在线教育平台—apps目录建立,以及数据表生成 apps目录建立 我们创建一个apps目录,将所有的app放到apps目录里去,这样方便管理,也 ...
- centos Linux下磁盘管理 parted,df ,du,fdisk,partprobe,mkfs.ext4,mount,/etc/fstab,fsck,e2fsck,mk2efs,tmpfs ,nr_inodes, LVM,传统方式扩容文件系统 第七节课
centos Linux下磁盘管理 parted,df ,du,fdisk,partprobe,mkfs.ext4,mount,/etc/fstab,fsck,e2fsck,mk2efs,tmpf ...
- “全栈2019”Java第七十七章:抽象内部类与抽象静态内部类详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
- 模板——最小生成树kruskal算法+并查集数据结构
并查集:找祖先并更新,注意路径压缩,不然会时间复杂度巨大导致出错/超时 合并:(我的祖先是的你的祖先的父亲) 找父亲:(初始化祖先是自己的,自己就是祖先) 查询:(我们是不是同一祖先) 路径压缩:(每 ...
随机推荐
- 微信小程序code 换取 session_key
code 换取 session_key 这是一个 HTTPS 接口,开发者服务器使用登录凭证 code 获取 session_key 和 openid.其中 session_key 是对用户数据进行 ...
- laravel的工厂模式数据填充:
数据表post中的字段结构. database\factory\UserFactory.php $factory->define(App\Post::class,function (Faker ...
- laravel使用使用 Php Artisan Tinker 实现模型的增删改查
tinker命令: php artisan tinker 查阅数据库数据: App\User::count(); App\User::where('username', 'samuel')->f ...
- Spring Boot + Spring Cloud 实现权限管理系统 (集成 Shiro 框架)
Apache Shiro 优势特点 它是一个功能强大.灵活的,优秀开源的安全框架. 它可以处理身份验证.授权.企业会话管理和加密. 它易于使用和理解,相比Spring Security入门门槛低. 主 ...
- 过滤器 拦截器 登录login实例
当请求来的时候,首先经过拦截器/过滤器,在经过一系列拦截器/拦截器处理后,再由再根据URL找到Servlet.执行servlet中的代码. 过滤器:按照过滤的对象类型的不同,可分为按资源名过滤和按请求 ...
- [HDU4585]Shaolin
Problem 问你一个数的前驱和后继 Solution Treap模板题 Notice 注意输出那个人的编号 Code #include<cmath> #include<cstdi ...
- java-Object类的解析(持续更新)
1.getClass()方法 public class Object { /*一个本地方法,具体是用C(C++)在DLL中实现的,然后通过JNI调用*/ private static native v ...
- Mysql 数据库意向锁意义
锁:对 “某种范围” 的数据上 “某种锁”1.“某种范围”:行.表 2.“某种锁”2.1 共享锁Shared Locks(S锁)1.兼容性:加了S锁的记录,允许其他事务再加S锁,不允许其他事务再加X锁 ...
- SpringCloud调用服务示例
SpringCloud調用服務示例. SpringCloud简介: Spring Cloud是一系列框架的有序集合.它利用Spring Boot的开发便利性巧妙地简化了分布式系统基础设施的开发,如服务 ...
- 每天CSS学习之caption-side
caption-side是CSS2的属性,其作用是规定标题的位置在表格的上面还是下面. 1.top:默认值,将表格标题定位在表格之上.如下例子: caption{ caption-side:top; ...