【问题标题】:Difficulty in understanding the implementation of graphs using Linked Lists难以理解使用链表实现图
【发布时间】:2017-01-06 15:51:02
【问题描述】:

我正在阅读一本关于 Algorithms 的书,其中包含以下代码。我很难理解这里的一些台词。

我在以下代码中将my doubt lines 显示为DOUBT LINE 1DOUBT LINE 2。 我还评论了一行REFERENCE,我是having difficulty,以便理解。 请详细说明DOUBT LINE 1DOUBT LINE 2

#define MAXV        100     /* maximum number of vertices */
#define NULL        0       /* null pointer */

/*  DFS edge types      */

#define TREE        0       /* tree edge */
#define BACK        1       /* back edge */
#define CROSS       2       /* cross edge */
#define FORWARD     3       /* forward edge */

typedef struct edgenode {
    int y;              /* adjancency info */
    int weight;         /* edge weight, if any */
    struct edgenode *next;      /* next edge in list */
} edgenode;

typedef struct {
    edgenode *edges[MAXV+1];    /* adjacency info */       //REFERENCE 
    int degree[MAXV+1];     /* outdegree of each vertex */
    int nvertices;          /* number of vertices in the graph */
    int nedges;         /* number of edges in the graph */
    int directed;           /* is the graph directed? */
} graph;

它是 graph.h 头文件,它也是读取和插入函数。

read_graph(graph *g, bool directed)
{
    int i;              /* counter */
    int m;              /* number of edges */
    int x, y;           /* vertices in edge (x,y) */

    initialize_graph(g, directed);

    scanf("%d %d",&(g->nvertices),&m);

    for (i=1; i<=m; i++) {
        scanf("%d %d",&x,&y);
        insert_edge(g,x,y,directed);
    }
}

insert_edge(graph *g, int x, int y, bool directed)
{
    edgenode *p;            /* temporary pointer */

    p = malloc(sizeof(edgenode));   /* allocate storage for edgenode */

    p->weight = NULL;
    p->y = y;
    p->next = g->edges[x]; //DOUBT LINE1

    g->edges[x] = p;        /* insert at head of list */ //DOUBT LINE 2

    g->degree[x] ++;        

    if (directed == FALSE)
        insert_edge(g,y,x,TRUE);
    else
        g->nedges ++;
}

【问题讨论】:

  • 头文件中有函数吗?最好不要,对吧?

标签: c pointers struct graph singly-linked-list


【解决方案1】:

每个顶点都有一组边。我们可以认为集合是无序的。在 mutator 函数之外的任何时候,指针 g-&gt;edges[i] 指向第一个 edgenode 事件在 ith 顶点,否则 NULL。然后,edgenode 中的 next 链接可传递地指向集合中的其他边。

所以,要添加一条边,首先创建一条新边,然后将其 next 指针分配给当前“第一个”节点(DOUBT LINE 1),然后将 g-&gt;edges[i] 指针分配给新创建的值(DOUBT LINE 2).

请注意,尽管节点的顺序发生了变化,但我上面所说的需要存在的条件都仍然满足——“以前”的第一个现在是第二个,新节点是第一个。没关系,因为我们只是存储一个集合 - 顺序无关紧要。

之前(=> 遍历“下一个”链接):

   // edges[i] == <previous> => <other stuff>...

之后:

   //         *             *    These asterisks are above what we set...
   //edges[i] == <new node> => <previous> => <other stuff>

【讨论】:

    【解决方案2】:

    链表表示next是指向下一个节点的指针。 示例:
    a {some_data,pointer_to_b}
    b {some_data,pointer_to_c}
    当要插入节点时,必须将前一个节点的next指针更改为新节点,并将新节点的next指针设置为下一个节点的地址。 例子:
    a {some_data,pointer_to_d/*what is done at doubt line 1*/}
    d {some_data,pointer_to_b} //插入的节点在疑问线2做了什么
    b {some_data,pointer_to_c}

    【讨论】:

      【解决方案3】:

      让我们剖析一下,让你清楚地了解一切。

      图的结构

      1o-->2o-->#
      2o-->3o-->#
      3o-->#
      4o-->#
      5o--.#
      

      这里

       `1o`: The node 1
      
       `-->`: It denotes a directed edge.
      
       `#`: denotes `NULL`
      

      现在让我们添加权重 = 5 的 2--&gt;4

      第一步:p = malloc(sizeof(edgenode));

      p-------->[ ]   ( This is the allocated node)
      

      Step-2: p-&gt;weight = NULL; // 应该是边的权重 p-&gt;y = y;

      | wieght = 5 |
      | y = 4      |
      | next       |
      

      第三步:p-&gt;next = g-&gt;edges[x]; g->edges[2] 是指向3o的指针

      | wieght = w |
      | y = 4      |
      | next =------------>3o
      

      现在图片是

      1o-->2o--->#
      
      p[]--+
           |
           V
      2o-->3o--->#
      3o-->#
      4o-->#
      5o--.#
      

      第四步:g-&gt;edges[2]=p g-&gt;edges[2] 基本上就是2o

      1o-->2o--->#
      2o-->[] --> 3o--->#
      3o-->#
      4o-->#
      5o-->#
      

      简单

      1o-->2o--->#
      2o-->4o--->3o--->#
      3o-->#
      4o-->#
      5o-->#
      

      解释:

      基本上,我们在这里维护一个列表,如果存在边x-&gt;yx-&gt;z,则为每个节点 x 放置 y、z。

      如果我们查看实现,我们会看到前面添加了节点。

      例如..如果我们添加x-&gt;y 那么边缘列表将如下所示

      x----&gt;y

      现在添加 z。

      x----&gt;z----&gt;y

      仅此而已...当您没有获得代码时,请准备好铅笔和纸尝试空运行,或者有时只是运行调试器。

      【讨论】:

        猜你喜欢
        • 2017-10-24
        • 2016-08-24
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多