在O(1)时间内删除单向链表结点

原理:

1.若待删结点在单链表中间,则获取结点下一个结点的值,并复制给待删结点,然后删除待删结点的下一个结点。

2.若待删结点在单链表尾部,则顺序遍历单链表,删除。

3.若链表只有一个结点,正是待删结点,则删除之,并修改相关指针。

核心代码:

//在O(1)时间删除结点。注:必须保证pDel为链表中的结点
void DeleteNode(List *list,pNode pDel)
{
	if(*list == NULL || pDel == NULL)
	{
		return;
	}
	//不是最后一个节点
	if(pDel->next != NULL)
	{//复制pDel后边的结点的值,并删除pDel后边的结点
		pNode pTemp = pDel->next;
		pDel->data = pTemp->data;
		pDel->next = pTemp->next;
		free(pTemp);
		pTemp = NULL;
	}else if(*list == pDel)//链表仅有一个结点
	{
		free(pDel);
		pDel = *list = NULL;
	}else//是最后一个结点
	{
		pNode pTemp = *list;
		while(pTemp->next != pDel)
		{
			pTemp = pTemp->next;
		}
		pTemp->next = NULL;
		free(pDel);
		pDel = NULL;
	}
}

完整代码:

/*
在O(1)时间内删除单向链表结点
by Rowandjj
2014/7/25
*/
#include<iostream>
using namespace std;
typedef struct _NODE_
{
	int data;
	struct _NODE_ *next;
}Node,*pNode,*List;
void AddToTail(List *list,int data)
{
	pNode pNew = (pNode)malloc(sizeof(Node));
	if(!pNew)
	{
		exit(-1);
	}
	pNew->data = data;
	pNew->next = NULL;
	if(*list == NULL)
	{
		*list = pNew;
	}else
	{
		pNode pTemp = *list;
		while(pTemp->next != NULL)
		{
			pTemp = pTemp->next;
		}
		pTemp->next = pNew;
	}
}
void Create(List *list,int n)
{
	if(n <= 0)
	{
		return;
	}
	int data;
	for(int i = 0; i < n; i++)
	{
		cin>>data;
		AddToTail(list,data);
	}
}
pNode FindNode(List list,int data)
{
	if(list == NULL)
	{
		return NULL;
	}
	pNode pTemp = list;
	while(pTemp != NULL)
	{
		if(pTemp->data == data)
		{
			return pTemp;
		}
		pTemp = pTemp->next;
	}
	return NULL;
}
void Traverse(List list)
{
	pNode pTemp = list;
	while(pTemp != NULL)
	{
		cout<<pTemp->data<<" ";
		pTemp = pTemp->next;
	}
	cout<<endl;
}
//在O(1)时间删除结点。注:必须保证pDel为链表中的结点
void DeleteNode(List *list,pNode pDel)
{
	if(*list == NULL || pDel == NULL)
	{
		return;
	}
	//不是最后一个节点
	if(pDel->next != NULL)
	{//复制pDel后边的结点的值,并删除pDel后边的结点
		pNode pTemp = pDel->next;
		pDel->data = pTemp->data;
		pDel->next = pTemp->next;
		free(pTemp);
		pTemp = NULL;
	}else if(*list == pDel)//链表仅有一个结点
	{
		free(pDel);
		pDel = *list = NULL;
	}else//是最后一个结点
	{
		pNode pTemp = *list;
		while(pTemp->next != pDel)
		{
			pTemp = pTemp->next;
		}
		pTemp->next = NULL;
		free(pDel);
		pDel = NULL;
	}
}
int main()
{
	List list = NULL;
	int n;
	cin>>n;
	Create(&list,n);
	Traverse(list);
	int data;
	cin>>data;
	pNode p = FindNode(list,data);
	if(p != NULL)
	{
		DeleteNode(&list,p);
	}
	Traverse(list);
  return 0;
}

在O(1)时间内删除单向链表结点

时间: 2024-10-01 04:53:22

在O(1)时间内删除单向链表结点的相关文章

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

// 在O(1)时间内删除单链表结点 /* 思考: 很显然链表是一个节点地址不连续的存储结构 删除节点一般很容易会想到是修改p节点的前一个节点的next为p->next 然而除非是双向链表,否则无法在常量级的时间里找到p的前节点 转变思路: 既然改变不了p前节点的next 只能在p 本身动手脚 那可以考虑修改p->data 使得p->data的值为p->next->data的值,同样可以达到效果 */ #include <iostream> #include &l

两种删除单链表结点的实现,一种O(n),一种O(1)

常规的删除单链表结点的做法是挨个查找到该结点的前一个结点,然后去掉要删除的这个结点,回收内存.这个需要O(n)的时间. 有一种比较快速的删除掉链表指定一个节点的方法,就是把下一个结点的内容复制到当前这个结点,然后把下一次结点删除掉,这个需要考虑当要删除的结点是最后一个结点的情况. 如果刚好是最后一个结点,则需要O(n)的时间,如果不是最后一个结点,可以在O(1)时间内完成删除操作. 1 // 2 // main.c 3 // SingleListDeleteNode 4 // 5 // Crea

时间复杂度分别为 O(n)和 O(1)的删除单链表结点的方法

有一个单链表,提供了头指针和一个结点指针,设计一个函数,在 O(1)时间内删除该结点指针指向的结点. 众所周知,链表无法随机存储,只能从头到尾去遍历整个链表,遇到目标节点之后删除之,这是最常规的思路和做法. 如图所示,删除结点 i,那么只需找到 i 的前驱 h,然后连 h 到 j,再销毁i 即可.虽然可以安全的删除 i 结点,但是是顺序查找找到 i,之后删除,时间复杂度是 O(n)级别的.具体做法就是:顺序查找整个单链表,找到要删除结点 i 的直接前驱 h,把 h额 next 指向i 的 nex

删除单向链表中的某个节点

删除单向链表中的某个节点 链表的节点删除 在删除链表的节点步骤如下: 1.找到被删除节点的前面一个节点 2.将前面节点的next节点改成下一个节点 3.将被删除节点的内存释放 public class deleteNode { Node head; class Node { int data; Node next; Node(int d) { data = d; next = null; } } void deleteNode(int key) { // Store head node Node

【转】Linus:利用二级指针删除单向链表

原文作者:陈皓 原文链接:http://coolshell.cn/articles/8990.html 感谢网友full_of_bull投递此文(注:此文最初发表在这个这里,我对原文后半段修改了许多,并加入了插图) Linus大婶在slashdot上回答一些编程爱好者的提问,其中一个人问他什么样的代码是他所喜好的,大婶表述了自己一些观点之后,举了一个指针的例子,解释了什么才是core low-level coding. 下面是Linus的教学原文及翻译—— “At the opposite en

剑指offer (13) O(1)时间删除单链表结点

单链表删除结点操作: 方法一.  从链表的第一个结点开始遍历,顺序遍历到需删除结点的前一个结点,然后调整指针指向  T(n) = O(n) 方法二.  将 需删除结点i的下一个结点j(如果存在) 的值赋值给 需删除结点i,然后 删除结点j,这就相当于删除了结点i  T(n) = O(1) 需要注意以下几点: 1. 如果待删除结点为单链表尾结点,此时 其后无后继结点,这时需要 从链表开头开始 顺序遍历查找 待删除结点的前驱结点 2. 如果单链表就只有一个结点,且需要删除头结点,此时 需要修改链表头

删除单向链表中间的某个节点,假定你只能访问该节点

1 /* 2 * 在这个问题中你访问不到链表的首节点,只能访问那个待删除节点,其实我们可以这样想 3 * 就是把后继结点的值复制到当前节点,当前节点的下一个地址指向后继结点的下一个地址 4 * 把删除当前节点的问题转化为删除后继结点的问题 5 * 在这里要注意以下,就是如果待删除的是链表的尾节点,则这个问题无解 6 * */ 7 public static boolean deleteNode(Node node) 8 { 9 if(node==null || node.next==null)

链表(二)——单向链表的基本操作(创建、删除、打印、结点个数统计)

1.指针的联动 通过两个指针分别指向前驱和后继结点,并在单向链表上进行移动,当指针指向待处理的结点时,该结点的前驱也有指针指向. 2.设有一个无序单向链表,且数据域的值均不相同,使指针pmin指向最小值结点,并使指针prem指向最小值结点的前驱结点: 代码片段: for(p = head; p; q = p, p = p->next) { if(pmin->data > p->data) { pmin = p; prem = q; } } 3.单向链表的删除算法 注:使用mallo

习题11-8 单链表结点删除 (20分)

习题11-8 单链表结点删除 (20分) 本题要求实现两个函数,分别将读入的数据存储为单链表.将链表中所有存储了某给定值的结点删除.链表结点定义如下: struct ListNode { int data; ListNode *next; }; 函数接口定义: struct ListNode *readlist(); struct ListNode *deletem( struct ListNode *L, int m ); 函数readlist从标准输入读入一系列正整数,按照读入顺序建立单链表