Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Algorithm 改进的BFS时间复杂度_Algorithm_Graph Theory_Graph Algorithm_Breadth First Search - Fatal编程技术网

Algorithm 改进的BFS时间复杂度

Algorithm 改进的BFS时间复杂度,algorithm,graph-theory,graph-algorithm,breadth-first-search,Algorithm,Graph Theory,Graph Algorithm,Breadth First Search,因此,当按照以下方式实现队列时,BFS的复杂性为O(| V |+| E |): ENQUEUE(Q,source_vertex) while Q != NULL u=DEQUEUE(Q) for each v in AdjacencyList[u] if v not yet visited Make v visited ENQUEUE(Q,v) 如果我修改代码将u的邻接列表中的所有顶点添加到队列中,如下所示: ENQUEUE(Q,sourc

因此,当按照以下方式实现队列时,BFS的复杂性为O(| V |+| E |):

ENQUEUE(Q,source_vertex)
while Q != NULL
   u=DEQUEUE(Q)
   for each v in AdjacencyList[u]
     if v not yet visited
        Make v visited
        ENQUEUE(Q,v)
如果我修改代码将u的邻接列表中的所有顶点添加到队列中,如下所示:

ENQUEUE(Q,source_vertex)
while Q != NULL
   u=DEQUEUE(Q)
   for each v in AdjacencyList[u]
      if v not finalized            
         ENQUEUE(Q,v)
   make u finalized
运行时间是否仍为O(| V |+| E |)


提前感谢。

据我所知,运行时复杂性也是
O(|V|+|E|)
。第二个版本只是将最终确定步骤(也可以称为访问)推迟到下一个迭代;递归调用的数量和顶点的顺序都没有改变。

假设您有一个由n个节点组成的团体(让我们将它们编号为1、2、…、n,并假设邻接列表按此顺序存储它们),然后从节点1开始运行修改后的算法。节点1将使节点2、3、…、n排队,总共进行Θ(n)个工作。队列现在如下所示:

ENQUEUE(Q,source_vertex)
while Q != NULL
   u=DEQUEUE(Q)
   for each v in AdjacencyList[u]
     if v not yet visited
        Make v visited
        ENQUEUE(Q,v)
2,3,4,…,n

然后处理节点2时,它将查看其所有边以获得Θ(n)更多工作,然后将节点3、4、5、…、n排队。我们的队列现在如下所示:

ENQUEUE(Q,source_vertex)
while Q != NULL
   u=DEQUEUE(Q)
   for each v in AdjacencyList[u]
     if v not yet visited
        Make v visited
        ENQUEUE(Q,v)
3,4,5,…,n,3,4,5,…,n

我们现在处理节点3,它查看其所有边的Θ(n)功,然后将节点的4、5、6、…、n排队,因此我们的队列如下所示:

ENQUEUE(Q,source_vertex)
while Q != NULL
   u=DEQUEUE(Q)
   for each v in AdjacencyList[u]
     if v not yet visited
        Make v visited
        ENQUEUE(Q,v)
4,5,6,…,n,3,4,5,…,n,4,5,6,…,n

这里的模式是,我们最终将图中每个节点的多个副本排队。事实上,随着时间的推移,我们将在队列中总共有Θ(n2)个节点,并且每个节点做Θ(n)个工作。这意味着该图完成的总工作量为Θ(n3),超过了原始BFS实现的O(m+n)时限


因此,这种新的实现可能比常规BFS渐进地慢。

让我们更改算法,将边添加到队列中(因为这是隐式执行的操作-除了在将其添加到队列中时仅查看相反的顶点,而不是整个边):

每个边缘将考虑两次排队,即
(u->v)
(v->u)
。当访问边
u
的第一个顶点时,将把每个相邻边放入队列,然后完成
u
。当访问
v
时,将考虑边缘
(v->u)
,但由于
u
已完成,因此不会添加到队列中;因此,每条边只会排队一次(在一个方向上,而不是在另一个方向上)

该算法的问题在于,它不会检查它要处理的顶点是否已经完成,并且会对队列中的每条边重新处理它,再次迭代所有相邻边,使算法
O(|V|E|)成为
(而不是
O(|V|+|E|)成为

一个简单的解决方案是:

ENQUEUE( Q,(NULL->source_vertex) )            # start with a dummy edge
WHILE Q != NULL
  (s->u)=DEQUEUE(Q)
  if u not finalized
    for each (u->v) in AdjacencyList[u]
      if v not finalized
        ENQUEUE(Q,(u->v))
    make u finalized
此外,两个版本的算法都将从一个顶点开始,然后处理同一连接组件中的每条边-但是它们将仅在连接图上执行完整的BFS。如果有多个断开连接的组件,则需要使用:

for each source_vertex in Graph
  if source_vertex not visited/finalised
    call your_algorithm( source_vertex )

然后,它将是
O(|V |+| E |)
,并将访问所有顶点,而不管图形是否连接。

如果图形有一个循环,您可能会一次又一次地将同一节点排队,从而导致无限循环。或者你的意思不同?嘿,是的,我意识到了这一点,所以我现在编辑了代码。你得到了相互矛盾的答案。我建议你尝试用越来越大的完整图来证明你自己答案是否定的。这不是循环的无限循环吗?我不这么认为
u
在循环结束时被最终确定,并且最终确定的节点从未放入队列中,因此队列必须最终变为空。我想我有一个反例来说明这一点。你能检查我的答案看我是否遗漏了什么吗?嘿,如果输入图是一个有向无环图怎么办?想象一个完整的有向无环图,再次给节点1,2,3,…,n编号,这样所有的东西都指向它后面的所有节点。节点2插入一次,节点3插入两次,节点4插入三次,以此类推。此外,节点编号k有(n-1-k)条边离开它。所做的总功为1(n-2)+2(n-3)+3(n-4)+4(n-5)+…+(n-3)2+(n-2)1+(n-1)0。如果计算出这个总和,它会再次计算出θ(n^3),因此这仍然比常规BFS慢。更改示例,将边添加到队列中,并处理边的未完成端-您会发现每个边都会添加到队列中一次(并且边的未完成端与示例中的顶点相同)但是,由于在
n
顶点上有一个完整的图,因此将有
n(n-1)/2
边,因此算法仍然是
O(|V|+|E |)的
只是
|E |
@MT0,对于已处理完的无方向案例,不会被放回队列,但仍将由内部循环重新扫描。正是由于多次重新处理边缘所花费的工作,导致了问题的产生。除非我弄错了?@MT0不过就排队的总人数而言,我完全同意你的看法。这部分论点是完全正确的。