我正在使用邻接列表表示。
基本上
A:[B,C,D] means A is connected to B,C and D
现在我正在尝试添加一个方法(在python中)以在图中添加边缘。
但在我添加优势之前。我想检查两条边是否连接。 所以例如我想在两个节点D和A之间添加一个边(不知道A和D连接的事实)。
因此,由于哈希/字典中没有键“D”,它将返回false。
现在,非常天真,我可以检查D和A,然后检查A和D ......但那非常粗暴。 或者每当我连接两个节点时,我总是可以复制..
即连接A和E时..答:[E]创建E:[A]
但这不太节省空间。
基本上我想让这个图表方向独立。
是否有任何数据结构可以帮助我解决这个问题。
我希望我的问题有道理。
答案 0 :(得分:3)
对于无向图,您可以使用一个简单的边列表来存储所有边对。这样可以节省空间并降低性能,但是你应该知道你不能同时拥有两者,所以你总是要做出权衡。
否则你可以使用三角邻接矩阵但是,为了避免浪费一半的空间,你必须以特定的方式存储它(通过开发一种有效的方法来检索边缘存在而不浪费空间)。你确定这是值得的吗,这不仅仅是过早的优化吗?
邻接列表大多数都很好,即使你必须将每个无向边存储两次,你的图表有多大?
请看一下我的回答:Graph representation benchmarking,这样您就可以选择自己喜欢的答案了。
答案 1 :(得分:1)
你已经遇到了经典的空间与时间的权衡。
正如您所说,如果您没有找到D-> A,您可以搜索A-> D。这将导致最多两倍的执行时间。或者,当插入A-> D时,也创建D-> A,但这是以额外空间为代价的。
最糟糕的情况是,对于时间权衡,您将进行2次查找,这仍然是O(N)(具有更好的数据结构的速度更快)。对于空间权衡,您将(在最坏的情况下)在每组节点之间创建一个大致为O(N ^ 2)的链路。因此,我只会进行2次查找。
答案 2 :(得分:1)
假设每个contains()
方法非常广泛,并且您希望避免不惜一切代价执行这些操作,可以使用 bloom filter ,并检查是否存在边缘 - 这样就减少了contains()
个电话的数量。
这个想法是:每个节点都将拥有自己的布隆过滤器,它将指示哪些边连接到它。检查布隆过滤器非常简单且便宜,并且在添加边缘时也可以对其进行修改。
如果您检查了布隆过滤器 - 并且它说“不” - 您可以安全地添加边缘 - 它不存在。
但是,布隆过滤器有误报 - 所以,如果布隆过滤器说“边缘存在” - 你必须检查列表是否确实存在。
注意:
(1)如果使用布隆过滤器,去除边缘将是一个问题。
(2)Bloom过滤器为您提供了良好的时间/空间权衡 - 随着过滤器大小的增加,误报的数量减少。
(3)然而,当边缘确实存在时 - 无论过滤器的大小是多少,你都必须使用contains()
方法。
答案 3 :(得分:0)
假设您的节点名称可以进行比较,您可以简单地存储边缘,以便第一个端点小于第二个端点。然后,您只需执行一次查找。这肯定适用于字符串。