我正在尝试使用向量数组来实现图形。我这样做非常困难。向量将保持顶点v附近的顶点,顶点v是名为uvertices的数组的索引。
这是我到目前为止所做的。
class Graph {
public:
int V; //this will represent the number of vertices in the graph
std::vector<int>* vertices;
Graph(int V) {
vertices = new std::vector<int>[V];
}
在这里,我创建了(或者想要并且意味着创建了)一个大小为V的ARRAY(V是图中的顶点数),它保存了向量。然后我希望能够创建边缘,所以我有
void Graph::insert_edge(int v, int u) {
}
作为一种方法。我想将值u推入到包含顶点v的邻接列表的向量中。我的向量数组的每个索引(名为顶点)表示图中每个顶点v的标识符。所以我想做一些像
这样的事情 vertices[v].push_back(u);
当我输入顶点[v]时,我很惊讶地发现,Intellisense给了我一个可能的函数列表,包括push_back。我感到惊讶的原因是因为我实际上没有创建任何向量,但我就这样离开了它。这显然不起作用,所以我开始调试,我意识到每当我第一次调用insert_edge时,它就会告诉我数组的大小和容量&#34; vertices&#34;是0.尽管我创建了我的图形数据结构
Graph G(8);
我花了大约两个小时试图弄清楚如何使用它,我只是没有成功。
如何设置,以便在插入边时,我可以查看顶点数组中的正确索引v,并访问该数组索引所持有的向量的push_back函数,以便我可以添加将顶点u转换为顶点v的邻接列表。
另外,我真的真的恳求如果人们给我投票或投票结束我的话题,请告诉我原因。花时间把所有这些都写下来并确保它写得很清楚而没有人甚至告诉我他们为什么要投票给我,这可能会非常令人沮丧。
答案 0 :(得分:2)
我认为你应该仔细考虑你选择的数据结构。在图/算法社区中,图的两个标准表示是邻接列表或邻接矩阵。参见例如 Standard graph representations
请激励你为什么使用std :: vector,并重新提问。链接列表(如在邻接列表表示中)使得删除边缘比使用矢量表示更有效。邻接矩阵也是如此。
答案 1 :(得分:2)
当我输入顶点[v]时,我很惊讶地发现,Intellisense给了我一个可能的函数列表,包括push_back。我感到惊讶的原因是因为我实际上没有创建任何矢量。
这不应该是令人惊讶的。动态数组在运行时和intellisense中分配,而所有其他静态分析器都不会运行代码,因此它们永远不会知道变量在运行时的状态。 Intellisense知道vertices[v]
的类型是std::vector<int>
,它知道该类型的成员函数。
但你也不应该感到惊讶,因为你确实创造了矢量。在Graph
。
我意识到每当我第一次调用insert_edge时,它就会告诉我数组的大小和容量&#34; vertices&#34;是0.
这里有一个误解。 vertices
是一个指针。在构造函数运行之后,它指向一个内存块,该内存块是V
个std::vector<int>
实例的动态数组。 vertices
没有size
或capacity
这样的成员。构造完成后,动态数组中的每个std::vector<int>
都为空。直到你推入顶点。
这显然不起作用。
您的insert_edge
似乎工作正常。但是你确实有泄漏内存的问题(除非你有一个你没有显示的正确的析构函数)以及错误的拷贝构造函数和拷贝赋值运算符的问题(不遵循三条规则......除非你&# 39;已完成但未显示)。您可以通过使用向量向量而不是手动管理内存来解决这两个问题。
如何设置,以便在插入边时,我可以查看顶点数组中的正确索引v,并访问该数组索引所持有的向量的push_back函数,以便我可以添加将顶点u转换为顶点v的邻接列表。
你已经明白了:
vertices[v].push_back(u);
对于矢量矢量,相同的语法也是正确的。
您也从未设置Graph::V
,但如果您使用向量向量,则首先不再需要它,因为可以使用vertices.size()
访问它。