C++模板图类,递归
C++ Template Graph Class, Recursion
我正在尝试用C++编写一个图类,实现为邻接列表。我正试图使这个类成为一个模板,这样节点和边就可以包含任意的有效负载。这是一个简单的想法,但我对语言如何支持这一点感到困惑。
我希望能够如下声明一个图:graph<int, int>
或graph<string,double>
等
第一个想法,从图形声明向后工作:
template<class ntype, class etype>
class node {
class edge {
etype payload;
node<ntype, etype>* to;
node<ntype, etype>* from;
}
ntype payload;
vector< edge<> > incoming; // How to avoid recursion ???
vector< edge<> > outgoing; // ????
}
template<class ntype, class etype>
class graph {
vector< node<ntype, etype> > nodes;
}
我对所涉及的递归、模板参数的范围等感到非常困惑。我试过研究嵌套类、typename与template以及其他问题,但这并没有让它变得更清楚。现在看来,C和void指针是编写代码的最佳方式。如有任何帮助或参考,我们将不胜感激。
我首先在节点类之外声明边缘类。在这种情况下,我看不出将其作为嵌套类有什么好处。实际上,通常情况下,嵌套类带来的缺点多于优点。这个问题很好地解释了为什么。
至于图类的设计,我建议使用一个模板参数来表示有效载荷(您可能希望图节点携带的任何任意数据类型),并使用第二个模板参数表示权重(任何数值,如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
。
哦,当然,图形头文件必须包括节点一。
我希望这是一个良好的开端。有任何问题,请告诉我。
- 通过递归进行因子分解
- 递归函数计算序列中的平方和(并输出过程)
- 使用递归的数组的最小值.这是怎么回事
- 递归列出所有目录中的C++与Python与Ruby的性能
- 递归计数给定目录的文件和所有目录
- 如何在BST的这个简单递归实现中消除警告
- C++:正在检查LinkedList中的回文-递归方法-错误
- 递归模板化函数不能分配给具有常量限定类型"const tt &"的变量"state"
- 递归无序映射
- TSP递归解的迭代形式
- 如何在Elixir中调用递归函数并行
- 返回递归调用和仅递归调用的区别
- 数组元素打印的递归方法
- 使用递归时获取变量的奇怪值
- 如何在C++中递归地按相反顺序打印集合
- 到连接组件算法的问题(递归)
- 如何使用递归打印修改后的星号三角形图案
- 使用递归模板动态分配的多维数组
- 递归函数有效,但无法记忆
- 包含模板文件的递归会导致编译失败