删除单链表某个结点

题目:删除带头结点的单链表L中的结点p,p不是最后一个结点,要求时间复杂度为O(1)。

解题思路:

如果不要求时间复杂度为O(1),我们可以找出p的前驱结点,然后很容易就删除p。

现在要求时间复杂度为O(1),因为p不是最后一个结点,知道结点p我们可以删除p的后继结点,那么我们可以把p的后继结点元素的值赋给p结点元素的值。

ADT定义如下

#define ElemType int

typedef struct LNode{

ElemType data;

LNode *next;

}LNode,*LinkList;

算法实现:

void deleteNode(LNode* &p)
{
	if(p==NULL||p->next==NULL) return;//如果p为空或为单链表中最后一个结点不符合题意,直接返回
	LNode* q=p->next;//q为p的后继结点
	p->data=q->data;
	p->next=q->next;//从单链表中删除结点q

	free(q);//释放结点q
	q=NULL;//将结点q置为空,防止它成为野指针
}

拓展:如果删除的结点p可能是最后一个结点,怎么办。

解题思路:此时只能保证删除结点的平均时间复杂度为O(1),当p不是最后一个结点,时时间复杂度为O(1),当p是最后一个结点时,时间复杂度为O(n)。

算法实现:

void deleteNode(LinkList &L,LNode* &p)
{
	if(p==NULL||L==NULL) return;//如果p为空或单链表L为空不符合题意,直接返回
	if(p->next) //如果p不是最后一个结点
	{
		LNode* q=p->next;//q为p的后继结点
	    p->data=q->data;
	    p->next=q->next;//从单链表中删除结点q

	    free(q);//释放结点q
	    q=NULL;//将结点q置为空,防止它成为野指针

	}
	else //如果p是最后一个结点
	{
		LNode* pre=L;//用pre表示p的前驱结点
		while(pre->next) //保持pre有后继结点
		{
			if(pre->next==p)//如果pre是p的前驱结点
			{
				pre->next=p->next;//将结点p从单链表中删除
				free(p);//释放结点p
	            p=NULL;//将结点p置为空,防止它成为野指针
			}
		}
		if(!p) //p不为空,说明p不在单链表L中
		{
			return;
		}
	}

}
时间: 2024-10-07 10:04:28

删除单链表某个结点的相关文章

如何在O(1)的时间里删除单链表的结点

题目是这样的:给你一个单链表的表头,再给你其中某个结点的指针,要你删除这个结点,条件是你的程序必须在O(1)的时间内完成删除. 由于有的同学对链表还不是很熟悉,本文尽量描述的通俗易懂,老鸟请直接跳过前面一大段. 链表结构如下: [cpp] view plaincopyprint? struct node { int val; node* next; }; 题目不是很难,很快就能想到好办法:) 首先回顾一下普通的删除方法,首先通过表头,找到待删除结点(设为B)的前一个结点(设为A),将A的指向改一

[算法浅析] 如何在O(1)的时间里删除单链表的结点

题目是这样的:给你一个单链表的表头,再给你其中某个结点的指针,要你删除这个结点,条件是你的程序必须在O(1)的时间内完成删除. 由于有的同学对链表还不是很熟悉,本文尽量描述的通俗易懂,老鸟请直接跳过前面一大段. 链表结构如下: struct node { int val; node* next; }; 题目不是很难,很快就能想到好办法:) 首先回顾一下普通的删除方法,首先通过表头,找到待删除结点(设为B)的前一个结点(设为A),将A的指向改一下就行,然后删除掉B结点就行了.要删除的结点一定要de

删除单链表某个结点(Java版)

题目:删除带头结点的单链表L中的结点p,p不是最后一个结点,要求时间复杂度为O(1). 解题思路: 如果不要求时间复杂度为O(1),我们可以找出p的前驱结点,然后很容易就删除p. 现在要求时间复杂度为O(1),因为p不是最后一个结点,知道结点p我们可以删除p的后继结点,那么我们可以把p的后继结点元素的值赋给p结点元素的值. ADT定义: //单链表的结点类 class LNode{ //为了简化访问单链表,结点中的数据项的访问权限都设为public public int data; public

删除单链表指定结点出现段错误?

起初我是这么写的: struct node * deletenode(struct node *head,int b){ struct node *pre,*cur; pre=NULL; cur=head; if(head&&head->data==b){ head=head->next; free(cur); } else{ while(cur->data!=b){ pre=cur; cur=cur->next; } pre->next=cur->ne

删除单链表中重复的结点

先批评下<<数据结构实验教程(C语言版) 清华大学出版社 :王国钧主编>>这本书,CTMD,错误真多! *删除单链表重复结点 算法-:第一个跟后面比较,同则删除;第二个...第n个; 采用 *算法二:先排序, 将排好后的相同结点删除*/ void delSameNodeDLink(LinkList h) {//内外循环 LinkList p1, p2, p3; p1 = h; while (p1->next) { p2 = p1->next; //1 p3 = p2-&

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

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

009实现一个算法来删除单链表中的一个结点,只给出指向那个结点的指针(keep it up)

呵呵,这个题不能直接删除已知的结点,因为是单链表,不知道前驱,只知道 后继结点,直接删除会使链表断开.不过我们可以删除已知结点的后继结点, 把后继结点的值赋值给已知结点. #include <iostream> struct Node { int data; Node* next; }; bool removeNode(Node* vNode) { if (vNode == NULL || vNode->next == NULL) return false; Node* pNext =

以指针和引用两种参数实现删除单链表L中所有值为X的结点的函数

下面是单链表的数据结构 typedef struct LNode{ ElemType data; struct LNode *next; }LNode,*Linklist; 1.以指针参数实现 void delete_x_1(LNode *head,ElemType x){//head为单链表头结点,删除结点的值为x LNode *l = head; LNode *p = head->next; while(p != null){ if(p->data == x){ l->next =

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

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