这是用邻接表实现无向图的正确方法吗?

Is this the right way of implementing undirected graph using adjacency list?

本文关键字:方法 实现      更新时间:2023-10-16

首先,我对图表不熟悉。在研究了图的概念之后。我想用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)要求用户输入一个整数(no。(顶点),因此我创建了一个具有请求大小的数组。同时,我指向头和cur指针指向每个数组节点。数组的索引号等于顶点号

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

我的问题是:

1)这种实现方式是否正确?

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

我会尽量让你明白的。

在无向图中,每个节点都可以连接到任何其他节点。这意味着一个节点"指向"任意数量的其他节点。在您的代码中,每个节点都有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

调用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,这意味着你的代码试图访问头[4]的链接部分,但头[4]没有存储有效节点的地址