zoukankan      html  css  js  c++  java
  • 面试题13:在O(1)时间删除链表结点

    题目:给定单向链表的头指针和一个结点指针,定义一个函数在O(1)时间删除该结点。

     链表结点与函数的定义如下:

    struct ListNode
    {
        int m_nValue;
        ListNode* m_pNext;
    };
    
    void DeleteNode(ListNode** pListHead,ListNode* pToBeDeleted);

    删除结点的操作我们经常碰到,比如一个链表A->B->C->D->E->F->G。如果我们要删除结点E,那么我们只需要让结点D的指针指向结点F即可,但是我们现在只给出链表头结点的指针以及结点E的指针,而又是单项链表,不能在O(1)时间内得到被删除结点前面的那一个结点的指针,所以我们原先的方法是不能在O(1)时间内删除结点E的。

    那么既然我们不能获得被删除结点的前一个结点的指针,我们就需要转变思路来考虑是否能够用过被删除结点后一个结点的指针来解决方法。因此被删除结点E的后一个结点指针是很容易得到的,也就是E->m_pNext。

    那么我们可能会想到如下方法:获得F的指针,将F的数据赋值给E,然后让E指向F的下一个结点。这里虽然删除的是结点F,但是相当于删除的是结点E。并且是O(1)时间复杂度。下面给出代码实例:

    View Code
    #include<iostream>
    #include<stdlib.h>
    #include<stack>
    using namespace std;
    
    //链表结构
    struct ListNode
    {
        int m_nValue;
        ListNode* m_pNext;
    };
    
    //创建一个链表结点
    ListNode* CreateListNode(int value)
    {
        ListNode *pNode=new ListNode();
        pNode->m_nValue=value;
        pNode->m_pNext=NULL;
        return pNode;
    
    }
    
    
    //遍历链表中的所有结点
    void PrintList(ListNode* pHead)
    {
        ListNode *pNode=pHead;
        while(pNode!=NULL)
        {
            cout<<pNode->m_nValue<<" ";
            pNode=pNode->m_pNext;
        }
        cout<<endl;
    }
    
    void ConnectListNode(ListNode* pCurrent,ListNode* pNext)//连接两个结点
    {
        if(pCurrent==NULL)
        {
            cout<<"前一个结点不能为空"<<endl;
            exit(1);
        }
        else
        {
            pCurrent->m_pNext=pNext;
        }
    }
    
    void DeleteNode(ListNode** pListHead,ListNode* pToBeDeleted)
    {
        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;
        }
    }
    
    void main()
    {
        //创建结点
        ListNode* pNode1=CreateListNode(1);//创建一个结点
        ListNode* pNode2=CreateListNode(2);//创建一个结点
        ListNode* pNode3=CreateListNode(3);//创建一个结点
        ListNode* pNode4=CreateListNode(4);//创建一个结点
        ListNode* pNode5=CreateListNode(5);//创建一个结点
        ListNode* pNode6=CreateListNode(6);//创建一个结点
        ListNode* pNode7=CreateListNode(7);//创建一个结点
        //连接结点
        ConnectListNode(pNode1,pNode2);//连接两个结点
        ConnectListNode(pNode2,pNode3);//连接两个结点
        ConnectListNode(pNode3,pNode4);//连接两个结点
        ConnectListNode(pNode4,pNode5);//连接两个结点
        ConnectListNode(pNode5,pNode6);//连接两个结点
        ConnectListNode(pNode6,pNode7);//连接两个结点
        //打印链表
        PrintList(pNode1);//打印
        //删除结点
        DeleteNode(&pNode1,pNode3);
        //打印链表
        PrintList(pNode1);//打印
    
        system("pause");
    
    }

    输出结果:

    1 2 3 4 5 6 7
    1 2 4 5 6 7

  • 相关阅读:
    对于Netty的十一个疑问
    IDEA中:求类似于eclipse中的ctrl+shift+o,我之前配置过后来重装找不到了,不是alt+enter也不是勾选自动导包
    Android之assets资源目录的各种操作
    五种方式让你在java中读取properties文件内容不再是难题
    Delphi 接口使用中,对象生命周期管理,如何释放需要注意的问题
    利用FR导出PDF汉字乱码的处理
    赵伟国辞去TCL集团董事等职位,紫光参与TCL定增浮盈已超7亿
    中山的房价
    webpack
    为什么需要索引
  • 原文地址:https://www.cnblogs.com/xwdreamer/p/2472102.html
Copyright © 2011-2022 走看看