当前位置: 首页 > article >正文

(C语言)双向链表

目录

链表的分类

双向链表的实现

1)定义链表

2)初始化双向链表

3)申请节点

4)尾插

5)头插

6)打印链表

7)尾删

8)头插

9)查找

10)指定位置删除

11)在指定位置后删除

12)销毁链表


链表的分类

根据链表的三个特点(带头/不带头,单向/双向,循环/不循环),可以将链表分为8种。常见的有两种:单链表(单向不带头不循环链表),双链表(双向带头循环链表)。是否带头指的是有没有头节点。链表(全网最详细)-CSDN博客。单链表已经写过了,此处我们将双链表。

双向链表的实现

1)定义链表

typedef int SLDateType;

//定义双向链表
typedef struct ListNode
{
	SLDateType date;   //节点中的邮箱有效数据
	struct ListNode* next;  //保存下一个节点地址
	struct ListNode* prev;   //保存上一个节点的有效地址
}LN;

2)初始化双向链表

双链表的初始化,主要是创建头节点,即哨兵位。

//双链表的初始化
void List_start(LN** head)
{
	*head = (LN*)malloc(sizeof(LN));
	(*head)->date = -1;//给哨兵位一个数据,但是它其实是无效数据
	//注意因为是循环链表,所以当只有一个哨兵位的时候,要让它指向它自己;
	(*head)->next = (*head)->prev = (*head);
}

3)申请节点

//申请节点
LN* ListBuyNode(SLDateType x)
{
	LN* newnode = (LN*)malloc(sizeof(LN));
	newnode->date = x;
	//因为是双向循环链表,永远不会走到空,所以将新节点也指向其自己
	newnode->next = newnode->prev = newnode;
	return newnode;
}

4)尾插

注意:除了双向链表的初始化以及销毁要传二级指针,其他函数均采用一级指针,因为哨兵位在被定义后就不能再对他进行修改了。

//双向链表的尾插
void SLpushback(LN* head, SLDateType x)
{
	LN* newnode = ListBuyNode(x);
	//对头节点head,尾节点head->prev,新节点newnode
	newnode->next = head;
	newnode->prev = head->prev;

	head->prev->next = newnode;
	head->prev = newnode;
}

5)头插

头插是指查到烧饼位的后面。

//双向链表的头插
void SLpushfront(LN* head, SLDateType x)
{
	LN* newnode = ListBuyNode(x);
	//对head newnode head->next进行修改
	newnode->next = head->next;
	newnode->prev = head;

	head->next->prev = newnode;
	head->next = newnode;
}

6)打印链表

//打印双向链表
void SLPrint(LN* head)
{
	LN* pcur = head->next;
	while (pcur != head)
	{
		printf("%d ", pcur->date);
		pcur = pcur->next;
	}
}

7)尾删

//双链表尾删
void SLDelback(LN* head)
{
	//对head head->prev head->prev->prev
	LN* del = head->prev;
	head->prev = del->prev;
	del->prev->next = head;

	free(del);
	del = NULL;
}

8)头插

//双链表的头插
void SLDelfront(LN* head)
{
	//对head head->next head->next->next进行调整
	LN* del = head->next;
	head->next = del->next;
	del->next->prev = head;
}

9)查找

找双向链表中查找数据,并返回节点;

//双链表的查找
LN* SLFind(LN* head,SLDateType x)
{
	LN* pcur = head->next;
	while (pcur != head)
	{
		if (pcur->date == x)
			return pcur;

		pcur = pcur->next;
	}
	return NULL;
}

10)指定位置删除

//指定位置删除
void SLDEL(LN* head, LN* pos)
{
	//删除pos节点
	//对pos->prev pos pos->next进行操作
	pos->prev->next = pos->next;
	pos->next->prev = pos->prev;

	free(pos);
	pos = NULL;
}

11)在指定位置后删除

//在指定位置后插入
void LInsert(LN* pos, SLDateType x)
{
	LN* newnode = ListBuyNode(x);
	//对pos  newnode  pos->next
	newnode->next = pos->next;
	newnode->prev = pos;

	pos->next->prev = newnode;
	pos->next = newnode;
}

12)销毁链表

//销毁链表
void LDestory(LN** head)
{
	//循环删除节点
	LN* pcur = (*head);
	while (pcur != *head)
	{
		LN* next = pcur->next;
		free(pcur);
		pcur = next;
	}
	free(*head);
	*head = NULL;
}

http://www.kler.cn/a/444361.html

相关文章:

  • 知网研学 | 知网文献(CAJ+PDF)批量下载
  • W25Q128读写实验(一)
  • 技术文档的规划布局:打造清晰且有条理的知识传递框架
  • JAVA开发时获取用户信息失败,分析后端日志信息
  • ChatGPT等大语言模型与水文水资源、水环境领域的深度融合
  • 【Jenkins】pipeline 的基础语法以及快速构建一个 jenkinsfile
  • iClent3D for Cesium 实现无人机巡检飞行效果
  • neo4j 图表数据导入到 TuGraph
  • 使用Docker启用MySQL8.0.11
  • HTMLCSS:这个动态删除按钮打几分?
  • 基于JavaScript的DBUtils增删改查操作实验
  • 算法编程题-不相交的线 联通网络的操作次数 销售价值减少的颜色球
  • git废弃指定文件的修改
  • Java设计模式 —— 【结构型模式】适配器模式(类的适配器、对象适配器、接口适配器)详解
  • 可视化平台FineReport的安装及简单使用
  • Windows 配置 Tomcat环境
  • 专业125+总分400+南京理工大学818考研经验南理工电子信息与通信工程,真题,大纲,参考书。
  • Python中map函数返回值类型用法介绍
  • arcgisPro将面要素转成CAD多段线
  • K8s HPA的常用功能介绍
  • 利用系统自带的存储感知功能清理系统中的升级补丁
  • Linux 定时任务操作详解及python简单的任务管理器
  • 设计模式-读书笔记2
  • Docker+Redis单机和集群部署【非常详细】
  • Android 获取屏幕物理尺寸
  • 建站技术 | HUGO + GitHub 创建博客页面