我首先要在节点类之外声明边缘类。在这种情况下,我看不出将其设为嵌套类有什么好处。实际上,一般来说,嵌套类带来的弊大于利。 This 问题对原因有很好的解释。
至于图形类的设计,我建议使用一个模板参数来表示有效负载(您可能希望图形节点携带的任何任意数据类型),并使用第二个模板参数来表示权重(任何数值,如int、float、double、long等)。
某些图表用例可能不关心图表是否加权,因此在这些情况下,您可以忽略权重字段,并且不要使用它(将其保留为某个默认值,例如 0,将是好习惯)。我还建议使用std::list 而不是std::vector 来保存节点,这样如果您需要向图中添加许多节点,就不会发生内存重新分配。
考虑到上述情况,图形类将如下所示。请注意,我将D 用于数据字段(有效负载),W 用于权重字段。
DirectedGraph.h
template <class D, class W> class DirectedGraph{
public:
DirectedGraph(){/*...*/}
~DirectedGraph(){/*...*/}
/*Pushes a node into this graph, which will have no connections initially.*/
void push(GraphNode<D, W> *node){/*...*/}
/*Erases a node from this graph.*/
void erase(GraphNode<D, W> *node){/*...*/}
std::list<GraphNode<D, W>> &getNodes(){/*...*/}
private:
/*This is the master list holding all nodes of this graph.*/
std::list<GraphNode<D, W>> nodes;
};
节点和边(我称之为“邻居”)类将如下所示:
GraphNode.h
/*Forward declaration of the edge structure (see below).*/
template <class D, class W> struct Neighbor;
template <class D, class W> struct GraphNode{
public:
GraphNode(D data) : data(data) {}
~GraphNode(){}
/*Some data this node element will hold*/
D data;
/*Adds an outgoing connection.*/
void addConnection(Neighbor<D, W> neighbor){ /*...*/}
/*You may also want to develop a 'removeConnectoin' method here.*/
/*...*/
/*Nodes that this one is connected to. Since this actually represents
a connection (an edge), the struct 'Neighbor' is used, which encapsulates
a pointer to a 'GraphNode' as well as the weight of the edge.*/
std::list<Neighbor<D, W>> neighbors;
/*Nodes that connect to this one. These are the incoming connections. Note
that this is not of type 'Neighbor' because it does not represente an edge.
It is just a record of which nodes have an outgoing connection to this one.*/
std::list<GraphNode<D, W>*> parents;
};
/*This struct represents an edge*/
template <class D, class W> struct Neighbor{
Neighbor<D, W>(GraphNode<D, W> *node, W weight) : node(node), weight(weight){}
GraphNode<D, W> *node;
W weight;
};
这里需要注意的一点是,使用 Neighbor 类的唯一原因是我们可以表示边缘的权重。如果您要使用的图表始终未加权,您可以将Neighbor<D, W> 的std::list 替换为GraphNode<D, W>* 的std::list。您还可以从您的实现中删除模板参数W。
哦,当然,图形头文件必须包含节点一。
我希望这是一个好的起点。有任何问题,请告诉我。