【发布时间】:2013-10-23 22:42:38
【问题描述】:
我想知道如果我使用 BFS 的时间复杂度是多少:
- 邻接矩阵
- 邻接列表
- 边缘列表
和它们的空间复杂度一样吗?
【问题讨论】:
标签: data-structures graph graph-algorithm breadth-first-search
我想知道如果我使用 BFS 的时间复杂度是多少:
和它们的空间复杂度一样吗?
【问题讨论】:
标签: data-structures graph graph-algorithm breadth-first-search
使用邻接矩阵实现的 BFS 的复杂度为O(|V|²)。当由邻接列表实现时是O(|V| + |E|)。
为什么邻接矩阵的情况更多?
这主要是因为每次我们想要找到与给定顶点“U”相邻的边是什么时,我们都必须遍历整个数组AdjacencyMatrix[U],当然长度是|V|。
将 BFS 想象为前沿。你取一个起始顶点S,它在水平0。与S 相邻的所有顶点都将位于1 级别。然后,我们将级别1的所有顶点的所有相邻顶点标记为级别2。因此,每个顶点将只属于一个边界。这些边界中的每一个都对应于不同的层次。当一个元素在边界中时,我们检查一次它的相邻顶点,这需要O(|V|)时间。由于边界在算法过程中覆盖|V| 元素,因此总时间将变为O(|V| * |V|),即O(|V|²)。
通过邻接列表和矩阵实现 BFS 的复杂性差异是因为在邻接矩阵中,为了确定哪些节点与给定顶点相邻,我们需要 O(|V|) 时间,而与边的数量无关。而在邻接表中,边是我们立即可用的,因此它所花费的时间与相邻顶点的数量成正比,所有顶点的总和 |V|是|E|。所以,BFS by Adjacency List 给出 O(|V| + |E|)。
【讨论】:
时间复杂度必然取决于表示。
正如link 所暗示的那样,邻接列表的时间复杂度为 O(V + E),邻接矩阵的时间复杂度为 O(V2)。
【讨论】:
首先让我们看看时间复杂度。如果邻接矩阵可以存储为sparse matrix,则空间复杂度将是相同的。稀疏矩阵本质上只存储邻接矩阵的非零值,因此具有与邻接表表示相同的空间复杂度,即 O(|V| + |E|)
现在谈谈时间复杂度。进行 BFS 搜索的一种方法是简单地使用稀疏邻接矩阵,因为通常使用邻接列表表示,即 O(|V| + |E|)。
在邻接矩阵上进行 BFS 的另一种方法是通过重复应用 Y=G X 来使用稀疏矩阵向量乘法,其中 G 是稀疏邻接矩阵,X 是边界上为 1 的稀疏向量。此操作基本上是 G 的列的组合。如果执行此操作以使每次乘法所花费的时间与 G 的每一列中访问的数据大小和向量 X 中的非零数成正比,那么时间复杂度将为也是 O(|V| + |E|)。这种方法的一个优点是,通过将 X 替换为代表多个 BFS 搜索边界的稀疏矩阵,可以直接将其扩展到多个 BFS 搜索。有关使用稀疏矩阵实现图算法的更多详细信息,请参见 paper。
边列表通常不用于 BFS,因为查找顶点的邻居很昂贵。
【讨论】:
Graph 不同表示的时间复杂度:
1.边缘列表:
边缘列表由列表中的所有边缘组成。为了做到BFS时间复杂度为O(E^2)。因为对于每条边u->v,你必须遍历整个边列表并找到源顶点为u的边并探索它们,然后探索顶点'v ' 在 u->v 中执行 BFS。
其中
E是边数。
如果根据源索引和目标索引对边进行排序,则排序列表将按 BFS 顺序排列。只需遍历列表,即可获得 BFS。
对边列表进行排序的时间复杂度为O(E*log(E))。
2。邻接列表
邻接是一个键映射,其中每个顶点都是一个键,并指向与该键顶点相关或相邻的顶点列表。
为了执行 BFS,将任何顶点放入队列并使其成为已访问,弹出队列 [0],选择起始顶点,探索其所有相邻顶点,使其成为已访问并将它们放入队列中类似地弹出队列[0]并探索所有未访问的顶点,直到队列变空。对于每个顶点,您只遍历其相邻的未访问顶点(除了边之外什么都没有)。
所以,时间复杂度是O(V+E)
3.矩阵
在矩阵表示中,对于每一个顶点,你都要遍历所有的顶点,检查是否有未访问过的顶点。因为,对于每个顶点,我们都在遍历所有顶点,
时间复杂度为O(V^2)
【讨论】: