链表(删除节点)

Posted

技术标签:

【中文标题】链表(删除节点)【英文标题】:Linked list (deleting a node) 【发布时间】:2014-03-11 14:43:27 【问题描述】:

我的问题是,如果用户输入了姓氏,并且链表中有多个相同的姓氏,并且其中一个姓氏在头节点中。我如何在不删除头节点的情况下删除另一个姓氏之一。我尝试了一些我能想到的方法,但是删除了所需的节点(这很好),包括头节点(这不是我想要的......)

void NumberList::deleteCertainRecord()

string lname = "";

ListNode *ptr;
ptr = head;
string answer;
cout << "Please enter last name: "<<endl;
cin>>answer;
int num = 0;
char confirm;
while (ptr!= NULL)
    lname = ptr -> data.person.getLastName();

    if(lname == answer)
        num++;
        cout << "Person found : ";
        cout << ptr->data.person.getTitle()<<" " << ptr -> data.person.getFirstName() << " " << ptr -> data.person.getLastName() << endl << endl;
        cout << "Do you want to delete his/her record? [Y/N]" << endl;
        do
            cin >> confirm;
            if(confirm=='Y'||confirm=='y')
                    ListNode *previousNode;

                    if(isEmpty())
                        return;
                    

                    else if(head->data.person.getLastName() == answer)
                        ptr = head->next;
                        delete head; 
                        head = ptr;
                    

                    else
                        ptr = head;

                        while(ptr!=NULL && ptr->data.person.getLastName() != answer)
                            previousNode = ptr;
                            ptr = ptr->next;
                        

                        if(ptr==NULL)
                            cout<< "Node not found!" << endl;
                            return;
                        
                        else
                            previousNode->next = ptr->next;
                            delete ptr; 
                        
                    
                    cout << endl << "Deleting..."<<endl;
                    cout << "Done!!" <<endl;
                    cout << "Exiting delete function... "<<endl;
                    return;
            
            else if(confirm=='N'||confirm=='n')
                break;
            
            else
                cout << "invalid input, please enter again!!" << endl;
            
        while(confirm!='Y'&&confirm!='y'&&confirm!='n'&& confirm!='N');
        cout << endl;
    

    ptr = ptr -> next;

if (num == 0)
    cout << "\nNo person with the last name ("<< answer << ") was found!" << endl;
    cout << "Exiting delete function... "<<endl;
    return;


【问题讨论】:

您应该可以删除链表中的头节点。让指针指向下一个,删除头,然后让头指向下一个。要删除链表中具有相同姓氏的所有元素,您必须遍历整个列表。如果您不想删除头节点,则只需在第一次迭代中跳过它。制作一个执行此操作的函数。 我不确定我是否理解您的问题:您有一个包含姓氏的链表,您希望删除函数删除包含给定姓氏的节点但跳过头节点?跨度> 【参考方案1】:

您执行此操作时使用的大量代码模糊了实际意图。

您有一个人的链接列表。 给定姓氏,您要枚举列表以查找匹配项。 发现匹配后,您希望提示用户确认删除 如果确认删除,则解出发现的节点,否则列表保持不变,然后将其删除。 否则,如果未确认,则跳到下一个节点,寻找更多匹配项

如果节点实际上是头节点,那么您显然对删除部分有问题。对于刚接触链表的人来说,特殊情况的头节点逻辑总是很棘手。幸运的是,如果您使用正确的算法,它可以完全规避。假设您的列表以 NULL 正确终止,如果列表为空,则包括一个 NULL 头指针,这样的算法如下:

ListNode ** pp = &head;
while (*pp)

    if ((*pp)->data.person.getLastName() == answer &&
         confirmDelete((*pp)->data.person)) // <== TODO: write this function
    
        ListNode *victim = *pp;
        *pp = victim->next;
        delete victim;
    
    else
       // just advance to next person
        pp = &(*pp)->next;
    

这将正确删除用户,即使他们是列表中的第一个节点并且正确地为您推进头指针。它也适用于有和没有匹配条件的单节点列表,甚至是 head 为 NULL 的空列表。这种技术使用列表中的指针in作为枚举列表的机制;不仅仅是它们的值,实际的指针

最后,如果您对列表进行排序,这可以大大提高效率,但我把它留给您。

【讨论】:

以上是关于链表(删除节点)的主要内容,如果未能解决你的问题,请参考以下文章

【JS算法】 删除链表中某个节点

删除链表中间节点和a/b处的节点

删除链表中的节点后,打印节点列表显示已删除节点

删除单向链表中的某个节点

算法总结之 删除链表的中间节点和a/b处的节点(链表中间节点的重要思想)

js 删除链表中重复的节点