C++实现图算法(二)

来源:互联网 发布:linux下svn服务器搭建 编辑:程序博客网 时间:2024/06/14 20:29

上次把图算法需要的顶点和边搞定了。

这次就把图的基本操作搞定,还是根据Mat的框架,自己动手写了一个。写的时候还发现Mat不小心留下的一个bug。

 

工程打包(VS2010)

 

这是整个图的完整代码:

 

 

先来看看类的成员变量和一些类型定义:

这里用到了向量(Vector)和链表(List)还有一个由链表组成的向量(Vecyot<List>)

 

类型的定义简化了代码,让我们看起来更加的直观。

下面紧跟着的是该类的几个重要数据成员:

点集NodeVectorm_Nodes和边集EdgeListVectorm_Edges;

点集用来存放所有的顶点,同时保证顶点的索引和顶点在点集中的下标对应。

边集用一个邻接链表表示。

其他数据我已经注释很清楚了,就不用在赘述了。

 

接下来是构造函数:

 

很简答,只需要一个参数用来标识该图是否是有向图。

几个Get函数便不再多费口舌。

下面是AddNode函数:

 

该函数需要一个node_type的值作为参数。函数第一步判断该点索引是否小于点集大小,如果小于则进一步检查该点插入到的位置是一个有效点还是一个无效点(因为删除操作是将一个点表示为无效),如果无效则可以插入并返回下一个可插入的顶点位置,否则出现错误;如果索引大于点集大小,说明是一个全新的点,则直接增加到点集的尾部,并对相应的边集进行初始化(不初始化后果很严重),然后返回下一个可插入的顶点位置。

 

下面是RemoveNode函数:

 

几乎一切数据结构,删除都是最烦人的。

函数首先将需要删除的点的索引置为无效(-1),然后分别对有向图和无向图进行删除相应边的操作。

无向图:

先从被删除顶点的邻接点开始找,一旦找到某个邻接点有和该点连接,则删除,一直找完所有邻接点,然后删除自己;(都在边集中操作)

有向图:

有向图调用了一个辅助内部函数进行暴力删除,也就是遍历整一个图,找到一个无效顶点,删除之。但是这里Mat犯了一个错误,这个错误当时让我崩溃了一段时间,最后还是给找到了,先看看mat写的:

 

杂言看真没什么错,可是一遇到某些特殊情况,就麻烦了!

问题主要在这句话:

 

调用erase删除一条边,这个是对的,但是这个是迭代器,删除算法会影响迭代器的,所以返回了下一个正确位置的迭代器这样等于是++curEdge,可是for循环在循环后有++了一次,这样一个删除就++了2次,如果到了end位置,++2次直接出错。所以,不可以++2次。

我于是改成了这样:

 

直接改用while循环,手动更新迭代器便可。

 

下面是AddEdge函数:

该函数比较简单,也分2种情况,无向图和有向图。如果是无向图,则自动增加一条反向边;有向图则不需要。

这个函数调用了一个辅助函数UniqueEdge,UniqueEdge用来判断边是否是已经增加过的。

 

UniqueEdge函数如下:

 

从边集下边为from(表示从from出发的边)开始遍历,一次比对to节点是否是传入的节点。没有找到,则说明边是唯一的,找到了,说明边已经增加过。

 

下面是RemoveEdge函数:

 

同样分有向图和无向图,对于有向图只需要遍历一次就可以删除完毕,无向图则需要多遍历一次以便删除反向边。

 

其他的几个函数一看便明。

该类还有一个比较特殊的地方,就是使用了类似stl中迭代器的设计。

定义了4个2组迭代器,分别对应边集的const和non-const迭代器,点集的const和non-const迭代器。

 

简单的使用方法:

 

 

以上内容若有不足之处,请告知于我,谢谢:)