【问题标题】:Deleting Every Third Node in a Linked List删除链表中的每三个节点
【发布时间】:2016-07-01 06:10:59
【问题描述】:

我有一个函数可以删除链表中的每三个节点:

void tricimate()
    {
    node * toDelete = head->next->next;
    while (toDelete != NULL)
    {
        if (toDelete->next == NULL)
        {
            tail = tail->prev;
            tail->next = NULL;
            delete toDelete;
            break;
        }
        node * ahead = toDelete->prev;
        node * behind = toDelete->next;
        ahead->next = behind;
        behind->prev = ahead;
        delete toDelete;
        toDelete = behind->next->next;
    }

}

它可以工作,但是当我尝试添加值为 47 的节点时,它不会添加它。我有这个:

29 7 2 3 31 37

什么时候我应该有这个:

29 7 2 3 31 37 47

这是我在链表后面添加新节点的代码:

void addBack(int x)
{
    node * newItem = new node;
    if (head == NULL && tail == NULL)
    {
        newItem->data = x;
        newItem->next = NULL;
        newItem->prev = NULL;
        head = newItem;
        tail = newItem;
    }
    else
    {
        newItem->data = x;
        newItem->next = NULL;
        newItem->prev = tail;
        tail->next = newItem;
        tail = newItem;
    }
}

我不明白出了什么问题,因为 addBack 以前可以工作。但是在我使用了 tricimate 功能后,它就停止了工作。我做错了什么?

【问题讨论】:

  • 删除节点后好像忘记改tail了。请注意,您的代码还有其他几个潜在的错误(例如,如果只有一个节点并且您调用 tricimate,第一行将导致运行时错误)。
  • 如果headhead->nextNULL,则node * toDelete = head->next->next; 的行为未定义。
  • @WhatsUp 我的教授告诉我们假设链表中至少有三个节点,我到底在哪里不改变尾巴?
  • @E.Reyes 您为删除每三个节点而编写的这段代码似乎有些过头了。为什么不只是有一个计数器,在你浏览列表时递增它。如果counter %3 == 0,删除你所在的当前节点?这不仅更容易编码,任何人都可以立即理解正在做什么。查看您发布的代码,很难判断您要做什么。

标签: c++ linked-list nodes doubly-linked-list


【解决方案1】:

函数可以通过以下方式定义

void tricimate()
{
    node *current = head;

    while ( current && ( current = current->next ) && ( current = current->next ) )
    {
        node *toDelete = current;

        current->prev->next = current->next;
        if ( current->next != nullptr )
        {
            current->next->prev = current->prev;
        }
        else
        {
            tail = current->prev;
        }

        current = current->next;

        delete toDelete;
    }
}

至于你的功能,那么对于初学者来说,即使它的第一条语句已经是错误的

void tricimate()
    {
    node * toDelete = head->next->next;
    //....

因为一般headhead->next 可以等于nullptr

【讨论】:

    【解决方案2】:

    查看您的 tricimate 函数,这看起来像是一个过度思考的情况,导致“过度编码”。

    要删除每三个节点(假设链表至少有 3 个节点),代码只需将计数器设置为 1,循环递增计数器,如果计数器可被 3 整除,则删除该节点.

    你应该做的是编写一个从列表中删除任何节点的函数(称之为remove_node)。如果你有,那么删除每三个节点的功能就变得简单了:

    void tricimate()
    {
       int counter = 1;
       node* curNode = head;
       while (curNode)
       {
          node *nextNode = curNode->next;  // save for the next iteration
          if ( counter % 3 == 0 )  // if we're on the node we want to delete...
             remove_node(curNode);  // remove it.
          ++counter;              // increment count
          curNode = nextNode;     // go to next node.
       }   
    }
    

    请注意,我没有实现remove_node 函数。我不知道你的链表的其余部分是如何实现的,所以如果我要尝试编写 remove_node 函数,我不想对此做太多假设。但至少,它应该有一个删除节点的功能——如果没有,它就缺少任何链表实现都应该具备的基本功能。

    【讨论】:

    • 不能对这个基本信息给予足够的支持。任何时候你有一个 Do_1 和一个 Do_N,Do_N 都应该根据 Do_1 来实现,并且只有在分析显示出显着和必要的优势后才更改为专门的案例。如果它们不是必需的,维护简单的代码应该会赢得胜利。
    • 我使用了你的函数,但是 47 的新节点仍然没有被添加到链表的后面。我的 addBack 函数有问题吗?
    • @E.Reyes -- 那么你是如何添加之前的节点的呢?他们不是也被“addBack”添加的吗?或者是否有一个添加节点的函数,它可以工作,而不是使用它,而是在addBack 函数中编写重复代码?
    • 我有一个 addBack 和 addFront 函数。在我使用 tricimate 函数之前,两者都有效。 addFront 仍然有效,但 addBack 不再有效。
    • @E.Reyes 这意味着 1) addBack 总是坏掉,或者 2) 你的 addFront 总是坏掉,或者 3) 你删除单个节点的函数总是坏掉,或者4) 1)、2) 或 3) 的组合。它与我发布的函数无关——它调用您现有的函数,如果它们有问题,则需要修复它们。您确实需要使用 good 测试用例彻底测试您的功能,以确保它们正常工作。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-07-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多