如何为C

时间:2017-02-02 18:33:07

标签: c pointers linked-list

我正在为uni工作,我需要找到图表的总和。

要做到这一点,我相信我需要一个链表,我可以用它来记住访问过的节点。我有链接列表正常工作,但我无法使用包含函数。这是我的代码:

struct listnode
{
  struct N *val;
  struct listnode *next;
};


int contains(struct listnode *head,struct N* value)
{
  struct listnode *current = head;
  while (current)
  {
    if ((current -> val) == value)
    {
      return 1;
    }
    current = current -> next;
  }
  return 0;
}

注意:N是图表的节点。

任何人都可以看到我正在做的任何问题吗?

编辑:当N *值在列表中时,包含函数应返回1,否则为0

EDIT2:

我有推送功能:

void push(struct listnode *head,struct N *value)
{
  if (head)
  {
    struct listnode *current = head;
    while (current->next)
    {
      current = current -> next;
    }
    current->next = malloc(sizeof(struct listnode*));
    current->next->val = value;
    current->next->next = NULL;
  }
  else
  {
    head = malloc(sizeof(struct listnode*));
    if (head)
    {
      head -> val = value;
      head -> next = NULL;
    }
    else
    {
      printf("error");
      exit(0);
    }
  }
}

我希望以下行返回1:

contains(push(visited,p),p);

其中p是指向结构N的指针,访问的是我的全局链表

EDIT3:

这是我认为应该起作用的最终总和函数,但不是因为包含。

long sum(struct N *p)
{
  if (p)
  {
    if (contains(visited,p) == 0) //if p hasnt been visited
    {
      push(visited,p); //make it visited
      return (p -> data) + sum(p -> x) + sum(p -> y) + sum(p -> z);
    }
    else
    {
      return 0;
    }
  }
  else
  {
    return 0;
  }
}

2 个答案:

答案 0 :(得分:2)

您的包含功能似乎没问题。问题是您始终向其传递NULL列表,这是由错误的push函数引起的。您需要在push中返回,或者传入一个指向另一个间接级别的指针,这样您就可以在head之外分配push。另一个可能的改进是注意到无论你传入什么,malloc和新节点的初始化实际上是相同的。

最后,主要问题是,最有可能导致段错误的是你为节点指定了足够的空间,而不是节点本身。

以下是一个例子:

#ifdef BY_INDIRECTION
  #define RET_TYPE void
  #define IN_TYPE struct listnode **
#else
  #define RET_TYPE struct listnode *
  #define IN_TYPE struct listnode *
#endif

RET_TYPE push(IN_TYPE head, struct N *value)
{
  struct listnode *current, **next;
  if(head)
  {
    for(current = head; current->next; current = current->next) ;
    next = &(current->next);
  }
  else
  {
#ifdef BY_INDIRECTION
    next = head;
#else
    next = &head;
#endif
  }

  *next = malloc(sizeof(struct listnode));
  if(!*next) {
      printf("error");
      exit(0);
  }
  (*next)->val = value;
  (*next)->next = NULL;

#ifndef BY_INDIRECTION
  return head
#endif
}

我在这里提出了两条建议。如果您想阅读我们使用间接的方法(传入listnode **并返回void),请选择定义BY_INDIRECTION的路径。如果您希望返回head(并仅传入常规listnode *),请阅读未定义BY_INDIRECTION的路径。

后一种方法具有返回值,因此可用于编写缩写形式,如if(contains(push(head, value), value)) { ... }。前一种方法没有,所以你必须这样做

push(&head, value);
if(contains(head, value)) { ... }

我建议使用间接方法,因为在放入值之后,您希望检查包含的实例非常少。

答案 1 :(得分:0)

这个比较:

if ((current -> val) == value)

它正在比较指针。如果您以这种方式致电contains()功能......

...
struct N val_to_find;
...
result = contains (list, &val_to_find);

即使val_to_find的内容与指针存储在列表中的任何结构的内容相同,也永远不会找到该值。

如果您对contains()的意图是找到具有相同数据的节点,而不仅仅是相同的指针,我建议你这样:

if (struct_n_comparing_function (current -> val, value) == EQUAL) ...

struct_n_comparing_function应该有以下原型:

int struct_n_comparing_function (struct N *a, struct N *b);

比较ab指向的两个结构的内容,如果EQUAL指向的结构的所有字段具有相同的值,则返回ab指向的结构字段。