删除链表中重复的结点 C++

本文介绍了一种方法来删除已排序链表中的重复节点,只保留唯一值,并提供了具体的C++实现代码示例。

题目描述

在一个排序的链表中,存在重复的结点,请删除该链表中重复的结点,重复的结点不保留,返回链表头指针。例如,链表1->2->3->3->4->4->5 处理后为 1->2->5


/*
struct ListNode {
    int val;
    struct ListNode *next;
    ListNode(int x) :
        val(x), next(NULL) {
    }
};
*/
class Solution {
public:
    ListNode* deleteDuplication(ListNode* pHead)
    {
        if(pHead==NULL) return NULL;
        map<int,int> M;
        ListNode result(0);
        ListNode* fast=pHead;
        ListNode* TT=&result;
        while(fast)
        {
            M[fast->val]++;
            fast=fast->next;
        }
       
        while(pHead)
        {
            if(M[pHead->val]==1)
            {
                TT->next=pHead;
                TT=pHead;
            }
            pHead=pHead->next;
        }
        TT->next=NULL;
        return result.next;
    }
};

<think>我们正在讨论C++删除链表结点的问题。根据引用[1]和引用[3]中的示例,我们可以总结出删除链表结点的一般步骤:1.检查链表是否为空。如果为空,则无需删除。2.保存当前头结点的指针(即要删除的节点)。3.将链表的头指针指向原头结点的下一个节点。4.删除保存的原头结点,释放内存。引用[1]中的代码片段展示了从链表头开始依次清空节点的过程,其中删除结点的操作是:ListNode*pDelete= m_pHead;m_pHead =m_pHead->pNext;delete pDelete;pDelete =nullptr;引用[3]中创建了一个带头节点的链表,但在删除节点时,对于非头节点的删除有示例,但我们可以借鉴其删除操作。注意:如果链表有头节点(dummy node),那么头节点通常不存储数据,我们删除的是第一个实际数据节点。但根据问题,这里我们讨论的是删除结点(即第一个存储数据的节点)。假设链表结构为:structListNode {intval;ListNode*next;ListNode(int x) :val(x), next(nullptr){}};删除结点的步骤:if(head!= nullptr) {ListNode* temp= head;//保存当前头结点head =head->next;//将头指针指向下一个节点deletetemp;//删除原头结点}但是,注意如果链表只有一个节点,那么删除后,head将变为nullptr。另外,如果链表使用了头节点(即哨兵节点,dummy node),那么头节点后面的第一个节点才是数据节点。删除第一个数据节点(即头结点的下一个节点)的方法略有不同:if(dummy->next !=nullptr){ListNode*temp =dummy->next;dummy->next= dummy->next->next;delete temp;}但根据问题,用户没有说明链表是否带头节点,所以我们将分别讨论两种情况。情况1:不带头节点(头指针直接指向第一个数据节点)删除结点:ListNode* toDelete =head;head= head->next;delete toDelete;情况2:带头节点(头节点不存储数据,第一个数据节点在头节点之后)删除第一个数据节点(注意这里不是删除头节点,而是删除第一个有效节点):if(head->next!= nullptr) {ListNode* temp= head->next;head->next =head->next->next;deletetemp;}但是,用户的问题描述是“删除链表的头结点”,在带头节点的情况下,头节点通常是不被删除的(除非销毁整个链表)。所以,我们通常理解用户的问题是不带头节点的情况。因此,我们主要针对不带头节点的链表进行说明。示例代码(不带头节点)://假设head是链表的头指针if (head){ListNode*temp =head;head= head->next;delete temp;}注意:删除后,头指针head已经指向了新的头结点(即原来的第二个节点),如果链表只有一个节点,删除后head变为nullptr。另外,引用[5]中删除倒数第n个节点的方法,虽然不直接相关,但提供了链表操作的一般思路(使用双指针)。现在,我们根据用户的问题,给出一个完整的示例代码(不带头节点的情况):</think>在C++删除链表结点需要谨慎处理指针关系和内存释放。以下是详细步骤和示例代码: ### 删除链表结点的步骤 1. **检查链表是否为空**:若链表为空(`head == nullptr`),直接返回。 2. **备份原头结点指针**:保存当前头结点的地址,避免内存泄漏。 3. **更新头指针**:将头指针指向原头结点的下一个节点。 4. **释放内存**:删除原头结点占用的内存。 5. **置空指针**(可选):将备份指针置空,避免野指针。 ### 示例代码(不带头节点) ```cpp struct ListNode { int val; ListNode* next; ListNode(int x) : val(x), next(nullptr) {} }; void deleteHead(ListNode*& head) { // 注意使用引用传递 if (head == nullptr) return; // 空链表检查 ListNode* temp = head; // 备份原头结点 head = head->next; // 更新头指针 delete temp; // 释放内存 temp = nullptr; // 置空指针(可选) } ``` ### 示例代码(带头节点) 若链表包含**哨兵头节点**(dummy node),需删除第一个实际节点: ```cpp void deleteFirstNode(ListNode* dummyHead) { if (dummyHead->next == nullptr) return; // 无实际节点 ListNode* temp = dummyHead->next; // 备份第一个实际节点 dummyHead->next = dummyHead->next->next; // 跳过第一个节点 delete temp; // 释放内存 } ``` ### 关键说明 1. **指针传递**:必须使用`ListNode*& head`(指针的引用)或`**`二级指针,否则函数内修改无法影响外部头指针[^3][^5]。 2. **内存安全**:务必使用`delete`释放内存,避免泄漏[^1][^3]。 3. **边界处理**:空链表和单节点链表需特殊处理: ```cpp // 单节点链表删除后,head应置为nullptr ListNode* head = new ListNode(1); deleteHead(head); // 此时head变为nullptr ``` ### 示例调用 ```cpp int main() { // 创建链表 1->2->3 ListNode* head = new ListNode(1); head->next = new ListNode(2); head->next->next = new ListNode(3); deleteHead(head); // 删除结点 // 此时链表变为 2->3 } ```
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值