我刚刚开始学习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;
}
除了三件事之外,这种方法很好。
如果新添加的顶点与列表中的最后一个顶点相同,则无法看到它。为了防止这种情况,我将for循环限制条件更改为vert != NULL
,但这会产生seg错误。
如果我尝试释放临时分配的指针,它会通过指针重置内存指针,这会在顶点列表的末尾添加一个无限循环。有没有办法释放指针而不写入指向的内存?或者是不是真的需要释放指针?
同样会破坏图表意味着破坏每个边缘和顶点?还是有更好的方法?
此外,如果图形的数据结构不是很好并且有更好的实现,我会很感激被指出。
答案 0 :(得分: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;
临时“新”指针是分配给您添加的顶点的内存位置.IT不会被释放,因为释放它意味着您删除了刚刚添加的顶点:O。
是的,摧毁图表必然意味着相同。
将链表实现为图的邻接列表实现始终是一个好习惯。尽管你总是可以使用c ++“2 D Vector”来实现它。
答案 1 :(得分:0)
这是一个可以使用的有效的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()片段:
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);
}
}