【带头结点的单链表】

2023-11-12


前言

单链表的概念:

单链表是一种链式存取的数据结构,用一组地址任意的存储单元存放线性表中的数据元素。链表中的数据是以结点来表示的,每个结点的构成:数据域(数据元素的映象) + 指针域(指示后继元素存储位置),元素就是存储数据的存储单元,指针就是连接每个结点的地址数据。


一、带头结点的单链表结构体设计

1. 带头结点的单链表

头节点没有单独设计其结构体,直接使用的是有效数据节点的结构体设计,是因为:

  1. 因为其头结点里的数据成员只需要一个:指针域
  2. 有效数据节点里面的数据成员不仅有数据域还有指针域,所以直接使用有效数据节点设计

下图展示了带头结点的单链表示意图:
在这里插入图片描述

2. 结构体声明

typedef int ELEM_TYPE; 
//有效数据节点结构体设计(头结点借用)
typedef struct Node
{
	ELEM_TYPE data;//数据域   (1.头结点:不保存任何数据    2.有效数据节点:保存有效值)   
	struct Node *next;//指针域  (1.头结点:保存第一个元素的地址    2.有效数据节点:保存下一个有效元素的地址)
}Node, PNode;

二、函数实现

1. 初始化

对于带头结点的单链表,由于其头节点只需要一个指针域,所以初始化只需要对头节点进行赋值,代码如下:

// 初始化函数(对于头结点进行赋初值)
void Init_list(struct Node *plist)
{
	assert(plist != NULL);
	if(NULL == plist)
	{
		return;
	}
	//plist->data;  头结点的数据域不需要赋值
	plist->next = NULL;  // 只需要将头节点的next域赋值为NULL
}

2. 申请新节点

从堆区申请一个节点大小的内存,并将申请好内存的地址返回。代码如下:

//购买一个新节点
struct Node *BuyNode(ELEM_TYPE val)
{
	struct Node*pnewnode = (struct Node*)malloc(1 * sizeof(struct Node));
	assert(pnewnode != NULL);  // 断言
	if(pnewnode == NULL)
	{
		return NULL;
	}
	// 将新购买的节点进行赋值
	pnewnode->data = val;
	pnewnode->next = NULL; 

	return pnewnode;
}

3. 头插

① 错误情况:首先断开了头节点的next域,导致有效数据元素全部找不到了
在这里插入图片描述
② 正确情况:
在这里插入图片描述
代码如下:

//头插
bool Insert_head(struct Node *plist, ELEM_TYPE val)
{
	//1.判断参数合法性
	assert(plist != NULL);
	if(NULL == plist)
	{
		return false;
	}

	//2.1申请新节点 (插入一个节点, malloc申请一个节点)
	struct Node*pnewnode = (struct Node*)malloc(1 * sizeof(struct Node));
	assert(pnewnode != NULL);
	if(pnewnode == NULL)
	{
		return false;
	}
	//2.2将val值赋值给新节点
	pnewnode->data = val;
	//pnewnode->next = NULL; //?

	//3.找到合适的插入位置  (因为是头插函数, 所以直接可以得到合适的插入位置)

	//4.插入
	pnewnode->next = plist->next;//因为plist的next域指向首元素地址
	plist->next = pnewnode;

	return true;
}

4. 尾插

尾插需要先将指针挪到最后一个节点处,挪动指针使用for循环:

for(struct Node* p = plist; p->next!=NULL; p= p->next);
// 让指针p先指向头节点,判断依据是下一个节点是否存在,如果存在的话,p向后走一步,最终指针p可指向尾节点

在这里插入图片描述
代码如下:

//尾插
bool Insert_tail(struct Node *plist, ELEM_TYPE val)
{
	assert(plist != NULL);
	//1.购买新节点
	struct Node * pnewnode = BuyNode(val);
	assert(pnewnode != NULL);
	if(NULL == pnewnode)
	{
		return false;
	}

	//2.找到合适的插入位置
	struct Node *p = plist;//因为指针p在for循环外面,还要使用,所以定义在for外面
	for(p; p->next!=NULL; p=p->next);
	//此时p指向尾结点

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

	return true;
}

5. 按位置插入

【注】插入的时候,先将指针挪动到待插入位置的上一个节点,然后将待插入节点的next置为待插入位置的下一个元素的地址,这样可以保证断开指针p的next域其后面的有效数据元素仍然可以找到

  1. 按位置插入,假设pos==2,则将p指针向后依次挪动2步即可
  2. 当pos == 0时,相当于头插,pos ==length时,相当于尾插
    在这里插入图片描述
    代码如下:
//按位置插入(pos=0 相当于头插  pos==length 相当于尾插)
bool Insert_pos(struct Node *plist, int pos, ELEM_TYPE val)
{
	assert(plist != NULL);
	assert(pos >=0 && pos<=Get_length(plist));

	//1.购买新节点
	struct Node * pnewnode = BuyNode(val);
	assert(pnewnode != NULL);
	if(NULL == pnewnode)
	{
		return false;
	}

	//2.找到合适的插入位置   
	struct Node *p = plist; 
	for(int i=0; i<pos; i++)
	{
		p=p->next;
	}

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

	return true;
}

6. 头删

头删的时候,记得先申请一个临时指针p,让指针p指向待删除节点,然后跨越指向,就可以达到删除节点的目的
在这里插入图片描述
代码如下:

//头删
bool Del_head(struct Node *plist)
{
	assert(plist != NULL);
	if(IsEmpty(plist))//删除需要判空
		return false;
	struct Node *p = plist->next;
	plist->next = p->next;//plist->next = plist->next->next;

	free(p);
	return true;
}

7. 尾删

在这里插入图片描述

  1. 申请一个临时指针p,需要将指针p指向尾节点
  2. 让指针q指向尾节点的前一个节点(前一个节点会变成新的尾节点)
  3. 尾节点的next为NULL
  4. 删除完成需要释放指针p

代码如下:

//尾删
bool Del_tail(struct Node *plist)
{
	assert(plist != NULL);
	if(IsEmpty(plist))   //删除需要判空
		return false;

	struct Node *p = plist;
	for(p; p->next!=NULL; p=p->next); // 此时p指向尾结点

	struct Node *q = plist;
	for(q; q->next!=p; q=q->next); // 此时q停在尾结点的前面

	q->next = p->next;//q->next = NULL;
	free(p);
	return true;
}

8. 销毁

借助头节点,无限头删。
在这里插入图片描述

代码如下:

//销毁1(malloc申请来的空间 全部释放掉)
void Destroy(struct Node *plist)
{
	assert(plist != NULL);
	//一直循环判断(判断单链表里还有没有节点,如果有,则头删一次)
	/*while(!IsEmpty(plist))
	{
		Del_head(plist);
	}
	plist->next = NULL;*/

	while(plist->next != NULL)
	{
		struct Node *p = plist->next;
		plist->next = p->next;
		free(p);
	}
	plist->next = NULL;
}

总结

  1. 需要前驱的操作函数:插入,删除等(让指针p指向头结点,判断依据是下一个节点存不存在,存在的话向后走一步)
    for(struct Node *p=plist; p->next!=NULL; p=p->next);//如果指针p循环外还使用,就提到for外面定义

  2. 不需要前驱的操作函数:查找,获取有效值个数,打印等(让指针p指向第一个元素地址,判断依据是当前指向的节点存不存在,存在的话向后走一步)
    for(struct Node *p=plist->next; p!=NULL; p=p->next);

  3. 插入的时候,pos == length是合法的;但是当删除的时候,pos ==length是非法的;

  4. 删除节点的时候,需要对链表进行判空操作;

  5. 链表不存在满这个概念,所以不需要判满操作;

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

【带头结点的单链表】 的相关文章

  • JXL(JExcelApi)相关资源

    1 主页 2 下载页面 Download JExcelApi 3 JXL API Online 4 全面挖掘Java Excel API 使用方法 1 5 全面挖掘Java Excel API 使用方法 2 6 使用JAVA透過JXL JE
  • 在虚拟机上安装macOS和Xcode

    最近要开发iOS软件 开发软件的操作系统需要是macOS 开发工具是Xcode 虽然实验室有苹果电脑 但是还是想在自己电脑上安装macOS虚拟机和Xcode软件 这样的话在宿舍或者在家都能开发 按照网上的教程成功安装了macOS和Xcode
  • git 提交分支报错(不能提交分支)

    git 提交新分支报错 报错信息如下 Compressing objects 100 100 100 done Writing objects 100 229 229 25 18 KiB 3 15 MiB s done Total 229
  • 淘宝x-sign算法demo示例

    用xposed hook这个方法就可以拿到对应的签名 需要可以留言 public String getMtopApiSign HashMap
  • 图文并茂:推荐算法架构——粗排

    导语 粗排是介于召回和精排之间的一个模块 是典型的精度与性能之间trade off的产物 理解粗排各技术细节 一定要时刻把精度和性能放在心中 本篇将深入重排这个模块进行阐述 一 总体架构 粗排是介于召回和精排之间的一个模块 它从召回获取上万
  • bilibili粉丝显示器

    代码地址 https github com hungtcs lab bilibili follower viewer ArduinoJSON https arduinojson org esp8266 oled ssd1306 https
  • Spirng @Conditional 条件注解的使用

    1 简介 Conditional 是 Spring 4 0 提出的一个新的注解 当标注的对象满足所有的条件时 才能注册为 Spring 中的 bean Conditional 源码中的定义如下 Target ElementType TYPE

随机推荐

  • C# Datagridview 标题完全居中

    DataGridView标题完全居中 标题文字居中 this dataGridView1 ColumnHeadersDefaultCellStyle Alignment DataGridViewContentAlignment Middle
  • Java 语言 TreeMap

    Java中的TreeMap是一种基于红黑树实现的排序映射表 它可以存储键值对 其中键和值都可以是任意类型的对象 TreeMap提供了快速的插入 删除和查找操作 具有高效的性能 并且可以根据键进行排序 因此在Java编程中非常常见 本文将介绍
  • 博士申请

    合适的工作难找 最新的招聘信息也不知道 AI 求职为大家精选人工智能领域最新鲜的招聘信息 助你先人一步投递 快人一步入职 南洋理工大学 南洋理工大学 Nanyang Technological University 是新加坡的一所世界著名研
  • 解决 Python 库安装提示:ModuleNotFoundError: No module named ‘windows‘. 问题解决方法

    在安装pyMouse PyKeyboard的时候报错我们可以尝试以下代码 应该有用 pip install PyUserInput
  • unity对象池系统

    当游戏场景中出现大量的可重复利用的物体时 通过Destory来销毁再创建会触发不必要的GC回收机制 浪费性能 我们可以利用unity自带的对象池系统 从而节约性能来得到同样的效果 为了使用这个对象池系统 我写了一个瞬间产生多枚子弹的测试脚本
  • 权限认证。。

    链接 手摸手 带你用vue撸后台 系列二 登录权限篇 掘金 juejin cn 前端权限控制 一 前端权限管理及动态路由配置方案 ONEO阿喔哟的博客 CSDN博客 检查员工是否具有特权 param requestTokenBO 请求令牌B
  • 如何快速算出一个数有多少个因子(c++)

    如何快速算出一个数有多少个 多少种 因子 c int count int n int sum 1 for int i 2 i i lt n i if n i 0 int tmp 0 while n i 0 n i tmp sum sum t
  • Piecewise混沌映射/PWLCM混沌映射(含MATLAB代码)

    一 Piecewise混沌映射 PWLCM混沌映射 混沌映射是生成混沌序列的一种方法 常见的混沌映射方式有 Logistic映射 Tent映射 Circle映射 而 Piecewise映射作为混沌映射的典型代表 数学形式简单 具有遍历性和随
  • python文件操作(with open)——读取行、写操作

    一 基础语法 1 打开文件 这里只介绍一种常用方式 但是打开文件方式有很多种 掌握一种最适合自己的即可 推荐使用这种方式 因为不需要close 具体原因往下看 看到示例就懂了 打开文件的模式有很多种 r 读 w 写等 此处不做详细介绍 采用
  • sublime text3取消自动换行!

    菜单栏中取消view gt word wrap的勾选也可以取消其代码的自动换行 菜单栏选择preferences gt Setting User中添加 word wrap false 即可
  • 膜拜(离散化差分模板题)

    题目描述 小鱼有 n 名优秀的粉丝 粉丝们得知小鱼将会在一条直线上出现 打算去膜他 为了方便 粉丝们在这条直线上建立数轴 第 i 名粉丝有一个侦查区间 li ri 如果小鱼在 j li j ri 处出现 这名粉丝将立刻发现并膜他 小鱼希望膜
  • python 3 中文URL编码转换问题

    链接里面含中文 转成URL编码 先引入模块 from urllib request import quote gt gt gt ff 摄像头 gt gt gt ff quote ff gt gt gt ff E6 91 84 E5 83 8
  • sql 还原数据库 错误3154

    在SQL Server2005及以下版本做数据库备份还原时 需要首先建立数据库 然后才能进行数据库还原操作 而在SQL Server2005以上版本做数据库还原时 不需要建立数据库 可以直接进行数据库还原操作 否则执行数据库还原操作时会报3
  • 求阶乘之和(循环版)(利用阶乘函数)

    请编写函数 用循环方法求阶乘之和 SumFac n 0 1 2 3 n include
  • uniapp uview 登录页

  • DETRs Beat YOLOs on Real-time Object Detection论文详解

    论文题目 DETRs Beat YOLOs on Real time Object Detection 论文地址 https arxiv org abs 2304 08069 论文代码 mirrors facebookresearch Co
  • jmeter:linux环境运行jmeter并生成报告

    是一个java开发的利用多线程原理来模拟并发进行性能测试的工具 一般来说 GUI模式只用于创建脚本以及用来debug 执行测试时建议使用非GUI模式运行 这篇博客 介绍下在linux环境利用jmeter进行性能测试的方法 以及如何生成测试报
  • matplotlib绘图与可视化2

    文章目录 前言 一 使用pandas和seaborn绘图 1 1 折线图 1 2 柱状图 1 3 直方图和密度图 1 4 散点图或点图 1 5 分面网格和分类数据 总结 前言 matplotlib是一个相当底层的工具 你可以从其基本组件中组
  • java ioc依赖注入,Spring bean的实例化和IOC依赖注入详解

    前言 我们知道 IOC是Spring的核心 它来负责控制对象的生命周期和对象间的关系 举个例子 我们如何来找对象的呢 常见的情况是 在路上要到处去看哪个MM既漂亮身材又好 符合我们的口味 就打听她们的电话号码 制造关联想办法认识她们 然后
  • 【带头结点的单链表】

    带头结点的单链表 前言 一 带头结点的单链表结构体设计 1 带头结点的单链表 2 结构体声明 二 函数实现 1 初始化 2 申请新节点 3 头插 4 尾插 5 按位置插入 6 头删 7 尾删 8 销毁 总结 前言 单链表的概念 单链表是一种