我正在研究一些关于如何为向量构建一个合适的构造函数的例子,我仍然对如何实际实现它感到困惑。使用给定的类......
class Graph
{
private:
class Edge
{
public:
Edge(string vertex, int weight)
{
m_vertex = vertex;
m_weight = weight;
}
~Edge(){}
string m_vertex;
int m_weight;
};
vector< list<Edge> > adjList; //vector of lists
public:
Graph();
~Graph();
vector < list < Edge > > get_adjList(){return adjList;}
//Other functions....
};
我仍然不确定在构造函数中放入什么Graph::Graph()
我尝试过做一些事情,例如
Graph::Graph()
{
new vector < list < Edge > >;
}
但我被告知这会导致内存泄漏。我以前只为链表制作了构造函数,直到现在才需要向量。我可以清楚地说明如何为列表向量创建构造函数。我需要构造函数,所以我可以访问其他文件中的adjList(列表的向量),以便复制它。
答案 0 :(得分:3)
Graph
构建vector< list< Edge > > adjList
时,Graph
已经有一个成员new
可供您分配和构建。您不需要编写任何进一步的构造函数。
此处对Graph::Graph()
{
new vector < list < Edge > >; // DELETE THIS LINE
}
的调用可以完全删除:
vector< list< Edge > >
就目前而言,它分配一个完全独立的new
,然后抛弃adjList
返回的指针。但是,从各方面来看,无论如何你都不需要它。您的new
成员已经在那里,空着并等待数据。您无需致电adjList
或其他任何内容。
您做需要的是填充Graph::Graph()
成员的某种方式。您可以在get_adjList()
或外部代码中执行此操作。
您当前的getter函数adjList
当前返回vector < list < Edge > >& get_adjList() {return adjList;}
的副本,而不是引用。您可以考虑更改该方法以返回引用:
vector < list < Edge > >* get_adjList() {return &adjList;}
或指针:
get_adjList()
以便类外的代码可以调用Graph my_graph;
vector< list<Edge> >& adjList = my_graph.get_adjList();
// Make a graph with two nodes, both pointing at each other, with weight 10
adjList.resize( 2 ); // make room for two nodes
adjList[0].push_back( Edge( 1, 10 ) );
adjList[1].push_back( Edge( 0, 10 ) );
然后操作类中的字段。
这样的事情:
vector< list<Edge> >
要防止手指一遍又一遍地输入typedef
,您可以在class Graph
内添加class Graph
{
public:
typedef vector< list< Edge > > adj_type;
// ...
};
:
Graph::adj_type& adjList = my_graph.get_adjList();
然后在外面,你可以这样说:
adj_type
如果您稍后更改代码,那么还会将其余代码与Graph
的确切定义隔离开来。
您最终应考虑向class Graph
{
//...
public:
void add_vertex( unsigned id )
{
if (id > adjList.size() )
adjList.resize( id );
}
void add_edge( unsigned from_id, unsigned to_id, int weight )
{
adjList[fromId].push_back( Edge( to_id, weight ) );
}
}
添加方法以添加顶点和边。类似的东西:
m_vertext
未经测试的代码,但您希望得到这个想法。
最后一个想法:Edge
为什么map< string, list<Edge> >
中有一个字符串?我刚注意到这一点,看起来很奇怪。
如果您的顶点是非数字的,那么您应该考虑使用vector
代替adjList
map<string, unsigned>
。或者添加{{1}}以将字符串映射到ID。否则,您将无法有效地将边缘追逐到顶点。
答案 1 :(得分:0)
如果您创建new
的实例(这不是Java),则不需要使用adjList
,vector
已经是堆栈上的Graph
变量我认为默认的矢量构造函数就足够了,不需要明确地调用它。仅当您的变量是指针时才需要调用new
。
但您可能需要将get_adjList
的返回类型更改为仅返回adjList
的引用,而不是adjList
的新副本。
class Graph
{
private:
vector<list<Edge> > adjList; //vector of lists
public:
Graph();
~Graph();
vector<list<Edge> > &get_adjList(){return adjList;}
};
或者如果您需要的是vector
元素,最好不要返回vector
,只需根据查询索引返回元素,例如:
list<Edge> &get_adjListElmt(int idx){return adjList[idx];}
答案 2 :(得分:0)
如果您的图表类可以从文件中读取,那么该类的构造函数可能类似于:
Graph::Graph(istream &iss)
{
// number of vertices in the graph
// where each vertex has a list of edges
size_t vertices;
iss >> vertices;
adjList.resize(vertices);
...
}
除了设置向量的大小之外,不需要为向量动态分配空间,除非您将向量声明为类中的指针。
现在,为了获取向量的访问权限,您可以在类中创建一个getter方法,该方法返回向量的副本(如果您不希望对原始文件进行变异),或者getter可以返回一个引用/指针到实际的对象
我前后实现了一个图表类,您可能想要查看的另一个选项是可以创建给定density
,maxedgeLength
和numberofvertices
的随机图形对象的构造函数
答案 3 :(得分:0)
我同意@ joe-z。但是,我认为问题可能是他需要一定大小的矢量。
struct Edge { // you could template this to make more generic.
int v2;
double weight;
};
class Graph {
public:
Graph(size_t size) : m_adj_list(size) {}
void AddEdge(int v1, int v2, double weight) {
m_adj_list[v1].emplace_back(v2, weight);
}
void Resize(size_t size) {
m_adj_list.resize(size, std::vector<Edge>());
}
private:
// You can use a list but in general a vector might be a better choice
std::vector<std::vector<Edge>> m_adj_list;
};
另外。不要只使用裸指针。使用std :: unique_ptr或std :: shared_ptr。通常,您可以使用规则(按此顺序):