图实现 C++
我想知道如何用 C++ 快速编写图的实现。我需要数据结构易于操作和使用图算法(例如 BFS、DFS、Kruskal、Dijkstra...)。 我需要这个实现来参加算法奥林匹克竞赛,因此编写数据结构越容易越好。
你能建议这样的DS(主要结构或类以及其中的内容)吗?我知道邻接列表和邻接矩阵是主要的可能性,但我的意思是更详细的代码示例。
例如,我上次考虑过这个DS,我必须为DFS实现一个图:
struct Edge {
int start;
int end;
struct Edge* nextEdge;
}
然后使用一个大小为n的数组,在其第i个位置包含表示从第i个节点开始的边的边列表(struct Edge) 。
但是当尝试在此图上进行 DFS 时,我必须编写 50 行代码,其中包含大约 10 个 while 循环。
有哪些“好的”实现?
I was wondering about a quick to write implementation of a graph in c++. I need the data structure to be easy to manipulate and use graph algorithms(such as BFS,DFS, Kruskal, Dijkstra...).
I need this implementation for an algorithms Olympiad, so the easier to write the data structure the better.
Can you suggest such DS(main structs or classes and what will be in them). I know that an Adjacency list and Adjacency matrix are the main possibilities, but I mean a more detailed code sample.
For example I thought about this DS last time I had to implement a graph for DFS:
struct Edge {
int start;
int end;
struct Edge* nextEdge;
}
and then used a array of size n containing in its i'th place the Edge List(struct Edge) representing the edges starting in the i'th node.
but when trying to DFS on this graph I had to write a 50 line code with about 10 while loops.
What 'good' implementations are there?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
下面是 C++ 中图数据结构作为邻接表的实现。
我使用 STL 向量来表示顶点,并使用 STL 对来表示边和目标顶点。
Below is a implementation of Graph Data Structure in C++ as Adjacency List.
I have used STL vector for representation of vertices and STL pair for denoting edge and destination vertex.
这实际上取决于您需要实现什么算法,没有灵丹妙药(这不应该令人惊讶......编程的一般规则是没有一般规则;-))。
我经常最终使用带有指针的节点/边结构来表示有向多重图...更具体地说:
换句话说,每个节点都有一个传入链接的双向链表和一个传出链接的双向链表。每个链接都知道
from
和to
节点,并且同时位于两个不同的双向链表中:来自同一from< 的所有链接的列表/code> 节点以及到达同一
to
节点的所有链接的列表。当跟踪来自同一节点的所有链接链时,使用指针
prev_same_from
和next_same_from
;在管理指向同一节点的所有链接的链时,会使用指针prev_same_to
和next_same_to
。这是很多指针的摆弄(所以除非你喜欢指针,否则就忘记这一点),但是查询和更新操作是高效的;例如,添加节点或链接的时间复杂度为 O(1),删除链接的时间复杂度为 O(1),删除节点 x 的时间复杂度为 O(deg(x))。
当然,根据问题、有效负载大小、图形大小、图形密度,这种方法可能会过度杀伤或对内存要求过高(除了有效负载之外,每个节点有 4 个指针,每个链接有 6 个指针)。
类似结构的完整实现可以在此处找到。
It really depends on what algorithms you need to implement, there is no silver bullet (and that's shouldn't be a surprise... the general rule about programming is that there's no general rule ;-) ).
I often end up representing directed multigraphs using node/edge structures with pointers... more specifically:
In other words each node has a doubly-linked list of incoming links and a doubly-linked list of outgoing links. Each link knows
from
andto
nodes and is at the same time in two different doubly-linked lists: the list of all links coming out from the samefrom
node and the list of all links arriving at the sameto
node.The pointers
prev_same_from
andnext_same_from
are used when following the chain of all the links coming out from the same node; the pointersprev_same_to
andnext_same_to
are instead used when managing the chain of all the links pointing to the same node.It's a lot of pointer twiddling (so unless you love pointers just forget about this) but query and update operations are efficient; for example adding a node or a link is O(1), removing a link is O(1) and removing a node x is O(deg(x)).
Of course depending on the problem, payload size, graph size, graph density this approach can be way overkilling or too much demanding for memory (in addition to payload you've 4 pointers per node and 6 pointers per link).
A similar structure full implementation can be found here.
这个问题很古老,但出于某种原因,我似乎无法将其从脑海中抹去。
虽然所有解决方案都提供了图形的实现,但它们也都非常冗长。他们根本不优雅。
您真正需要的不是发明自己的图形类,而是一种告诉一个点连接到另一个点的方法 - 为此,
std::map
和std::unordered_map
工作得很好。简而言之,将图定义为节点和边列表之间的映射。如果您不需要边缘上的额外数据,则端节点列表就可以了。因此,C++ 中的简洁图形可以像这样实现:
或者,如果您需要额外的数据,
现在您的图形结构将很好地插入语言的其余部分,并且您不必记住任何新的笨重接口 - 旧的笨重的界面就可以了。
没有基准,但我有一种感觉,这也将优于这里的其他建议。
注意:
int
不是索引——它们是标识符。This question is ancient but for some reason I can't seem to get it out of my mind.
While all of the solutions do provide an implementation of graphs, they are also all very verbose. They are simply not elegant.
Instead of inventing your own graph class all you really need is a way to tell that one point is connected to another -- for that,
std::map
andstd::unordered_map
work perfectly fine. Simply, define a graph as a map between nodes and lists of edges. If you don't need extra data on the edge, a list of end nodes will do just fine.Thus a succinct graph in C++, could be implemented like so:
Or, if you need additional data,
Now your graph structure will plug nicely into the rest of the language and you don't have to remember any new clunky interface -- the old clunky interface will do just fine.
No benchmarks, but I have a feeling this will also outperform the other suggestions here.
NB: the
int
s are not indices -- they are identifiers.最常见的表示可能是这两种:
邻接列表
邻接矩阵
这两个中的邻接矩阵是最简单的,只要你不介意有一个(可能很大)
n * n
数组,其中n
是顶点。根据数组的基本类型,您甚至可以存储边权重以用于最短路径发现算法等。The most common representations are probably these two:
Adjacency list
Adjacency matrix
Of these two the adjacency matrix is the simplest, as long as you don't mind having a (possibly huge)
n * n
array, wheren
is the number of vertices. Depending on the base type of the array, you can even store edge weights for use in e.g. shortest path discovery algorithms.我更喜欢使用索引(而不是指针)的邻接列表
I prefer using an adjacency list of Indices ( not pointers )
可以有一种更简单的表示,假设人们必须只测试图算法而不是在其他地方使用它们(图)。这可以作为从顶点到其邻接列表的映射,如下所示:-
There can be an even simpler representation assuming that one has to only test graph algorithms not use them(graph) else where. This can be as a map from vertices to their adjacency lists as shown below :-
这是图的基本实现。
注意:我使用链接到下一个顶点的顶点。每个顶点都有一个指向相邻节点的列表。
通过上面的代码,你可以扩展做DFS/BFS等。
Here is a basic implementation of a graph.
Note: I use vertex which is chained to next vertex. And each vertex has a list pointing to adjacent nodes.
With the above code, you can expand to do DFS/BFS etc.