【问题标题】:graph implementation with adjacency lists in CC 中具有邻接表的图形实现
【发布时间】:2013-06-01 19:14:57
【问题描述】:

我刚开始学习 C,作为自学练习,我正在用 C 实现数据结构和算法。现在我正在处理一个图表,这是它的数据结构表示。

typedef int graphElementT;
typedef struct graphCDT *graphADT;

typedef struct vertexTag
{
    graphElementT element;
    int visited;
    struct edgeTag *edges;
    struct vertexTag *next; 
} vertexT;

typedef struct edgeTag
{
    int weight;
    vertexT *connectsTo;
    struct edgeTag *next;
} edgeT;

typedef struct graphCDT
{
    vertexT *vertices;
} graphCDT;

我在这个图中添加了一个 addVertex 函数。

int addVertex(graphADT graph, graphElementT value)
{
    vertexT *new = malloc(sizeof(*new));

    vertexT *vert;
    new->element = value;
    new->visited = 0;
    new->edges = NULL;
    new->next = NULL;

    int i = 0;

    for(vert=graph->vertices; vert->next != NULL; vert=vert->next)
    {
        if(vert->element == value)
        {
            printf("already exists\n");
            return 0;
        }
    }   

    vert->next = new;

    //free(new);
    printf("\ninserted %d\n", vert->element);   

    return 1;       
}

这很好用,除了三件事。

  1. 如果新添加的顶点与列表中的最后一个顶点相同,则看不到。为了防止这种情况,我将 for 循环限制条件更改为 vert != NULL,但这会导致段错误。

  2. 如果我尝试释放临时分配的指针,它会通过指针重置内存指针,这会在顶点列表的末尾添加一个无限循环。有没有办法在不覆盖它指向的内存的情况下释放指针?还是真的不需要释放指针?

  3. 破坏图也意味着破坏每条边和顶点吗?还是有更好的方法?

另外,如果这个图形数据结构不是一个好的数据结构并且有更好的实现,我会很感激指出。

【问题讨论】:

  • int addVertex(graphADT graph - 你的意思是graphCDT 吗?
  • for(vert=graph->vertices; vert->next - 在使用之前确保 graph->vertices 不为 NULL。 vert->element == value - 你没有提供 graphElementT 实现,所以很难说这里发生了什么。 printf("\ninserted %d\n", vert->element); - 你在这里打印错误的顶点,应该是new->element
  • 另外,避免使用 new 作为标识符,因为它是 C++ 中的关键字
  • 哦,糟糕,我有一个typedef graphCDT *graphADT; typedef char graphElementT。我也知道它是 C++ 中的一个关键字,但它在 C 中真的很重要吗?
  • 将来是否有可能将您的项目转换为 C++。否则就是不好的风格。

标签: c pointers data-structures graph segmentation-fault


【解决方案1】:

1

如果将限制条件更改为 vert!=NULL ,并且循环以 vert==NULL 结束,即,要添加的顶点不存在,那么您将阅读下一条语句:

vert->next = new;

这意味着您正在访问 NULL ,vert 指针,因此是 seg 错误。

现在要允许检查最后一个元素是否不是要添加的顶点,以及防止 seg 错误,请执行以下操作:

for(vert=graph->vertices; vert->next != NULL; vert=vert->next)
{
    if(vert->element == value)
    {
        printf("already exists\n");
        return 0;
    }
}   

if(vert->element == value)
    {
        printf("already exists\n");
        return 0;
    }

vert->next = new;

2

临时“新”指针是分配给您添加的顶点的内存位置。它不会被释放,因为释放它意味着您删除了刚刚添加的顶点:O。

3

是的,破坏图本质上是一样的。

将链表实现为图形的邻接表实现始终是一个好习惯。尽管您始终可以使用 c++“二维向量”来实现相同的。

【讨论】:

  • 不,我打算坚持使用 C。谢谢您的回答。 :)
【解决方案2】:

这是一个您可以使用的有效 addVertex 函数。 我保持原来的声明不变。 我添加了一个 main (),您可以在其中提供命令行参数进行测试。

int addVertex(graphADT graph, graphElementT value)
{
   vertexT *tmpvert , *vert ;
   vert=graph->vertices ;
  /*check to see whether we really need to create a new vertex*/
   tmpvert = vert;
     while(tmpvert != NULL)
     {
       /* U can put a debug printf here to check what's there in graph:
        *  printf("tmpvert->elem=%d   ", tmpvert->element);
        */
        vert = tmpvert;
        if(tmpvert->element == value)
             return 0;
        tmpvert=tmpvert->next ;
    }
   /*If we are here , then we HAVE to allocate memory and add to our graph.*/
   tmpvert = (vertexT*)malloc(sizeof(vertexT));
   if ( NULL == tmpvert )
        return 0; /* malloc failure */
   tmpvert->element = value;
   tmpvert->visited = 0;
   tmpvert->edges = NULL;
   tmpvert->next = NULL;

   if ( NULL == vert )
        graph->vertices = tmpvert; /*Notice that I dont use virt=tmpvert */
   else
        vert->next = tmpvert; /*putting stuff in next is fine */

    return 1;
/* Dont try printing vert->element here ..vert will be NULL first time */
/*return code for success is normally 0 others are error.
 *That way you can have your printfs and error code
 *handling outside this function.But its ok for a test code here */
}

现在对main()sn-p进行测试:

int main (int argc , char* argv[]) {
        graphADT graph ;
        graph =(graphADT) malloc ( sizeof(struct graphCDT) );
        graph->vertices = NULL;
        while ( --argc >0)
        {
                int value = atoi(argv[argc]);
                addVertex(graph,value);
        }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2019-09-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多