【问题标题】:Why is my linked list printing backwards?为什么我的链表打印反了?
【发布时间】:2019-07-26 13:21:39
【问题描述】:

我想打印我的链表的内容,它来自一个文件,如下:

1,Postit Notes,Sticky notes,3
2,Black pens,Gel pens with black ink,5
3,Blue pens, Gel pens with blue ink, 4
4, Red pens, Gel pens with red ink for grading, 3
5, Notecards,Ruled 3" by 5" notecards,2
7,Whiteout,For mistakes made when writting with ink,3

到目前为止,在我的程序中,我的输入被正确读取,并且我已经调试了该部分,所以我知道这不是问题所在。我在打印链接列表时遇到问题。

我尝试编写addRecord 方法(如下所示),在该方法中,我为新节点分配内存,分配所需的数据,并尝试将其添加到链表的末尾。我还有一个打印链表内容的方法,如下图:

static void *addRecord(List *list, int newID, char *newName, char *newSummary, int newCount) 
{
  //Allocate memory for the node
  Node *new = (Node *)malloc(sizeof(Node)); 

  //Add in data
  new->id = newID;
  strcpy(new->name, newName);
  strcpy(new->summary, newSummary);
  new->count = newCount;

  //Node gets data you added in
  new->next = list->head;
  list->head = new;
  return EXIT_SUCCESS;
}
void print(List *list)
{
  printf("LIST IN FORWARD ORDER:\n");

  //Create a temporary node to traverse the list
  Node *temp = list->head;

  //Traverse the entire list
  while (temp != NULL) {
    printf("Item ID: %d\n", temp->id);
    printf("Name: %s\n", temp->name);
    printf("Summary: %s\n", temp->summary);
    printf("Count: %d\n", temp->count);
    printf("-----\n");
    temp = temp->next;
  }
}

这是我的链接列表的设置方式:

//struct for each office item
struct NodeStruct {
    int id;
    char name[MAX_NAME];
    char summary[MAX_SUM];
    int count;
    struct NodeStruct *next;
};


/** Structure for the whole list, including head and tail pointers. */
typedef struct {
  /** Pointer to the first node on the list (or NULL ). */
  Node *head;
} List;

我的预期输出应该是这样的:

LIST IN FORWARD ORDER:
Item ID: 1
Name: Postit Notes
Summary: Sticky notes
Count: 3
-----
Item ID: 2
Name: Black pens
Summary: Gel pens with black ink
Count: 5
-----
Item ID: 3
Name: Blue pens
Summary: Gel pens with blue ink
Count: 4
-----
Item ID: 4
Name: Red pens
Summary: Gel pens with red ink for grading
Count: 3
-----
Item ID: 5
Name: Notecards
Summary: Ruled 3" by 5" notecards
Count: 2
-----
Item ID: 7
Name: Whiteout
Summary: For mistakes made when writting with ink
Count: 3
-----

但是,我的实际输出是:

LIST IN FORWARD ORDER:
Item ID: 7
Name: Whiteout
Summary: For mistakes made when writting with ink
Count: 3
-----
Item ID: 5
Name:  Notecards
Summary: Ruled 3" by 5" notecards
Count: 2
-----
Item ID: 4
Name:  Red pens
Summary:  Gel pens with red ink for grading
Count: 3
-----
Item ID: 3
Name: Blue pens
Summary:  Gel pens with blue ink
Count: 4
-----
Item ID: 2
Name: Black pens
Summary: Gel pens with black ink
Count: 5
-----
Item ID: 1
Name: Postit Notes
Summary: Sticky notes
Count: 3
-----

在我的打印方法中,当我尝试打印头节点的内容时,我从 ID 为 7 的项目中获取数据/信息,而我应该获取 ID 为 1 的项目的信息。有人可以解释一下吗我的为什么我的列表是向后打印的?我试图追踪它,但我有点困惑。我尝试了其他方法来添加记录,但是当我尝试这样做时,我不断收到Segmentation Fault: 11

提前谢谢你!

编辑:

在下面 Thomas Jager 的评论之后,我对我的 addRecord 方法进行了以下修改:

static void *addRecord(List *list, int newID, char *newName, char *newSummary, int newCount) 
{
  //Allocate memory for the node
  Node *new = (Node *)malloc(sizeof(Node)); 

  //Add in data
  new->id = newID;
  strcpy(new->name, newName);
  strcpy(new->summary, newSummary);
  new->count = newCount;

  //Special case: If the first node is null, add the data here
  if (list->head->next == NULL) {
    list->head->next = new;
  } else {
    Node *temp = new; 
    while (temp != NULL) {
      new = new->next; 
    }
  }

  return EXIT_SUCCESS;
}

但是,现在,我收到以下错误:

Segmentation fault: 11

我无法理解发生的分段错误错误,有人可以向我解释一下吗?

【问题讨论】:

  • 添加到列表时,您添加到列表的前面。它不是向后打印,而是向后打印。
  • 如果要添加到列表尾部,需要在List结构体中维护列表尾部。在Node *head; 之后添加Node *tail;,并更新addRecord 中的tail 指针。 Ylou 可能希望能够添加到头部或尾部。这是一个很好的练习。
  • 嗨@ThomasJager,非常感谢您指出这一点。您能否查看我对上述问题的编辑,因为我仍然遇到一些错误并且不确定我做错了什么导致分段错误?
  • @PomegranateSociety 在您修改后的代码中,您访问new->next,这几乎肯定是一些垃圾值。您想做类似的事情,但通过现有列表的 next 值,而不是 new 的值。请参阅下面的答案。

标签: c data-structures printing linked-list insert


【解决方案1】:

问题在于您添加到列表的方式。您总是在列表的头部而不是尾部添加。

解决此问题的一种方法是更改​​您的 addRecord 函数:

static void addRecord(List *list, int newID, char *newName, char *newSummary, int newCount) 
{
  //Allocate memory for the node
  Node *new = malloc(sizeof(Node));

  //Add in data
  new->id = newID;
  strcpy(new->name, newName);
  strcpy(new->summary, newSummary);
  new->count = newCount;

  //New node has no next, yet
  new->next = NULL;

  //Add new node to the end of the list
  Node **next_p = &list->head;
  while (*next_p)
    next_p = &(*next_p)->next;
  *next_p = new;
}

有很多方法可以添加到列表的尾部。我在这里选择的方式使用指向Node * 的指针。这允许List 中的headNode 中的next 以相同的方式表示。

另一种方式稍微不那么优雅,但更具可读性。可以像您在编辑的问题中所做的那样避免这个双指针,但修改为通过列表的nexts:

  //Add new node to the end of the list
  if (!list->head->next) {
    list->head->next = new;
  } else {
    Node *temp = list->head->next; 
    while (temp->next) {
      temp = temp->next; 
    }
    temp->next = new;
  }

这两种情况都要求初始的 list->headNULL,但考虑到您的打印,这似乎已经是这种情况了。

我还更改了一些其他内容。您不应该在 C 中转换 malloc 的返回值。此外,您的 addRecord 具有返回类型 void *,而您返回 EXIT_SUCCESS。如果您尝试返回成功值,void * 可能不是正确的做法。

【讨论】:

  • while 循环完全没有效率。想象一下这个列表有 100 万个条目。
  • @Jabberwocky 这解决了他们在开头而不是结尾发生插入的问题。高效的数据结构,即使只是保留指向最后一个条目的指针,也是独立的问题。
  • head 指针之外维护tail 指针很可能比您的解决方案更简单,当然也更有效。
猜你喜欢
  • 1970-01-01
  • 2021-03-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-12-03
  • 2019-09-14
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多