【问题标题】:having hard time debugging deletion of head node in a circular linked list很难调试循环链表中头节点的删除
【发布时间】:2020-10-09 05:52:56
【问题描述】:

我正在学习数据结构,并正在练习循环链表上的问题。所以,我应该写一个函数来删除循环链表的head 节点,所以我想出了这段代码-

void del_head(struct node** head, struct node** tail)
{
    struct node* new_head = (*head)->next;
    free(*head);
    *head = new_head;
    (*tail)->next = *head;
}

调试后发现tail没有更新。

我很难找到问题所在。

感谢任何帮助,谢谢

【问题讨论】:

  • “尾巴没有更新”到底是什么意思。提供minimal verifiable example,包括您用来得出该结论的测试日志/结果。代码的一个问题是它没有正确处理删除头部时列表包含单个元素的情况(即头部和尾部相同)。
  • 如果您的列表是真正的循环,这将是灾难的秘诀。 IE。单节点列表将有 三个 指针都引用同一个节点:head 指针、tail 指针、节点自己的 next 指针(例如,节点指向自身,因为列表毕竟是循环的)。怀有这种洞察力的花絮,上述内容如何落到实处?相信我。纸、铅笔、用于指针的单行框、用于结构的双行框以及表示什么指向什么的箭头,在学习动态数据结构管理实践时将非常有启发性。
  • 循环单链表不需要head指针。只是一个tail。用tail->next找到头部。

标签: c pointers linked-list dynamic-memory-allocation circular-list


【解决方案1】:

调试后发现tail没有更新。

您的代码对于具有多个1 节点的循环列表非常有效,并且由于您正在删除head 节点,因此如果列表将具有多个1 节点,tail 将指向head 节点删除后的同一节点,因为它指向删除前的节点。

考虑循环列表只有一个节点的情况:

      head---|      
             |
             |
   tail----| |
          ---------------
          | data | next |-------|
          ---------------       |
             |                  |
             |------------------|

headtail 和节点 next 都指向同一个节点。
对于这种情况,您的代码最终将访问已释放的内存。

你可以这样做:

void del_head(struct Node** head, struct Node** tail) {

    // validate head and tail pointer
    if (!(head && *head)) {
        printf ("Invalid head pointer\n");
        return;
    }

    if (!(tail && *tail)) {
        printf ("Invalid tail pointer\n");
        return;
    }

    struct Node* x = *head;
    if (*tail == x) {
        // the circular list has only one node
        *head = *tail = NULL;
    } else {
        *head = (*tail)->next = x->next;
    }

    x->next = NULL;
    free(x);
}

【讨论】:

  • 良好的错误检查和有趣的主动清理.next 指针。紫外线。甚至可以将整个节点归零:memset(x, sizeof *x, 0);
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-30
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多