通常用于在内存中表示图形的两种方法是使用邻接列表或邻接矩阵。使用指向链表的指针数组实现邻接列表。有没有什么理由比使用矢量矢量更快?我觉得它应该使搜索和遍历更快,因为回溯会更简单。
答案 0 :(得分:1)
链接邻接的向量是最受欢迎的教科书模因,在实践中有许多变化。当然你可以使用矢量矢量。有什么区别?
一个是链接(无论如何都是双链接)允许在恒定时间内轻松添加和删除边。这显然只有在边缘集缩小和增长时才是重要的。对于边缘矢量,任何单独的操作都可能需要O(k),其中k是入射边缘计数。
注意:如果邻接列表中边缘的 order 对于您的应用程序而言并不重要,则可以轻松地使用向量进行O(1)删除。只需将最后一个元素复制到要删除的元素的位置,然后删除最后一个元素!唉,当邻接的顺序很重要时,有很多情况(例如,你担心嵌入飞机)。
即使必须维持订单,您也可以安排复制成本以分摊到多次操作的每次操作的平均值O(1)。仍然在某些应用中,这还不够好,并且它需要“删除”标记(保留顶点数量就足够了),只有当标记删除的数量是向量的固定部分时才执行压缩。代码很繁琐,在所有操作中检查已删除的节点会增加开销。
另一个区别是开销空间。邻接列表节点非常小:只是一个节点号。双链路可能需要4倍于数字本身的空间(如果数字是32位,两个指针都是64)。对于一个非常大的图形,400%的空间开销并不是那么好。
最后,经常长时间编辑的链接数据结构很容易导致高度不连续的内存访问。与通过向量的线性访问相比,这降低了缓存性能。所以这里的矢量获胜。
在大多数应用程序中,差异并不值得担心。然后,巨大的图形是现代世界的方式。
正如其他人所说的那样,最好为邻接使用通用的List容器,可以通过链接节点或节点向量快速实现。例如。在Java中,您使用List
并使用LinkedList
和ArrayList
实现/配置文件,以查看哪种方法最适合您的应用程序。 NB ArrayList
会压缩每个remove
上的数组。尽管add
已摊销,但上述情况并无摊销。
还有其他变化:假设您有一个非常密集的图形,其中经常需要搜索具有特定标签的一个给定节点的所有边缘。然后你想要邻接的 maps ,其中键是边缘标签。当然,地图可以是哈希,树木或跳棋或任何你喜欢的地图。
列表还在继续。如何实现有效的顶点删除?正如您所料,这里也有其他选择,每种都有优点和缺点。