【问题标题】:Extra node after filling a linked list in C在C中填充链表后的额外节点
【发布时间】:2019-11-22 12:31:23
【问题描述】:

我有一个整数(例如:123),我需要将它反向(逐位)存储在链表中。 但我似乎在列表末尾有一个额外的数字。 例如:807需要存储为“7 -> 0 -> 8” 但我的输出是“7 -> 0 -> 8 -> -1094795586”。

这是 leetcode 题“加两个数”的问题。

//我需要用结果填充“l”(反转)

void FillList(struct ListNode* l, unsigned long long int result)
{
    struct ListNode *newNode = l;
    newNode->val = 0;
    while(result != 0)
    {
        newNode->val = result % 10;
        result /= 10;
        newNode->next = malloc(sizeof(struct ListNode));
        newNode = newNode->next;
    }
    newNode->next = NULL;
} 

输出是“7 -> 0 -> 8 -> -1094795586”,而不是“7 -> 0 -> 8”。

【问题讨论】:

  • 你在循环中做的最后一件事是分配一个新节点而不给它任何值。
  • 我可以只释放循环后的最后一个节点吗?
  • 那将是一个肮脏的补丁,而不是一个解决方案。
  • 谢谢。我明白了。

标签: c memory linked-list


【解决方案1】:

问题是你总是分配一个新的下一个节点,即使没有下一个值。

while(result != 0)
{
    newNode->val = result % 10;
    result /= 10;
    newNode->next = malloc(sizeof(struct ListNode));  // <<<<<<-----
    newNode = newNode->next;
}

这有点棘手,因为您想在每次迭代中分配一个注释,但您已经从分配的节点开始,使第一次迭代成为一种特殊情况。

我们可以通过记住前一个节点是什么来解决这个问题。

void FillList(struct ListNode* node, unsigned long long int num)
{
    struct ListNode* prev = NULL;
    do {
        // Since prev starts NULL this only happens the second time.
        if( prev ) {
            prev->next = node = malloc(sizeof(struct ListNode));
        }
        node->val = num % 10;

        // It's safer to always ensure everything is initialized.
        node->next = NULL;
        num /= 10;

        // Store the current node as the previous one.
        prev = node;
    } while(num != 0);
}

此外,通过使用 do/while 循环,我们确保它始终运行一次,即使 num 从 0 开始。这消除了 0 作为特殊情况。

【讨论】:

    【解决方案2】:

    假设我们要创建的结果只是7

    newNode->val = 0; // sets l to 0, OK so far
    while(result != 0) // true!
    {
        newNode->val = result % 10; // gets changed to 7
        newNode->next = malloc(sizeof(struct ListNode)); // you create a new node!
                                                         // (without assigning a value to it!)
        // now getting back to the while, discovering that you won't enter it again
        // but the next node is already created!
    }
    

    你需要避免这个多余的节点。一种可能的方法(对代码的最小更改):

    struct ListNode* newNode = l;
    for(;;)
    {
        newNode->val = result % 10;
        result /= 10;
        if(result == 0)
            break;
        // at this point we now KNOW that we yet need another node, so we create it
        newNode->next = malloc(sizeof(struct ListNode));
        newNode = newNode->next;
    }
    newNode->next = NULL;
    

    您会发现对l 的第一个赋值(当newNode 仍然指向同一个节点时)也涵盖了0 的特殊情况,因为0 % 100 / 10 仍然保持为0。 ..

    【讨论】:

    • 谢谢你,工作就像一个魅力,易于理解。
    【解决方案3】:

    在您的情况下,头节点 l 始终不等于 NULL。 并假设你的头节点 l 是 NULL 并且你的代码可以是

    void FillList(struct ListNode* l, unsigned long long int result){
        struct ListNode *newNode = NULL,*pNode=NULL;
        do{
          newNode=malloc(sizeof(struct ListNode));
          newNode->val = result % 10;
          newNode->next = NULL;
          if(l==NULL){
             l=newNode;
             p=newNode;
          }else{
             p->next=newNode;
          }
        }while((result /= 10)>0);
    } 
    

    【讨论】:

      猜你喜欢
      • 2014-09-03
      • 2012-06-25
      • 1970-01-01
      • 2020-04-30
      • 2013-07-16
      • 2018-03-30
      • 1970-01-01
      • 2021-12-23
      • 1970-01-01
      相关资源
      最近更新 更多