数据结构单链表插入和删除操作

单链表:先回顾单链表的特点  逻辑相邻 物理上不一定相连

首先初始化单链表,其中主要保存的是该节点自身的值以及下个节点的地址。

有效节点结构体设计:
​
struct Node{
​
int data;//数据域
​
struct Node* next;//指针域
​
}

以下是单链表的插入以及删除操作:

(一)插入操作

单链表的插入主要分为头插,尾插,以及按位置插入这三种来进行操作。

(1)头插

bool Insert_head(PNode pn, int val)
{
	assert(pn!=NULL);//判断不为空

	//1.申请新节点
	struct Node* pnewnode = (struct Node*)malloc(1 * sizeof(struct Node));
	assert(pnewnode != NULL);
	pnewnode->data = val;
	pnewnode->next = NULL; // 这里可写可不写


	//2.找到合适的插入
	//头插时插入在头结点的后边,所以不用找

	//3.插入
	pnewnode->next = p->next;//先让C指向B  (不能先断开AB中间的线  不然找不到B)
	p->next = pnewnode;//此时再让A指向C
	return true;
}

(2)尾插

bool Inseret_tail(PNode pn, int val)
{
	//1.申请新节点
	struct Node* pnewnode = (struct Node*)malloc(1 * sizeof(struct Node));
	assert(pnewnode != NULL);
	pnewnode->data = val;
	pnewnode->next = NULL; // 这些步骤都与前面的一样

	//2.找到合适的插入位置(尾插,需要一个临时指针p指向尾结点)
	struct Node* p = pn;
	for (p; p->next != NULL; p = p->next);

	//3.插入
	pnewnode->next = p->next;
	p->next = pnewnode;

	return true;
}

(3)按位置插入(将C插入到AB)

bool Inseret_pos(PNode pn, int pos, int val)
{
	
	assert(pos >= 0 && pos <= Get_length(pn));

	//1.申请新节点
	struct Node* pnewnode = (struct Node*)malloc(1 * sizeof(struct Node));
	assert(pnewnode != NULL);//确保申请成功
	pnewnode->data = val;//传入val
	pnewnode->next = NULL; // 

	//2.找到合适的插入位置(按位置插入AB之间,在这里发现规律,pos等于几则让指向头结点的指针p向后走pos步,此时p指向AB的A)
	struct Node* p = pn;
	for (int i = 0; i < pos; i++)
	{
		p = p->next;
	}
    //3.插入
	pnewnode->next = p->next;//先让C指向B  (不能先断开AB中间的线  不然找不到B)
	p->next = pnewnode;//此时再让A指向C

	return true;
}

按位置插入这里改变pos的值便可以实现头插和尾插。

(二)删除操作

(1)头删

bool Del_head(PNode pn)
{
	//assert
	if (IsEmpty(pn))
	{
		return false;
	}

	struct Node* p = pn->next;//pn是头结点 pn->next则是第一个有效节点地址  即头删的节点   则此时p指向待删除节点
	//将待删除节点跨越指向(让带删除节点上家的next域指向下家的地址,而下家的地址在待删节点p的next中)
	pn->next = p->next;
	free(p);
	p = NULL;

	return true;
}

(2)尾删

bool Del_tail(PNode pn)
{
	//assert
	if (IsEmpty(pn))
	{
		return false;
	}

	//找到待删除节点用p指向(尾删的待删除节点就是倒数第一个节点)
	struct Node* p = pn;
	for (p; p->next != NULL; p = p->next);//当P指向的next域为空停下来

	//q指向倒数第二个节点
	struct Node* q = pn;
	for (q; q->next != p; q = q->next);

	q->next = pn;//q->next = p->next;
	free(p);

	return true;

}

(3)按位置删    同样这里改变pos的值能实现头删和尾删

bool Del_pos(PNode pn, int pos)
{
	//assert
	assert(pos >= 0 && pos < Get_length(pn));
	if (IsEmpty(pn))//注意这里的判空操作在后面有定义
	{
		return false;
	}

	//先找到待删除节点的上一个节点,用q指向  规律:pos等于几 q就向后走几步
	struct Node* q = pn;
	for (int i = 0; i < pos; i++)
	{
		q = q->next;
	}
	//此时 q指向待删除节点的上一个节点
	//接下来 再让p指向待删除节点 待删除节点在q的next中
	struct Node* p = q->next;

	//跨越指向,再释放
	q->next = p->next;
	free(p);//删除待删除节点

	return true;
}
  bool IsEmpty(PNode pn)
{
	return pn->next == NULL;
}

(4)按值删

bool Del_val(PNode pn, int val)
{
	//assert
	if (IsEmpty(pn))
	{
		return false;
	}

	struct Node* p = Search(pn, val);//判断value是否存在
	if (p == NULL)//search返回的地址为空代表没找到
	{
		return false;
	}
	//此时待删除节点存在,  且用指针p指向

	struct Node* q = pn;
	for (q; q->next != p; q = q->next);
	//再申请一个临时指针q  让q指向p的上一个节点


	q->next = p->next;
	free(p);
	//跨越指向,和释放
	return true;
}

//查找
struct Node* Search(PNode pn, int val)
{
	//assert
	for (struct Node* p = pn->next; p != NULL; p = p->next)
	{
		if (p->data == val)
		{
			return p; //找到 则扔出去
		}
	}

	return NULL; //没找到,返回NULL地址
}

以上便是一些单链表的相关操作,简单可直接拿去使用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值