在O(1)时间内删除链表节点

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

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

void DeleteNode(ListNode** pListHead, ListNode* pToBeDeleted);

 

算法思路:

一般我们是从头节点开始遍历,知道找到要删除的节点的前面一个节点,但是时间复杂度为O(n)
改进思路:找到要删除的节点pDeleteNode的下一个节点pNext,把下一个节点的值(pNext->m_nValue)
赋给要删除的节点(PDeleteNode->m_nValue),再把要删除的节点指向下一个节点的下一个节点:(pDelete->m_pNext = pNext->m_pNext)
然后再把pNext节点删除,pNext = NULL;

 

代码:

// DeleteNodeInList.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"
#include<iostream>
using namespace std;

/*
算法思路:
一般我们是从头节点开始遍历,知道找到要删除的节点的前面一个节点,但是时间复杂度为O(n)
改进思路:找到要删除的节点pDeleteNode的下一个节点pNext,把下一个节点的值(pNext->m_nValue)
赋给要删除的节点(PDeleteNode->m_nValue),再把要删除的节点指向下一个节点的下一个节点:(pDelete->m_pNext = pNext->m_pNext)
然后再把pNext节点删除,pNext = NULL;


*/


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

void DeleteNode(ListNode** pListHead, ListNode* pToBeDeleted)
{
	if (!pListHead || !pToBeDeleted)
	{
		return;
	}
	if (pToBeDeleted->m_pNext != NULL)//删除的节点不是尾巴节点
	{
		ListNode* p = pToBeDeleted->m_pNext;
		pToBeDeleted->m_nValue = p->m_nValue;
		pToBeDeleted->m_pNext = p->m_pNext;

		delete p;
		p = 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 = pToBeDeleted->m_pNext;
		delete pToBeDeleted;
		pToBeDeleted = NULL;
	}

}


/*
分析: 对于n-1个非尾巴节点而言,我们可以在O(1)的时间把下一个节点的内存复制覆盖要删除的节点,并删除下一个节点;
对于尾巴节点而言,由于仍然需要顺序查找,时间复杂度是O(n).因此总的平均时间复杂度是[(n-1)*O(1)+O(n)]/n,因此平均时间
复杂度是O(1);


*/


int _tmain(int argc, _TCHAR* argv[])
{
	return 0;
}


对于n-1个非尾巴节点而言,我们可以在O(1)的时间把下一个节点的内存复制覆盖要删除的节点,并删除下一个节点;

对于尾巴节点而言,由于仍然需要顺序查找,时间复杂度是O(n).因此总的平均时间复杂度是[(n-1)*O(1)+O(n)]/n,

因此平均时间复杂度是O(1);

 

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值