第七十七课 最小生成树(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算法+并查集数据结构
并查集:找祖先并更新,注意路径压缩,不然会时间复杂度巨大导致出错/超时 合并:(我的祖先是的你的祖先的父亲) 找父亲:(初始化祖先是自己的,自己就是祖先) 查询:(我们是不是同一祖先) 路径压缩:(每 ...
随机推荐
- HTML 5 <span> 标签
标签定义及使用说明 <span> 用于对文档中的行内元素进行组合. <span> 标签没有固定的格式表现.当对它应用样式时,它才会产生视觉上的变化.如果不对 <span& ...
- [洛谷 P1559] 运动员最佳匹配问题
题目描述 羽毛球队有男女运动员各n人.给定2 个n×n矩阵P和Q.P[i][j]是男运动员i和女运动员j配对组成混合双打的男运动员竞赛优势:Q[i][j]是女运动员i和男运动员j配合的女运动员竞赛优势 ...
- eclipse安装springboot插件
1.工具栏->Help->Eclise Marketplace打开应用市场 2.在应用市场中搜索sts,选择Spring Tools 4紧张安装 3.按提示进行安装
- angular组件之间的通讯
组件通讯,意在不同的指令和组件之间共享信息.如何在两个多个组件之间共享信息呢. 最近在项目上,组件跟组件之间可能是父子关系,兄弟关系,爷孙关系都有.....我也找找了很多关于组件之间通讯的方法,不同的 ...
- EXCEL词典(xllex.dll)文件丢失或损坏解决方法
EXCEL词典(xllex.dll)文件丢失或损坏解决方法 1● 问题 2● 解决 fail 3● 方法2 regsvr32 xllex.dll 4● 方法3 启动server ...
- Spring boot异常统一处理方法:@ControllerAdvice注解的使用、全局异常捕获、自定义异常捕获
一.全局异常 1.首先创建异常处理包和类 2.使用@ControllerAdvice注解,全局捕获异常类,只要作用在@RequestMapping上,所有的异常都会被捕获 package com.ex ...
- python 转换代码格式
import os dirname="C:\\Users\\haier\\Desktop\\new" def walk(path): for item in os.listdir( ...
- linux的命令:
uname -r linux的版本号 uname -a 显示系统名.节点名称.操作系统的发行版号.操作系统版本.运行系统的机器 ID 号 cd /dev/ 切换到根目录: ls 查看根目录文件
- jquery checkbox的使用
获取单个checkbox选中的写法: $('input:checkbox:checked').val(); $("input:[type='checkbox']:checked") ...
- TTL特殊门电路
集电极开路(OC)门:主要作用实现线与功能:用做驱动器:实现电平转换 三态输出(TS)门:应用于计算机总线结构,通过分时控制三态门始轮端使得cpu与不同的外设通信:应用于双向传输,实现门电路与总线实现 ...