使用双重指针实现链表结点的插入与删除

单链表结点的插入和删除是数据结构中很基本的操作。如果单链表带有头结点,那么可以把头结点指针传递给插入和删除函数;可如果对无头结点的单链表进行上述操作,仅传递头指针(指向第一个结点的指针),在插入或删除操作改变链表头指针时,将会有些问题。
下面我们通过一个实例说明这个问题。

//单链表结点定义
struct ListNode
{
    int val;
    ListNode* next;
    ListNode(int value):val(value), next(NULL){}
};

采用“尾插法”向链表中插入结点,如果用以下代码实现:

//insert.cpp version_1
void add2Tail(ListNode* pHead, int value)
{
    ListNode* pNew = new ListNode(value);
    if(!pHead) pHead = pNew;    //?
    else
    {
        ListNode* pNode = pHead;
        while(pNode->next) pNode = pNode->next;
        pNode->next = pNew;
    }   
}

上述代码中,给add2Tail函数传递的是指向链表第一个结点的指针。可是这段代码第四行有个很严重的问题,由于当原链表为空,插入新结点时会改变“头指针”pHead,但这种改变仅仅改动的是函数内部的局部变脸pHead,原链表“头指针”(实参)实际上仍为NULL。具体可参照下面的图示:

链表指针
tips:上图中,当函数形参为指向链表第一个结点的指针时,”传值“方式传递的是地址100;而形参如果为指向头指针的指针,传递的是地址200。

因此我们要对这段代码做一些改动,给add2Tail传递指向“头指针”的指针,这样便可达到当pHead==NULL时,插入新结点后也可改动外部的pHead。代码如下:

//insert.cpp version_2
void add2Tail(ListNode** pHead, int value)
{
    ListNode* pNew = new ListNode(value);
    if(!*pHead) *pHead = pNew;    //原链表为NULL
    else
    {
        ListNode* pNode = *pHead;
        while(pNode->next) pNode = pNode->next;
        pNode->next = pNew;
    }   
}

同理,删除单链表中第一个含有某特定值的结点时,如果第一个结点就是待删除结点的话,这将改变头指针,因此也要给删除函数传递指向头指针的指针,代码如下:

void removeNode(ListNode** pHead, int value)
{
    if(!pHead || !*pHead) return;
    ListNode *p2BeRemoved = NULL;
    if((*pHead)->val == value)    //第一个结点为待删除对象
    {
        p2BeRemoved = *pHead;
        *pHead = (*pHead)->next;
    }
    else    
    {
        ListNode* pNode = *pHead;
        while(pNode->next && pNode->next->val != value) pNode = pNode->next;

        if(pNode->next && pNode->next->val == value)
        {
            p2BeRemoved = pNode->next;
            pNode->next = pNode->next->next;
        }
    }

    if(p2BeRemoved)
    {
        delete p2BeRemoved;    
        p2BeRemoved = NULL;   //删除指针后,最后将其赋与NULL值,防止野指针
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值