• [刷题] 剑指offer 面试题18:删除链表节点


    要求

    • 给定单向链表的头指针和一个节点指针,在O(1)时间内删除该节点
    • 常规思路:从头节点a开始顺序遍历,发现p指向要删除的节点i,然后把p的m_pNext指向i的下一个节点j,时间复杂度O(n)
    • O(1)的思路:把i的下一个节点j的内容复制到i,然后令i指向j的下一个节点
    • 考虑特殊情况:
      • 链表只有一个节点:删除该节点
      • 删除尾节点:遍历至倒数第二个节点,删除

    DeleteNodeList.cpp

      1 #include <cstdio>
      2 #include "List.h"
      3 
      4 void DeleteNode(ListNode** pListHead,ListNode* pToBeDeleted){
      5     if(!pListHead || !pToBeDeleted)
      6         return;
      7     if(pToBeDeleted->m_pNext != nullptr){
      8         ListNode* pNext = pToBeDeleted->m_pNext;
      9         pToBeDeleted->m_nValue = pNext->m_nValue;
     10         pToBeDeleted->m_pNext = pNext->m_pNext;
     11         delete pNext;
     12         pNext=nullptr;
     13     }
     14     else if(*pListHead == pToBeDeleted){
     15         delete pToBeDeleted;
     16         pToBeDeleted = nullptr;
     17         *pListHead = nullptr;
     18     }else{
     19         ListNode* pNode = *pListHead;
     20         while(pNode->m_pNext != pToBeDeleted){
     21             pNode = pNode->m_pNext;
     22         }
     23         pNode->m_pNext = nullptr;
     24         delete pToBeDeleted;
     25         pToBeDeleted = nullptr;
     26     }
     27 }
     28 
     29 void Test(ListNode* pListHead,ListNode* pNode){
     30     printf("The original list is:
    ");
     31     PrintList(pListHead);
     32     
     33     printf("The node to be deleted is:
    ");
     34     PrintListNode(pNode);
     35     
     36     DeleteNode(&pListHead,pNode);
     37     
     38     printf("The result list is:
    ");
     39     PrintList(pListHead);
     40 }
     41 
     42 void Test1(){
     43     ListNode* pNode1 = CreateListNode(1);
     44     ListNode* pNode2 = CreateListNode(2);
     45     ListNode* pNode3 = CreateListNode(3);
     46     ListNode* pNode4 = CreateListNode(4);
     47     ListNode* pNode5 = CreateListNode(5);
     48     
     49     ConnectListNodes(pNode1,pNode2);
     50     ConnectListNodes(pNode2,pNode3);
     51     ConnectListNodes(pNode3,pNode4);
     52     ConnectListNodes(pNode4,pNode5);
     53     
     54     Test(pNode1,pNode3);
     55     
     56     DestroyList(pNode1);
     57 }
     58 
     59 void Test2()
     60 {
     61     ListNode* pNode1 = CreateListNode(1);
     62     ListNode* pNode2 = CreateListNode(2);
     63     ListNode* pNode3 = CreateListNode(3);
     64     ListNode* pNode4 = CreateListNode(4);
     65     ListNode* pNode5 = CreateListNode(5);
     66 
     67     ConnectListNodes(pNode1, pNode2);
     68     ConnectListNodes(pNode2, pNode3);
     69     ConnectListNodes(pNode3, pNode4);
     70     ConnectListNodes(pNode4, pNode5);
     71 
     72     Test(pNode1, pNode5);
     73 
     74     DestroyList(pNode1);
     75 }
     76 
     77 // 链表中有多个结点,删除头结点
     78 void Test3()
     79 {
     80     ListNode* pNode1 = CreateListNode(1);
     81     ListNode* pNode2 = CreateListNode(2);
     82     ListNode* pNode3 = CreateListNode(3);
     83     ListNode* pNode4 = CreateListNode(4);
     84     ListNode* pNode5 = CreateListNode(5);
     85 
     86     ConnectListNodes(pNode1, pNode2);
     87     ConnectListNodes(pNode2, pNode3);
     88     ConnectListNodes(pNode3, pNode4);
     89     ConnectListNodes(pNode4, pNode5);
     90 
     91     Test(pNode1, pNode1);
     92 
     93     DestroyList(pNode1);
     94 }
     95 
     96 // 链表中只有一个结点,删除头结点
     97 void Test4()
     98 {
     99     ListNode* pNode1 = CreateListNode(1);
    100 
    101     Test(pNode1, pNode1);
    102 }
    103 
    104 // 链表为空
    105 void Test5()
    106 {
    107     Test(nullptr, nullptr);
    108 }
    109 int main(int argc,char* argv[]){
    110     Test1();
    111     Test2();
    112     Test3();
    113     Test4();
    114     Test5();
    115     return 0;
    116 }

    List.h

     1 struct ListNode{
     2     int m_nValue;
     3     ListNode* m_pNext;
     4 };
     5 
     6 ListNode* CreateListNode(int value);
     7 void ConnectListNodes(ListNode* pCurrent,ListNode* pNext);
     8 void PrintListNode(ListNode* pNode);
     9 void PrintList(ListNode* pHead);
    10 void DestroyList(ListNode* pHead);
    11 void AddToTail(ListNode** pHead,int value);
    12 void RemoveNode(ListNode** pHead,int value);

    List.cpp

     1 #include "List.h"
     2 #include <stdio.h>
     3 #include <stdlib.h>
     4 
     5 ListNode* CreateListNode(int value){
     6     ListNode* pNode = new ListNode();
     7     pNode->m_nValue = value;
     8     pNode->m_pNext = nullptr;
     9     return pNode;
    10 }
    11 
    12 void ConnectListNodes(ListNode* pCurrent,ListNode* pNext){
    13     if(pCurrent == nullptr){
    14         printf("Error to connect two nodes.
    ");
    15         exit(1);
    16     }
    17     pCurrent->m_pNext = pNext;    
    18 }
    19 
    20 void PrintListNode(ListNode* pNode){
    21     if(pNode == nullptr){
    22         printf("The node is nullptr
    ");
    23     }
    24     else{
    25         printf("The key in node is %d.
    ",pNode->m_nValue);
    26     }
    27 }
    28 
    29 void PrintList(ListNode* pHead){
    30     printf("PrintList starts.
    ");
    31     ListNode* pNode = pHead;
    32     while(pNode != nullptr){
    33         printf("%d	",pNode->m_nValue);
    34         pNode = pNode->m_pNext;
    35     }
    36     printf("
    PrintList ends.
    ");
    37 }
    38 
    39 void DestroyList(ListNode* pHead){
    40     ListNode* pNode = pHead;
    41     while(pNode != nullptr){
    42         pHead = pHead->m_pNext;
    43         delete pNode;
    44         pNode = pHead;
    45     }
    46 }
    47 
    48 void AddToTail(ListNode** pHead,int value){
    49     ListNode* pNew = new ListNode();
    50     pNew->m_nValue = value;
    51     pNew->m_pNext = nullptr;
    52     if(*pHead == nullptr){
    53         *pHead = pNew;
    54     }else{
    55         ListNode* pNode = *pHead;
    56         while(pNode->m_pNext != nullptr)
    57             pNode = pNode->m_pNext;
    58         pNode->m_pNext = pNew;
    59     }
    60 }
    61 
    62 void RemoveNode(ListNode** pHead,int value){
    63     if(pHead == nullptr || *pHead == nullptr)
    64         return;
    65     ListNode* pToBeDeleted = nullptr;
    66     if((*pHead)->m_nValue == value){
    67         pToBeDeleted = *pHead;
    68         *pHead = (*pHead)->m_pNext;
    69     }else{
    70         ListNode* pNode = *pHead;
    71         while(pNode->m_pNext != nullptr && pNode->m_pNext->m_nValue != value)
    72             pNode = pNode->m_pNext;
    73         if(pNode->m_pNext != nullptr && pNode->m_pNext->m_nValue == value){
    74             pToBeDeleted = pNode->m_pNext;
    75             pNode->m_pNext = pNode->m_pNext->m_pNext;
    76             }
    77         }
    78         if(pToBeDeleted != nullptr){
    79             delete pToBeDeleted;
    80             pToBeDeleted = nullptr;
    81         }
    82 }

    总结

    • 操作数据用指针(如修改数据的内容),操作指针用指针的指针(如修改指针的指向)
    • 想要改变一个值,就要先得到它的地址,想要改变一个指针,就要先得到指针的地址(指针的指针)
    • 在.h中定义数据结构体,声明函数;在.cpp中实现函数
    • new和delete配套使用,new申请内存,delete释放new分配的对象指针指向的内存,之后还要清空指针才能完成彻底删除
  • 相关阅读:
    CSPS模拟 49
    StrGame
    CSPS模拟 48
    [没有证明]原根求法
    CSPS模拟 47
    CSPS模拟 46
    CSPS模拟 45 乔迁之喜
    CSPS模拟 44
    平衡二叉树
    go语言学习--指针数组和数组指针
  • 原文地址:https://www.cnblogs.com/cxc1357/p/12027597.html
Copyright © 2020-2023  润新知