一、功能描述
通过在控制台界面输入已有数据文件的名称,读取数据文件内容并建立图结构,进而利用fastQ算法对所得图进行社团检测,得到并输出最优划分方式。
二、设计
1. 数据类型的设计和说明
数据类型为一个结点无权,但边可赋权值并允许自回路的无向图:
① 边赋权:随着社团的合并,社团数量减少,社团间会出现大量平行边,在BGL里邻接矩阵的存储方式不支持平行边,所以改而采用边的权重增加的方式体现平行边的存在。
② 自回路:随着合并,社团内部的结点之间会有边相连,为了体现这种边的存在,采用了自回路等效表示的方法。同样,也是通过给自回路赋权来体现平行边的概念。
③ 无向:在该程序中,fastQ算法所讨论的图均无方向。如果数据文件出现重复数据,程序运行过程中会自动忽略。
④ 结点无权:因为是无向图并且已经用自回路赋权的方式表示社团内部结点之间的边,所以结点无需赋权。
2. 关键算法的设计
算法分为以下几步:
⑴ 准备工作:
① 浏览文件内容,得到结点数目n和边的数目m;
② 建立具有n个结点的图;
③ 读取文件内容,并同时为图逐条添加边(包括边权值初始化);
⑵ 图操作:
① 穷举所有社团两两合并的情况,计算使得ΔQ最大的合并方式;
② 记录最佳合并方式(在数组order内),对①所得的ΔQ最大值做累计;
③ 根据最佳合并方式更新图,对图的边进行修改;
④ 重复第①步,直到所有社团合并为一个社团;
⑶ 输出划分结果:
① 找到使得ΔQ的累加值最大的位置;
② 根据①中所得最大位置,从order中读取相应数量的数据,对社团编号进行归组;
3. 模块结构图及各模块的功能
关键在于图的合并过程:
for(jNghbrVrtx=adjacent_vertices(*j,ug);jNghbrVrtx.first!=jNghbrVrtx.second;++jNghbrVrtx.first)
{
i2jNghbrEdge=edge(*i,*jNghbrVrtx.first,ug);
double i2jNghbrEdgeWeight=get(edge_weight_t(),ug,i2jNghbrEdge.first);
j2jNghbrEdge=edge(*j,*jNghbrVrtx.first,ug);
double j2jNghbrEdgeWeight=get(edge_weight_t(),ug,j2jNghbrEdge.first);
remove_edge(*i,*jNghbrVrtx.first,ug);
if(*jNghbrVrtx.first!=*i)
{
remove_edge(*i,*jNghbrVrtx.first,ug);
add_edge(*i,*jNghbrVrtx.first,i2jNghbrEdgeWeight+j2jNghbrEdgeWeight,ug);
}
else
{
j2jEdge=edge(*j,*j,ug);
double j2jEdgeWeight=get(edge_weight_t(),ug,j2jEdge.first);
remove_edge(*i,*jNghbrVrtx.first,ug);
add_edge(*i,*i,i2jNghbrEdgeWeight+j2jNghbrEdgeWeight+j2jEdgeWeight,ug);
}
}
下面就把代码贴出来,主要是一个main,三个头文件:
main.cpp
#include"getDeltaQ.h"
#include"combineIJ.h"
#include"tip.h"
#include<vector>
#include<string>
#include<math.h>
#include<fstream>
#include<iostream>
#include<boost\graph\graph_utility.hpp>//为了调用 print_vertices()和print_edges()
#include<boost\graph\adjacency_matrix.hpp>
using namespace std;
using namespace boost;
//边的权重属性类型---边有权,权重为double类型
typedef property<edge_weight_t,double> edgeWeightProperty;
//无向图中的结点类型:无向图、结点无权、边有权,图无权【是否允许平行边的概念只在邻接表里面有,邻接矩阵忽略此参数】
typedef adjacency_matrix<undirectedS,no_property,edgeWeightProperty> UGraph;
//边迭代器类型
typedef graph_traits<UGraph>::edge_iterator edge_iter;
//结点迭代器类型
typedef graph_traits<UGraph>::vertex_iterator vertex_iter;
//边的描述符类型
typedef graph_traits<UGraph>::edge_descriptor edge_dscr;
//入边迭代器类型
typedef graph_traits<UGraph>::in_edge_iterator in_edge_iter;
int main(int,char*[])
{
/****************************************************************************/
//****************************************
//* *
//* 构 造 图 *
//*