为链表类型数据结构实现“删除算法”

时间:2017-03-03 09:31:07

标签: c++ algorithm linked-list singly-linked-list delete-operator

这是我编写的删除函数,用于在需要时从链接列表中删除一些节点。

  • 链表按字母顺序存储

使用下面的函数,当我尝试删除链接列表的第一个元素(名为head)时,当我尝试打印链接列表(使用打印功能)并且程序崩溃时,我收到运行时错误。我知道这可能是因为没有创建新的头节点。但我不知道如何解决这个问题。这可能很简单,但无法弄清楚。你可以帮忙:))

这是删除功能:

 void deleteName(someStruct * &head, string name)
{
    someStruct * ptr = head;
    someStruct * previous;

    if(head == NULL)
    {
        cout << "empty";
    }
    else if(head->name == name)
    {
        ptr = head;
        head = head->next;
        delete head;
    }
    else
    {
        while (ptr -> name != name)
        {
            previous = ptr;
            ptr = ptr->next;
        }
        previous->next = ptr->next;
        delete ptr;
    }
}

这是打印功能:

void Print(someStruct * head)
{
    someStruct * pointer = head;
    //List is empty
    if(head == NULL)
    {
        cout << "List is empty" << endl;
    }
    else
    {
        while(pointer != NULL)
        {
            cout << pointer->name;
            cout << pointer->points << endl;
            pointer = pointer->next;
        }
    }
}

3 个答案:

答案 0 :(得分:1)

else if(head->name == name)
{
    ptr = head;
    head = head->next;
    delete head;
}

此:

  1. head的旧值保存到ptr,这是正确的
  2. 推进inout param head,这也是正确的
  3. 完全忽略ptr,其中包含您要删除的旧节点,而是删除当前列表头,让inout参数head指向已删除的节点。

    此位不正确。

  4. 只需将delete head更改为delete ptr

    注意以备将来参考:良好的结构方法是使用不需要删除的本地sentinel节点。这将删除head的特殊情况(通过添加永远不会删除临时头的不变量)并简化代码。

    void deleteName(someStruct * &head, string name)
    {
        if(!head) {
            cout << "empty";
            return;
        }
    
        someStruct tmphead;
        tmphead.next = head;
    
        for (someStruct *prev = &tmphead; prev->next; prev = prev->next) {
            if (prev->next->name == name) {
                auto todelete = prev->next;
                prev->next = todelete->next;
                delete todelete;
                // if there can be only one match, just bail out
                break;
                // otherwise, if there can be many, go round again
                // but remember to check whether prev->next is null
                // if (!prev->next) break;
            }
        }
    
        head = tmphead.next;
    }
    

    如果someStruct太大或太复杂而无法像这样使用临时头,则可以使用临时本地头指针执行相同操作,并使prev成为指向指针的指针。 / p>

答案 1 :(得分:1)

delete head块中的else if是问题所在。

将块更改为:

else if(head->name == name) {
    //ptr = head; You don't have to. You already have initialized ptr with head
    head = head->next;
    delete ptr; //Delete prt not head, head is now the next node which you assigned in previous line
}

答案 2 :(得分:1)

else if(head->name == name){
   ptr = head;
   head = head -> next;
   delete ptr;  // change to this statement n you're good to go
}