C++ 解析输入文件以创建有向图C++;

C++ 解析输入文件以创建有向图C++;,c++,parsing,graph,graph-algorithm,topological-sort,C++,Parsing,Graph,Graph Algorithm,Topological Sort,所以我开始了一个关于有向图和拓扑排序的项目。我正在寻找解析表单中课程输入文件的最有效方法: COURSE_1 COURSE_2 其中课程1是课程2的先决条件 NONE COURSE_3 课程3没有任何先决条件 显然,所有顶点标签都是字符串。我创建了一个包含数据成员的Graph类,用于存储顶点、边和顶点标签。稍后,我将添加方法进行拓扑排序,并找到从一个顶点到另一个顶点的最短路径。考虑到这些未来的计划,我的问题是使用邻接列表是否更好?还是矩阵?另外,从输入文件填充图形的最有效

所以我开始了一个关于有向图和拓扑排序的项目。我正在寻找解析表单中课程输入文件的最有效方法:

COURSE_1    COURSE_2    
其中课程1是课程2的先决条件

NONE    COURSE_3
课程3没有任何先决条件

显然,所有顶点标签都是字符串。我创建了一个包含数据成员的
Graph
类,用于存储顶点、边和顶点标签。稍后,我将添加方法进行拓扑排序,并找到从一个顶点到另一个顶点的最短路径。考虑到这些未来的计划,我的问题是使用邻接列表是否更好?还是矩阵?另外,从输入文件填充图形的最有效方法是什么?我最初的想法是使用邻接列表。由于图形的大小在编译时是未知的,我的想法是

std::vector<std::list<std::string>> adjacencyList;

我是不是走错方向了

关于邻接列表和矩阵之间的选择,这取决于图形的性质以及您打算如何使用它

看看这个例子

另外,您有没有看一下库中提供了哪些图形? 还有一种选择。
如果您打算实现的内容已经存在,那么可能值得检查。

您在很多方面都是正确的

如果您可以假设您将遇到的所有输入都是
NONE
COURSE_X
,并且您可以假设所有X形成一个连续的整数间隔,从1(或0)开始并延伸到顶点数,那么您可以在内部将顶点视为数字。如果不是这样,您可以为每个顶点标签指定一个数字(例如使用std::unordered_map)并具有这种抽象结构

现在,如果您选择使用此模型,则使用起来很方便,因为您的整个图形可以表示为
std::vector
。如果要存储有关边的更多信息,如标签、权重等,可以使用某种结构类型替换
int
。每当要访问特定节点的邻接列表时,只需访问节点id下的向量单元即可

显然,这是一个基于邻接列表的解决方案。一般来说,它适用于稀疏图。可以这样想:如果你对稀疏图使用一个矩阵,那么分配的内存中很大一部分将不会被使用。使用邻接图消除了这一点,但它消除了对任意边的恒定访问时间。这意味着检查给定边是否存在可能需要线性时间。也就是说,我不希望你在拓扑排序中使用这个检查。但是,如果选择使用矩阵,则仍然需要将顶点映射到数字,映射到该零件


最后但并非最不重要的一点是,您可以使用指针而不是整数ID。基本上,您不会使用id查找向量中的顶点,但可以通过存储的指针直接访问vertice。您很可能仍然需要字符串->指针映射,至少在创建图形时是这样。

如果要定义输入文件,您可能希望在文件顶部定义顶点的数量,以便可以一次性分配构建数据结构所需的内存,而不是在读取文件时让它们增长。您可能不应该使用std::list,除非您希望插入的次数比读取的次数多得多。@MustafaOzturk我没有定义输入文件。我曾想过使用
std::list
,因为邻接列表会随着输入文件的处理而增长。这对我来说似乎是过早的优化。矩阵可以工作,邻接列表或节点链接网络也可以工作。向量是好的,列表和地图也是好的。首先让代码工作起来,然后看看它执行得有多好,并决定哪个操作会让你慢下来;如果您正在使用标准容器并实践良好的封装,那么更改实现比您想象的要容易得多。
void populateGraph(std::string filename, Graph* graph)