C语言链表3

3、单链表的算法之遍历节点

3.1、什么是遍历
(1)遍历就是把单链表中的各个节点挨个拿出来,就叫遍历。
(2)遍历的要点:一是不能遗漏、二是不能重复、追求效率。
3.2、如何遍历单链表
(1)分析一个数据结构如何遍历,关键是分析这个数据结构本身的特点。然后根据本身特点来制定它的遍历算法。
(2)单链表的特点就是由很多个节点组成,头指针+头节点为整个链表的起始,最后一个节点的特征是它内部的pNext指针值为NULL。从起始到结尾中间由各个节点内部的pNext指针来挂接。由起始到结尾的路径有且只有一条。单链表的这些特点就决定了它的遍历算法。
(3)遍历方法:从头指针+头节点开始,顺着链表挂接指针依次访问链表的各个节点,取出这个节点的数据,然后再往下一个节点,直到最后一个节点,结束返回。

3.3、编程实战
(1)写一个链表遍历的函数,void bianli(struct node*pH);

// 遍历单链表,pH为指向单链表的头指针,遍历的节点数据打印出来
void bianli(struct node*pH)
{
	//pH->data				// 头节点数据,不是链表的常规数据,不要算进去了
	//struct node *p = pH;		// 错误,因为头指针后面是头节点
	struct node *p = pH->pNext;	// p直接走到第一个节点
	printf("-----------开始遍历-----------\n");
	while (NULL != p->pNext)		// 是不是最后一个节点
	{
		printf("node data: %d.\n", p->data);
		p = p->pNext;				// 走到下一个节点,也就是循环增量
	}
	printf("node data: %d.\n", p->data);
	printf("-------------完了-------------\n");
}

int main(void)
{
	bianli2(pHeader);
	
	return 0;
}

4、单链表的算法之删除节点

4.1、为什么要删除节点
(1)一直在强调,链表到底用来干嘛的?
(2)有时候链 表节点中的数据不想要了,因此要删掉这个节点。
4.2、删除节点的2个步骤
(1)第一步:找到要删除的节点;第二步:删除这个节点。
4.3、如何找到待删除的节点
(1)通过遍历来查找节点。从头指针+头节点开始,顺着链表依次将各个节点拿出来,按照一定的方法比对,找到我们要删除的那个节点。
4.4、如何删除一个节点
(1)待删除的节点不是尾节点的情况:首先把待删除的节点的前一个节点的pNext指针指向待删除的节点的后一个节点的首地址(这样就把这个节点从链表中摘出来了),然后再将这个摘出来的节点free掉接口。
(2)待删除的节点是尾节点的情况:首先把待删除的尾节点的前一个节点的pNext指针指向null(这时候就相当于原来尾节点前面的一个节点变成了新的尾节点),然后将摘出来的节点free掉。
4.5、注意堆内存的释放
(1)前面写的代码最终都没有释放堆内存。当程序都结束了的情况下那些没有free的堆内存也被释放了。
(2)有时候我们的程序运行时间很久,这时候malloc的内存如果没有free会一直被占用直到你free释放它或者整个程序终止。

// 从链表pH中删除节点,待删除的节点的特征是数据区等于data
// 返回值:当找到并且成功删除了节点则返回0,当未找到节点时返回-1
int delete_node(struct node*pH, int data)
{
	// 找到这个待删除的节点,通过遍历链表来查找
	struct node *p = pH;			// 用来指向当前节点
	struct node *pPrev = NULL;		// 用来指向当前节点的前一个节点

	while (NULL != p->pNext)		// 是不是最后一个节点
	{
		pPrev = p;					// 在p走向下一个节点前先将其保存
		p = p->pNext;				// 走到下一个节点,也就是循环增量
		// 判断这个节点是不是我们要找的那个节点
		if (p->data == data)
		{
			// 找到了节点,处理这个节点
			// 分为2种情况,一个是找到的是普通节点,另一个是找到的是尾节点
			// 删除节点的困难点在于:通过链表的遍历依次访问各个节点,找到这个节点
			// 后p指向了这个节点,但是要删除这个节点关键要操作前一个节点,但是这
			// 时候已经没有指针指向前一个节点了,所以没法操作。解决方案就是增加
			// 一个指针指向当前节点的前一个节点
			if (NULL == p->pNext)
			{
				// 尾节点
				pPrev->pNext = NULL;		// 原来尾节点的前一个节点变成新尾节点
				free(p);					// 释放原来的尾节点的内存
			}
			else
			{
				// 普通节点
				pPrev->pNext = p->pNext;	// 要删除的节点的前一个节点和它的后一个节点相连,这样就把要删除的节点给摘出来了
				free(p);
			}
			// 处理完成之后退出程序
			return 0;
		}
	}
	// 到这里还没找到,说明链表中没有我们想要的节点
	printf("没找到这个节点.\n");
	return -1;
}

int main(void)
{
	
	delete_node(pHeader, 12);
	printf("------------------删除后-------------\n");
	
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值