【问题标题】:Implementing the pseudocode using matrix:使用矩阵实现伪代码:
【发布时间】:2020-04-10 17:14:42
【问题描述】:

我需要以矩阵形式实现以下代码。我需要获取源顶点并随机生成连通图。但是,伪代码采用列表形式,我不确定我是否将其正确转换为矩阵形式,出于某种原因,我不断让所有节点得到充分探索,或者它们的颜色全部变为黑色?

D代表距离

π 代表父母

颜色 = 白色未访问/灰色已访问/黑色所有邻居已探索

     #include <iostream>
#include <limits>
#include <queue>
#include <stdlib.h>     /* srand, rand */

using namespace std;



enum  Color {white , gray, black};
struct vertex{

    Color color =white ;
   int relationship =0;
   int distance =abs(numeric_limits<int>::max());
   int parent =0;

};

void BFS(int size ,int s)
{
   //no need for first loop to initializer to defaults since they are already
    vertex g [size][size];
    int random;
    for(int i=0;i<size;i++)
    {
        for(int j=0;j<size;j++)
        {
            random =rand()%(size);
            if(j!=i and random!=i) //to make it undirected
            {
                g[i][random].relationship=1;
                g[random][i].relationship=1;

            }

        }

    }
   ///
   g[s][0].color =gray;
   g[s][0].distance=0;
   g[s][0].parent=0;
    queue <int> q;
    q.push(s);

    int u;
    while(!q.empty())
    {
        u=q.front();
        q.pop();
        g[u][0].color=black;
        for(int v=0;v<size;v++)
        {
            if (g[u][v].relationship==1 and g[v][0].color==white) {
                g[v][0].color = gray;
                g[v][0].distance = g[u][0].distance+1;
                g[v][0].parent = u;
                q.push(v);
            }


        }
    }


    for(int i = 0; i<size;i++)
    {

       for(int j =0;j<size;j++)
       {
           cout<<g[i][j].relationship <<" ";
       }
       cout<<endl;

    }
for(int i = 0; i<size;i++)
{

    cout<<" Distance of node: " << i<<" from the source is: ";
    cout<< g[i][0].distance<<" ";
    if(g[i][0].color==white)
    {
        cout<<" Color of node: " << i<<" is white";

    }
    if(g[i][0].color==gray)
    {
        cout<<" Color of node: " << i<<" is gray";

    }

    if(g[i][0].color==black){
        cout<<" Color of node: " << i<<" is black";

  }
    cout<<" parent of node: " << i<<" ";
    cout<< g[i][0].parent<<" "<<" ";
    cout<<endl;
   }

}
int main() {


    int vertices;
    cout<<"Please enter the number of vertices: "<<endl;
    cin>>vertices;
    int source;
    cout<<"Please enter the source  "<<endl;
    cin>>source;
    BFS(vertices,source);




    return 0;
}

【问题讨论】:

  • 如果它是无向的,不应该是 g[i][j].relationship=1 AND g[j][i].relationship=1 吗?还是你的意思是别的?
  • 无向图的对角矩阵应为0,否则有向
  • 我写的是 I 和 J,而不是 I 和 I。你写的是无向的。这意味着如果 g[ I ][ J ] 关系存在,则 g[ J ][ I ] 也存在。你似乎也没有在 BFS 稍后检查 g[U][V] 和 g[V][U],你也没有在设置时设置 g[ I ][ J ] 和 g[ J ][ I ] g[ I ][ J ] 在生成随机边的部分。
  • @JunisvaultCo 哦,我明白了,谢谢!

标签: c++ algorithm graph-algorithm breadth-first-search clrs


【解决方案1】:

您似乎只是偶尔将 u 误认为 v 并且没有考虑伪代码中的标识。

            q.pop();
            g[v][0].color=black;

是为了在 for 之后。另外,你做到了

g[v][0].color=black

而不是

g[u][0].color=black

与你。再一次,同样的错误:

                g[v][0].distance = g[v][0].distance+1;

什么时候你应该写这个(和你一起):

                g[v][0].distance = g[u][0].distance+1;

用 u 代替 v。否则真的没有任何意义。

我强烈建议阅读 BFS 背后的逻辑。 https://www.geeksforgeeks.org/breadth-first-search-or-bfs-for-a-graph/

如果您确实了解 BFS 背后的逻辑并且碰巧犯了这些错误,这里有 2 个调试技巧可以帮助我了解问题所在:

  1. 如果您的程序应该输出一些值,但没有输出,则可能存在循环。通常在调试时在中间阶段使用 cout 是一个好主意,看看结果是否符合您的预期。你可以在循环的情况下做类似的事情来注意循环在哪里,甚至可能是为什么。

    1.1。如果不知何故,无论你把cout放在哪里,你仍然没有得到输出,这可能是一个分段错误(在某些编码环境中它会说分段错误,有时你会看到它需要一段时间才能说诸如“进程已结束,返回一些非 0 的数字”之类的内容可能类似于控制台中的“进程已结束,返回 -243”。分段错误是当您访问一些您不应该访问的内存时(您的元素之一尝试访问数组超出范围,或者您从列表中删除了此元素并尝试访问它)。

  2. 一旦 q.pop() 被解决,你会注意到负的和大的输出(这通常是不可能的)。这意味着某处发生了溢出。您从除了源之外的几乎所有节点的最大距离开始,溢出非常有意义,您以某种方式添加到具有最大距离的节点。

编辑:关于随机生成,就像现在一样,它实际上并不是那么随机。您应该使用带有种子(例如当前时间)的随机生成器来实际每次都获得一棵新树。

在 C++ 中,有 srand,在这里您可以看到来自 https://www.cplusplus.com/reference/cstdlib/srand/ 的一个关于从 srand 获取实际随机数的快速示例(只需在不带参数的情况下对其进行初始化将使其每次都选择相同的种子,因此给出相同的结果但是,我们可以通过获取当前时间来修复它,因为当前时间总是不同的,并将其用作种子):

/* srand example */
#include <stdio.h>      /* printf, NULL */
#include <stdlib.h>     /* srand, rand */
#include <time.h>       /* time */

int main ()
{
  printf ("First number: %d\n", rand()%100);
  srand (time(NULL));
  printf ("Random number: %d\n", rand()%100);
  srand (1);
  printf ("Again the first number: %d\n", rand()%100);

  return 0;
}

【讨论】:

  • 非常感谢,我现在得到了正确的距离,但是对于节点颜色,它显示它们全部为黑色或已探索
  • 如果黑色意味着探索,那么如果图形完全连接,那么你应该期望它们都是黑色的(最后)。节点不会是黑色的唯一情况是由于它没有(直接或通过另一个节点)连接到源。由于随机生成,这几乎不会发生。如果在生成时去掉 J 循环,每个 I 节点只生成一条边,就会看到白色节点。
  • @Misu 另外,您的代码在使用随机数生成器时,也应该每次都为生成器使用另一个种子,因为正常的 rand() 每次都使用相同的种子。种子为什么存在?有时您想要相同的“随机行为”序列。我已经用它的工作原理更新了我的答案。
【解决方案2】:

您的q.pop() 放错地方了。由于它位于 for 循环的中间,因此您从队列中删除队列中处理的每个顶点的 size 条目。您要做的是将q.pop() 移动到u=q.front() 之后。

u = q.front();
q.pop();
for(int v = 0; v < size; v++)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-05-09
    • 2016-02-24
    • 2018-05-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-11-01
    相关资源
    最近更新 更多