如何删除符合特定值的双向链表中的所有项?

时间:2016-02-18 22:19:28

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

我有一个任务,我必须编写一个函数,可以删除双向链表的任何部分,其中有一个具有预定输入的值。我在这方面工作了很长一段时间,而且我发现我编写的代码还有其他任何问题。作业如下:

  

编写C ++函数以删除链表中的节点。该函数有两个参数 - 链表的头部和要删除的值。它应该删除包含要删除的值的所有节点。它应该返回链表的头部。

     

链表结构:

struct node
{
    int value;
    node *next;
    node *prev;
};
node *DeleteNode(node *head, int value){
node *tmp=head;
while(tmp!=NULL){
    if(tmp->value==value){
        if(tmp==head){
            head=head->next;
            head->prev=NULL;
            delete tmp;
            tmp=head;
        }
        else if(tmp->next==NULL){
            node *temp=tmp;
            temp->prev->next=NULL;
            delete tmp;
            tmp=temp;
        }
        else{
            node *node1=tmp;
            node1->prev->next=node1->next;
            node1->next->prev=node1->prev;
            delete tmp;
            tmp=node1;
        }
    }
    tmp=tmp->next;
}
return head;}

所以,当它运行

的测试时
  

1< - > 2 - < - > 3 - < - > 4

并且需要删除所有3,它会得到

的结果
  

1< - > 2 - < - > 4

这是正确的。它适用于需要移除头部项目的其他示例,以及需要移除尾部的示例。它已经与所有期望的功能一起工作.... BESIDES ......

  

2 - < - > 2 - < - > 2 - < - > 2 - < - > 65 - < - > 83

需要删除2s。它只是得到

的结果
  

2'; - > 65 - < - > 83

因此出于某种原因,额外的2被留下了。任何猜测?我提供了为此问题提供的所有内容。我认为问题可能在我的部分中删除双向链表中的中间项,但我完全迷失了。非常感谢!

4 个答案:

答案 0 :(得分:3)

这看起来很可疑(添加一些空格):

node* node1 = tmp;
node1->prev->next = node1->next;
node1->next->prev = node1->prev;
delete tmp;
tmp = node1;

node1只是tmp的别名。它实际上并没有用于任何其他目的。然后,您delete tmp并将其分配给node1 - 这正是您刚刚删除的内容!

您可能想要这样做:

tmp->prev->next = tmp->next;
tmp->next->prev = tmp->prev;
node* prev = tmp->prev;
delete tmp;
tmp = prev; 

答案 1 :(得分:2)

当您的初始头节点与值匹配时,会出现问题。

在此,您将下一个节点设置为新头并删除旧节点,然后将tmp设置为新头,

if(tmp==head){
        head=head->next;
        head->prev=NULL;
        delete tmp;
        tmp=head;
 }

然后退出if语句时设置

tmp = tmp-> next

因此,在if块中,将当前节点设置为下一个节点,然后删除以前的节点,然后在退出if语句时再次向下移动到下一个节点,有效地跳过新头节点一共。

答案 2 :(得分:1)

我除了Barry的回答:

node *temp=tmp;
temp->prev->next=NULL;
delete tmp;
tmp=temp;

这将为当前节点temp设置别名tmp,然后将前一个节点的next指针设置为NULL,删除当前节点并将tmp指针设置为temp,但这只是刚刚删除的节点的别名。您可能希望node *temp=tmp->prev;将您的tmp设置为新的最后一个元素。

可能导致您的错误的原因是,与您的价值比较,您致电

tmp=tmp->next;

最后,转到下一个节点。你应该将它包装在else块中,只有在你的值不匹配时才执行。

答案 3 :(得分:0)

当定义双链表时,通常会定义一个包含两个指针的单独结构:一个指向列表头部的指针和另一个指向列表尾部的指针。例如

struct list
{
    node *head = nullptr;
    node *tail = nullptr;
    //...
};

同样在结构内部声明了处理列表的成员函数。

然而,如果要使用您的方法,那么删除具有等于给定值的值的所有节点的函数可以看起来如此示范程序中所示

#include <iostream>

struct node
{
    int value;
    node *next;
    node *prev;
};

void display( node *head )
{
    for ( ; head; head = head->next )
    {
        std::cout << head->value << ' ';
    }
    std::cout << std::endl;
}

node * AppendNode( node *head, int value )
{
    node *tmp = new node { value, nullptr, nullptr };

    if ( !head )
    {
        head = tmp;
    }
    else
    {
        node *prev = head;
        while ( prev->next ) prev = prev->next;
        tmp->prev = prev;
        prev->next = tmp;
    }

    return head;
}

node * DeleteNode( node *head, int value )
{
    for ( node *current = head; current; )
    {
        if ( current->value == value )
        {
            node *tmp = current;

            if ( current->next )
            {
                current->next->prev = current->prev;
            }

            if ( current->prev )
            {
                current->prev->next = current->next;
                current = current->next;
            }
            else
            {
                head = current->next;
                current = head;
            }

            delete tmp;
        }
        else
        {
            current = current->next;
        }            
    }

    return head;
}    

int main()
{
    node *head = nullptr;

    for ( int x : { 2, 2, 2, 2, 65, 83 } ) head = AppendNode( head, x );

    display( head );

    head = DeleteNode( head, 2 );

    display( head );

    head = DeleteNode( head, 83 );

    display( head );

    head = DeleteNode( head, 65 );

    display( head );
}

它的输出是

2 2 2 2 65 83 
65 83 
65