手把手教你:单链表的创建,以及各种插法、删法(基于C语言)(其二)

继续书接上回

其二当中我们讲解了链表的头插法,任意插法,指定数据后面插法,那么最后一节,我们讲解链表的头删法,尾删法,以及指定位置删法

头删法:

顾名思义,就是把排第一的那个节点删掉。

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

void pop_head(List* list)
{
	Node* tempNode = list->next;
	if (tempNode == NULL)
	{
		return;
	}
	list->next = tempNode->next;
	free(tempNode);
}

逐一讲解:

  1. 首先我们创建了一个tempNode,代表的是首元节点,如果首元节点为NULL,那么就不需要再删除掉了,直接return
  2. 若首元节点不为空,我们就把 头节点 指向 首元节点的下一个节点,那么tempNode->next这个节点就成了新的首元节点啦
  3. 最后我们还要调用free函数释放掉原来的首元节点,避免内存泄漏

尾删法:

尾删法即把最后的节点删除掉,就像一辆火车把最后的那节车厢给脱钩一样。

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

void pop_back(List* list)
{
	Node* backNode = list->next;
	if (!backNode)
	{
		return;
	}
	while (backNode->next != NULL)
	{
		backNode = backNode->next;
	}
	Node* preNode = list;
	while (preNode->next != backNode)
	{
		preNode = preNode->next;
	}
	preNode->next = NULL;

	free(backNode);
}

        这里的尾删法最重要的一个问题便是,怎么找到尾节点?以及要把倒数第二个节点重新指向为NULL

逐一讲解:

  1. Node* backNode = list->next 这个代码,是为了从首元节点开始遍历,并且下面进行了 if 的判断,是为了避免链表本来就只有一个头节点,实现不了尾删
  2. 然后我们使用while循环,来找到尾节点,backNode即代表尾节点的意思
  3. 重点来了,我们又定义了一个preNode,这个代表的是尾节点的前一个节点,因为我们需要让倒数第二个节点指向为NULL嘛
  4. 第二个while循环的条件为 preNode->next != backNode,即只要preNode的指向不是尾节点,就一直向下找,当循环结束后,preNode即为倒数第二个节点
  5. preNode->next = NULL 让倒数第二个节点重新指向空,然后用free函数释放掉原来的尾节点,这样原来的尾节点就被成功删除,而preNode就成了新的尾节点

指定位置删法:

和之前讲到的指定位置插入一样的原理,但是指定位置删除则需要考虑更多的情况。

需要考虑的情况如下:

  • 要删除的位置刚好为首元节点,即指定的位置为0
  • 要删除的位置是中间节点
  • 要删除的位置刚好为尾节点
  • 指定的位置,比链表的节点数量要大
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

void pop_pos(List* list, int position)
{
	Node* curNode = list;
	int location = 0;
	if (position == 0)
	{
		pop_head(list);
        return;
	}
	while (curNode)
	{
		if (position == location++)
		{
			if (curNode->next == NULL)
			{
				pop_back(list);
                return;
			}
			else
			{
				Node* popNode = curNode->next;
				Node* backNode = popNode->next;
				curNode->next = backNode;
				free(popNode);
                return;
			}
		}
		curNode = curNode->next;
	}
	if (position > location)
	{
		pop_back(list);
	}
}

逐一讲解:

  1. 我们通过int location = 0 抽象出一个链表的索引
  2. 紧接着,我们判断传入的position的值是否为0,是就直接调用前面写好的pop_head函数,然后返回即可
  3. 然后我们就要考虑另外两种情况,我们用while循环遍历整个链表,循环里面放一个if 判断是否到达了指定的位置
  4. 如果到达了位置,我们再用if (curNode->next == NULL) 来判断指定位置的节点是否为尾节点,是的话,我们直接调用写好的pop_back函数即可
  5. 如果不是,即代表了要删除的节点在中间的位置,Node* popNode = curNode->next,popNode代表了我们要删除的节点,这个节点为curNode->next。紧接着的Node* backNode = popNode->next;  curNode->next = backNode; 是把断开的节点连接起来的,如果看不懂建议可以手工画图理解
  6. 最后我们释放掉popNode即可

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值