剑指Offer系列---(16)在O(1)时间删除链表结点

1.题目描述:
给定单向链表的头指针和一个结点指针,定义一个函数在O(1)时间删除该结点。链表结点与函数的定义如下:
struct ListNode
{
  int m_nValue;
  ListNode* m_pNext;
};
void DeleteNode(ListNode** pListHead,ListNode* pToBeDeleted);
2.分析:
1)在单向链表中删除一个结点,最常规的做法无疑是从链表的头结点开始,顺序遍历查找要删除的结点,并在链表中删除该节点。
2)如果我们把下一个结点的内容复制到需要删除的结点上覆盖原来的内容,再把下一个结点删除,那就相当于把当前结点删除了。
3)此方法的前提是结点存在于链表内,删除最后一个结点时比较特殊。
3.源代码:

//  Copyright (c) 2015年 skewrain. All rights reserved.

#include <iostream>
#include <stdio.h>
#include <stack>
using namespace std;

struct ListNode
{
    int m_nValue;
    ListNode *m_pNext;
};

ListNode* CreateLink(int a[],int k)
{
    ListNode *Head = NULL,*q = NULL;
    for (int i=0; i<k; i++)
    {
        ListNode *pNew = new ListNode();
        pNew->m_nValue = a[i];
        pNew->m_pNext = NULL;
        
        if(Head==NULL)
        {
            Head = pNew;
            q = pNew;
        }
        else
        {
            q->m_pNext = pNew;
            q = pNew;
        }
    }
    return Head;
}

//从头到尾打印列表
void printLink(ListNode *pHead)
{
    cout<<"链表内容为:";
    ListNode *p = pHead;
    while (p) {
        cout<<p->m_nValue<<" ";
        p=p->m_pNext;
    }
    cout<<endl;
}

void DeleteNode(ListNode** pListHead,ListNode* pToBeDeleted)
{
    if (!pListHead || !pToBeDeleted) {
        return;
    }
    //要删除的结点不是尾结点
    if (pToBeDeleted->m_pNext!=NULL)
    {
        ListNode* pNext = pToBeDeleted->m_pNext;
        pToBeDeleted->m_nValue = pNext->m_nValue;
        pToBeDeleted->m_pNext = pNext->m_pNext;
        
        delete pNext;
        pNext = NULL;
    }
    //链表只有一个结点,删除头结点(也是尾结点)
    else if (*pListHead == pToBeDeleted)
    {
        delete pToBeDeleted;
        pToBeDeleted = NULL;
        *pListHead = NULL;
    }
    //链表中有多个结点,删除尾结点
    else
    {
        ListNode* pNode = *pListHead;
        while (pNode->m_pNext != pToBeDeleted) {
            pNode = pNode->m_pNext;
        }
        pNode->m_pNext = NULL;
        delete pToBeDeleted;
        pToBeDeleted = NULL;
    }
}

//--------测试用例--------
//1.链表中有多个结点,删除尾结点
void Test1()
{
    cout<<"测试用例1"<<endl;
    int a[] = {1,2,3};
    ListNode *ptr = CreateLink(a,3);
    ListNode *del = ptr;
    while (del->m_nValue!=3) {
        del = del->m_pNext;
    }
    cout<<"删除结点前:";
    printLink(ptr);
    DeleteNode(&ptr, del);
    cout<<"删除结点后:";
    printLink(ptr);
}

//2.链表中有多个结点,删除尾结点
void Test2()
{
    cout<<"测试用例2"<<endl;
    int a[] = {1,2,3};
    ListNode *ptr = CreateLink(a,3);
    ListNode *del = ptr;
    while (del->m_nValue!=1) {
        del = del->m_pNext;
    }
    cout<<"删除结点前:";
    printLink(ptr);
    DeleteNode(&ptr, del);
    cout<<"删除结点后:";
    printLink(ptr);
}

//3.链表中有多个结点,删除尾结点
void Test3()
{
    cout<<"测试用例3"<<endl;
    int a[] = {1,2,3};
    ListNode *ptr = CreateLink(a,3);
    ListNode *del = ptr;
    while (del->m_nValue!=2) {
        del = del->m_pNext;
    }
    cout<<"删除结点前:";
    printLink(ptr);
    DeleteNode(&ptr, del);
    cout<<"删除结点后:";
    printLink(ptr);
}

//4.链表中有多个结点,删除尾结点
void Test4()
{
    cout<<"测试用例4"<<endl;
    int a[] = {1};
    ListNode *ptr = CreateLink(a,1);
    ListNode *del = ptr;
    while (del->m_nValue!=1) {
        del = del->m_pNext;
    }
    cout<<"删除结点前:";
    printLink(ptr);
    DeleteNode(&ptr, del);
    cout<<"删除结点后:";
    printLink(ptr);
}

//5.链表中有多个结点,删除尾结点
void Test5()
{
    cout<<"测试用例5"<<endl;
    ListNode *ptr = NULL;
    ListNode *del = ptr;
    cout<<"删除结点前:";
    printLink(ptr);
    DeleteNode(&ptr, del);
    cout<<"删除结点后:";
    printLink(ptr);
}
int main(int argc,char *argv[]){

    Test1();
    Test2();
    Test3();
    Test4();
    Test5();
    return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值