【问题标题】:Is this the right way of implementing undirected graph using adjacency list?这是使用邻接表实现无向图的正确方法吗?
【发布时间】:2015-10-01 14:29:23
【问题描述】:

首先,我是图的新手。在研究了图的概念之后。我想到了用c ++实现。搜索实现的时候觉得代码很难看懂,所以想自己实现。

以下是我尝试过的代码:

#include<iostream>
using namespace std;

struct Node {
    int data;
    Node *link;

};

//creating array of nodes
struct Node *array[10];
//creating array of head pointers to point each of the array node.
struct Node *head[10];
//creating array of current pointers to track the list on each array node.
struct Node *cur[10];

void create(int v)
{

    for (int i = 0; i < v; i++) {
        array[i] = new Node;
        head[i] = cur[i] = array[i];
        array[i]->data = i;
        array[i]->link = NULL;
    }

}

void add(int fr, int to)
{
    Node *np = new Node;
    np->data = to;
    np->link = NULL;

    if (head[fr]->link == NULL) {
        head[fr]->link = np;
        cur[fr] = np;

    } else {
        cur[fr]->link = np;
        cur[fr] = np;
    }

    /*Node* np1=new Node;
    np1->data=fr;
    np1->link=NULL;
    if(head[to]->link==NULL)
    {
    head[to]->link=np1;
    cur[to]=np1;
    }else
    {
    cur[to]->link=np1;
    cur[to]=np1;
    }*/

}

void print(int a)
{
    Node *p = NULL;
    p = head[a];

    for (; p != NULL; p = p->link)
    { cout << p->data; }

}



main()
{

    int a;
    cout << "enter the size of array";
    cin >> a;
    create(a);
    //adding edges
    add(1, 4);
    add(1, 3);
    add(0, 3);
    add(0, 2);
    print(0);
    cout << "\n";
    print(1);
    //print(3);

}

解释:

1)要求用户输入一个整数(顶点数),因此我正在创建一个具有请求大小的数组。同时我将 head 和 cur 指针指向每个数组节点。数组的索引号等于顶点号。

2) 通过 add 函数将边从一个顶点添加到另一个顶点。如果边缘发出的顶点的头节点为空,则我指向 head=cur=new 节点(np),否则我在每次添加后更新 cur 指针。 Head 将指向数组索引节点。 3)打印连接到请求节点的边。

我的问题是:

1)这种实现方式对吗?

2)在上述情况下,假设我们连接顶点 1 和顶点 3。上面的代码 3 链接到 1。我想自动更新从顶点 3 到顶点 1 的连接,所以我添加了里面的代码添加函数中的注释部分。当我尝试运行它要求我输入数组大小的代码时,我输入了一些整数,它显示了分段错误。为什么?

【问题讨论】:

  • 你能告诉我你输入的整数值吗?
  • 我尝试将 3 和 4 作为 'a',它们都给出了分段错误。

标签: c++ arrays list graph


【解决方案1】:

我会试着给你这个想法。

在无向图中,每个节点都可以连接到任何其他节点。 这意味着一个节点“指向”任意数量的其他节点。 在您的代码中,每个节点都有Node*link;,它是指向下一个节点的指针。您需要一个链接列表(或数组):每个节点都必须包含指向它所连接的所有节点的链接。这是邻接表。类似的东西

struct Node
{
    int data;
    ADJ* adjs; // list of Node*
};

struct ADJ
{
    ADJ* next;
    Node* data;
};

这里的 adjs 是邻接列表。

另外,void print(int a) 的解决方案更类似于您在常见列表中找到的解决方案。您需要打印节点的所有邻接关系,即它指向的所有节点。

请记住,由于图形是无向的,因此您需要指针 A->B 和 B->A

【讨论】:

  • 所以你的意思是说首先我们创建一个 ADJ 数组,并使 ADJ 的 *next 指针一个接一个地指向 Node 的节点。
  • 没错,这就是邻接表的表示。作为奖励,您还可以实现具有相同结构的有向图。您可以有一些变体,例如,可以使用 Node* 数组代替 Node* 列表,但概念是相同的。
【解决方案2】:

调用 create(3) 后,您的数组如下所示:

array  
0 -> (0,NULL)
1 -> (1,NULL)
2 -> (2,NULL)
3
4
5
6
7
8
9 

调用 add(1,4) 时出现分段错误。

在第一部分,即

Node *np = new Node;
np->data = to;
np->link = NULL;

if (head[fr]->link == NULL) {
    head[fr]->link = np;
    cur[fr] = np;

} else {
    cur[fr]->link = np;
    cur[fr] = np;
}

完全没有问题。

现在数组如下所示:

array  
0 -> (0,NULL)
1 -> (1,->) (4,NULL)
2 -> (2,NULL)
3
4
5
6
7
8
9

但下一部分是分段错误的原因,即

Node* np1=new Node;
np1->data=fr;
np1->link=NULL;
if(head[to]->link==NULL)
{
head[to]->link=np1;
cur[to]=np1;
}else
{
cur[to]->link=np1;
cur[to]=np1;
}

问题出在这一行:

head[to]->link==NULL

这里 to 的值为 4,这意味着您的代码尝试访问 head[4] 的链接部分,但 head[4] 未存储有效节点的地址。

【讨论】:

  • 我认为它的头部 [4] 而不是头部 [2]。我尝试将 'a' 设为 5,效果很好。非常感谢。
猜你喜欢
  • 2012-11-11
  • 2019-09-01
  • 1970-01-01
  • 2021-01-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多