最短路径算法建模时的队列问题

发布于 2024-11-10 17:20:24 字数 1548 浏览 1 评论 0原文

我有一个队列问题。对图进行建模,我正在用 C++ 编写最短路径算法。

在我的 while (!q.empty()) 中,当我返回此语句时,前面的 vertex* 会发生更改。

你能弄清楚为什么吗?

int MyMatrix::searchBreadth(MyVertex* from,MyVertex* to)
{
queue<MyVertex*> q;  
path=INFINITY;

from->visit();  
from->setDistance(0);  
q.push(from);  

//here q.front()'s attributes get changed when returning from the for-loop  
while(!q.empty())
{  
    MyVertex* v=q.front();  
    q.pop();  
    int k=v->getDistance();  
    vector<MyVertex> nb=getNeighbours(*v);  
    for(int i=0;i<nb.size();i++)  
    {  
        if(nb[i].getDistance()==INFINITY)
        {  
            nb[i].setDistance(k+1);  
            q.push(&nb[i]);  
        }

        if((nb[i].getName().compare(to->getName())==0)
           && !nb[i].isVisited())
        {
            //path found  
            int j=nb[i].getDistance();  
            if(j<path) path=j;  
        }  

        nb[i].visit();  
     }  
}  
return path;  

}   

getNeighbours() 来了

vector<MyVertex> MyMatrix::getNeighbours(MyVertex &v)
{  
    int index=0;  
    for(int l=0; l<stations.size(); l++ )
    {  
        if(stations[l].getName().compare(v.getName())==0)index=l;  
    }

    vector<MyVertex> out;  
    for(int k=0;k<matrixSize;k++)
    {  
        if(matrix[index][k].getName().compare("null")!=0)
        {  
            out.push_back(matrix[index][k].getTo());  
        }  
    }  

    return out;
}

I have a queue problem. Modeling a graph, I'm doing a shortest path algorithm in C++.

In my while (!q.empty()) the front vertex* gets changed when I return to this statement.

Can you figure out why?

int MyMatrix::searchBreadth(MyVertex* from,MyVertex* to)
{
queue<MyVertex*> q;  
path=INFINITY;

from->visit();  
from->setDistance(0);  
q.push(from);  

//here q.front()'s attributes get changed when returning from the for-loop  
while(!q.empty())
{  
    MyVertex* v=q.front();  
    q.pop();  
    int k=v->getDistance();  
    vector<MyVertex> nb=getNeighbours(*v);  
    for(int i=0;i<nb.size();i++)  
    {  
        if(nb[i].getDistance()==INFINITY)
        {  
            nb[i].setDistance(k+1);  
            q.push(&nb[i]);  
        }

        if((nb[i].getName().compare(to->getName())==0)
           && !nb[i].isVisited())
        {
            //path found  
            int j=nb[i].getDistance();  
            if(j<path) path=j;  
        }  

        nb[i].visit();  
     }  
}  
return path;  

}   

here comes getNeighbours()

vector<MyVertex> MyMatrix::getNeighbours(MyVertex &v)
{  
    int index=0;  
    for(int l=0; l<stations.size(); l++ )
    {  
        if(stations[l].getName().compare(v.getName())==0)index=l;  
    }

    vector<MyVertex> out;  
    for(int k=0;k<matrixSize;k++)
    {  
        if(matrix[index][k].getName().compare("null")!=0)
        {  
            out.push_back(matrix[index][k].getTo());  
        }  
    }  

    return out;
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

℡Ms空城旧梦 2024-11-17 17:20:24

您的问题很微妙,但与 q.push(&nb[i]) 相关。您所做的是添加一个指向向量中某个位置的指针,这在概念上与添加一个指向 MyVertex 对象的指针不同。邻居向量包含“按值”的 MyVertex 对象(如果这有助于您理解问题)。

查看内存中的 nb 可能会有所帮助:

        0         1                   I
nb [MyVertex0|MyVertex1|   ...   |MyVertexI]
             +---------+
                  | (Notice it is NOT pointing to MyVertex1!)
&nb[1]------------+

当您推送 &nb[1] 时,您正在推送地址 nb + (1 * sizeof(MyVertex) )nb 在堆栈上声明,因此该地址将位于堆栈上的某个位置。

因此,当您的 for 循环返回时,nb 会刷新(可以这么说)并添加新数据。但是,您的队列 q 包含不再有效的 nb 地址!

简而言之:您的队列引用向量中的位置,而不是向量中的数据

如果您想保持方法不变,这意味着 getNeighbors 需要更改为返回 MyVertex* 向量。


您应该简单地编辑BreadthFirstSearch 采用两个 MyVertex&,而不是指针。然后,您可以将 q 更改为 queue,将 v 更改为 MyVertex,最后您应该更改q.push(&nb[i])q.push(nb[i])

Your problem is subtle, but related to q.push(&nb[i]). What you're doing is adding a pointer to a location in a vector, which is not conceptually the same as adding a pointer to a MyVertex object. The vector of neighbors contains the MyVertex objects "by value" (if that helps in your understanding of the problem).

A look at nb in memory may help:

        0         1                   I
nb [MyVertex0|MyVertex1|   ...   |MyVertexI]
             +---------+
                  | (Notice it is NOT pointing to MyVertex1!)
&nb[1]------------+

When you push &nb[1] you're pushing the address nb + (1 * sizeof(MyVertex)). nb is declared on the stack, so that address is going to be somewhere on the stack.

So when your for-loop comes back around, nb gets refreshed (so to speak) and new data is added. However, your queue q contains addresses into nb that are no longer valid!

Simply put: your queue is referencing a LOCATION in the vector, not the DATA in the vector.

If you want to keep your method as-is, this means getNeighbors needs to change to return a vector of MyVertex*.


You should simply edit BreadthFirstSearch to take two MyVertex&, rather than pointers. You would then change q to be a queue<MyVertex>, v to MyVertex, and finally you should change q.push(&nb[i]) to just q.push(nb[i]).

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文