- 题目
给定单向链表的头指针和一个结点指针,定义一个函数在O(1)时间内删除该结点,链表结点与函数定义如下。
struct ListNode
{
int _data;
struct ListNode* _next;
};
void DeleteNode(ListNode **pHead,ListNode *pDelNode)
思路分析:单链表中删除结点pDel的方法一般是遍历链表找到删除结点的前一个结点pPre,将pPre的next域指向pDel的下一个结点再删除pDel,这样做可以达到删除的要求但是不满足题上所述的时间复杂度为O(1)的要求,那么我们是不是一定要得到前一个结点呢?我们可以将pDel的下一个结点的内容覆盖到pDel上,再把下一个节点删除,这样就相当于删除了 pDel结点,这种方法满足了时间复杂度的问题,但是如果被删除的结点在尾部没有下一个结点怎么办呢?,这个时候我们就需要从头遍历链表,完成删除操作,最后需要注意的是链表中只有一个结点时,删除后要把头结点置NULL。下面我们来看看具体的实现代码。
#include<stdio.h>
#include<stdlib.h>
typedef struct ListNode
{
int _data;
struct ListNode* _next;
}ListNode;
void DeleteNode(ListNode **pHead,ListNode *pDelNode)
{
if (NULL == pHead || NULL == *pHead || NULL == pDelNode)
return;
if (pDelNode->_next != NULL)//删除的不是尾结点
{
ListNode *pNext = pDelNode->_next;
pDelNode->_data = pNext->_data;
pDelNode->_next = pNext->_next;
free (pNext);
pNext = NULL;
}
else if (*pHead == pDelNode)//链表中只有一个节点
{
free(pDelNode);
pDelNode = NULL;
*pHead = NULL;
}
else//链表中有很多节点删除尾结点
{
ListNode *pCur = *pHead;
while (pCur->_next != pDelNode)//此处假设删除节点在链表内
pCur = pCur->_next;
pCur->_next = pDelNode->_next;
free(pDelNode);
pDelNode = NULL;
}
}
void DelTest()//测试函数
{
ListNode* pHead = (ListNode*)malloc(sizeof(ListNode));
pHead->_data = 0;
pHead->_next = NULL;
ListNode* pCur = pHead;
for (size_t i = 1; i < 10; i++)
{
ListNode* pNew = (ListNode*)malloc(sizeof(ListNode));
pNew->_data = i;
pNew->_next = NULL;
pCur->_next = pNew;
pCur = pNew;
}
ListNode* pDel = pHead->_next->_next->_next;
ListNode* pTail = pHead;
while (pTail->_next)
pTail = pTail->_next;
ListNode* pHead1 = NULL;
DeleteNode(&pHead, pHead);//删除头节点
DeleteNode(&pHead, pTail);//删除尾结点
DeleteNode(&pHead, pDel);//删除任意节点
DeleteNode(NULL, pTail);//特殊NULL测试
DeleteNode(&pHead1, pDel);//链表为空
DeleteNode(&pHead, NULL);//删除节点为空
}
int main()
{
DelTest();
system("pause");
return 0;
}
注意上述代码,是基于删除的结点在来链表中的假设完成的,因为判断结点是否在链表中需要O(n)的时间,无法满足题意的要求,这项工作可以交给函数的调用者自己处理。