单链表详解(如何实现单链表)

ab26cc04595f467d978356fbb6c6fd0a.gif

文章目录

前言

  • 一、单链表是什么?
  • 二、单链表的实现
  • 总结

顺序表的缺点

1.中间/头部的插入删除,时间复杂度为O (N)
2.realloc 扩容(特别是异地扩,需要申请新空间,拷贝数据,释放旧空间)会有不小的消耗。
3.增容一般是呈2倍的增长,势必会有一定的空间浪费。 例如当前容量为100,满了以后增容到200,我们再继续插入了5个数据,后面没有数据插入了,那么就浪费了95个数据空间

针对顺序表的缺点,设计了链表


一、单链表是什么?

ae4dc5612f4840b997c5d7fe639174d1.png

链表是数据结构之一,其中的数据呈线性排列。在链表中,数据的添加和删除都较为方便,就是访问比较耗费时间。

1.2结构

typedef int SLTDateType;
typedef struct SListNode
{
	SLTDateType data;
	struct SListNode* next;

}SLTNode;

这就是单链表的经典结构

其实一个链表还分逻辑模型和物理模型

逻辑模型

facb5ff9a1f74c09881685afa590cfea.png

物理模型

92872284be4e41a9bc2905ba7741dc99.png

二.单链表的实现(接口函数的实现)

2.1打印

打印只有一个细节就是cur = cur->next,cur是一个结构体指针,可以通过->去访问成员,他的意思就是往下去遍历。

void SListPrint(SLTNode* phead)
{
	SLTNode* cur = phead;
	while (cur != NULL)
	{
		printf("%d->", cur->data);
		cur = cur->next;
	}
}

2.2检查扩容

和之前的顺序表的思路是一样的,单链表也是需要检查扩容的,如果满了就要扩,如果少了就要增。

SLTNode* BuyListNode(SLTDateType x)
{
	SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
	newnode->data = x;
	newnode->next = NULL;
	if (newnode == NULL)
	{
		printf("malloc fail\n");
		exit(-1);
	}
	return newnode;
}

2.3尾插

a810a3fba58a46e2b266443f495b0cd2.png

利用两个指针,先检查扩容,如果是空的就增容,然后先找到尾,然后在把新开辟的内存链接起来就可以了。

void SListPushBack(SLTNode** pphead, SLTDateType x)
{
	SLTNode* newnode = BuyListNode(x);
	if (*pphead == NULL)
	{
		*pphead = newnode;
	}
	else
	{
		//找到尾节点
		SLTNode* tail = *pphead;
		while (tail->next != NULL)
		{
			tail = tail->next;
		}

		tail->next = newnode;
	}
}

2.4头插

6d9f0d68e1224f2b951b22a46f7cbd2f.png

注意要不要传2级指针,只有判断是否使用phead

void SListPushFront(SLTNode** pphead, SLTDateType x)
{
	SLTNode* newnode = BuyListNode(x);
	newnode->next = *pphead;
	*pphead = newnode;

}

2.5尾删

尾删有两个方法,两个指针和单指针

两个指针法

将最后一组元素释放,在将最后一个元素置空,但是一个节点要单独考虑

void SListPopBack(SLTNode** pphead)
{
	assert(*pphead != NULL);
		if ((*pphead)->next = NULL)
		{
			free(*pphead);
			*pphead = NULL;
		}
		else
		{
			SLTNode* prev = NULL;
			SLTNode* tail = *pphead;
			while (tail->next != NULL)
			{
				prev = tail;
				tail = tail->next;
			}
			free(tail);
			tail = NULL;
			prev->next = NULL;
		}
}

单指针法

void SListPopBack(SLTNode** pphead)
{
    SLTNode*tail=*pphead;	
    assert(*pphead != NULL);
		if ((*pphead)->next = NULL)
		{
			free(*pphead);
			*pphead = NULL;
		}
   while(tail->next->next!=NULL)
  {
        tail=tail->next;
}
          free(tail->next);
      tail->next=NULL;
}

2.6头删

保存下一节点next,删除头节,点将头节点赋值为next。

void SListPopFront(SLTNode** pphead)
{
	assert(*pphead != NULL);
	SLTNode* next = (*pphead)->next;
	free(*pphead);
	*pphead = next;
}

2.7查找

SLTNode* SListFind(SLTNode* phead, SLTDateType x)
{
	SLTNode* cur = phead;
	while (cur != NULL)
	{
		if (cur->data == x)
		{
			return cur;
		}
		else
		{
			cur = cur->next;
		}
	}
	return NULL;
}

2.8在pos位置之前去插入一个节点

5a565a46e4484286b8b3bb9c313c2270.png

先要找到他的位置,找到pos之前的位置

void SListInsert(SLTNode** pphead, SLTNode* pos, SLTDateType x)
{
	SLTNode* newnode = BuyListNode(x);
	if (*pphead == pos)
	{
		newnode->next = *pphead;
		*pphead = newnode;
	}
	else//找到pos之前的位置
	{
		SLTNode* posprev = *pphead;
		while (posprev->next != pos)
		{
			posprev = posprev->next;
		}
		posprev->next = newnode;
		newnode->next = pos;
	}
}

2.8在pos位置之后去插入一个节点

void SListInsertAfter(SListNode* pos, SListData x)
{
	assert(pos);
	SListNode* newnode = BuyListNode(x);
	SListNode* next = pos->next;
	pos->next = newnode;
	pos->next->next = next;
}

2.9在pos位置去删去一个结点(头要特殊处理)

void SListInsert(SListNode** pphead, SListNode* pos, SListData x)
{
	assert(pphead);
	assert(pos);
	if (pos == *pphead) 
	{
		*pphead=pos->next;
         free(pos);
	}
	else
	{
		SListNode* pre = *pphead;//找到前一个
		while (pre->next != pos)	
		{
			pre = pre->next;
		}
		pre->next = pos->next;//前一个指向后一个
		free(pos);
	}
}

3.0销毁,还原

void SListDestory(SLTNode**pphead)
{
       SLTNode*cur=*pphead;
      while(cur!=NULL)
{
     SLTNode*next=cur->next;
     free(cur);
      cur=next;
}
      *pphead=NULL;
}
   

 

 


总结

单链表的缺点就是不可以随机访问,而顺序表却可以做到,说明单链表也有缺陷,那什么结构可以让我们更好?只有继续的学习才会知道。

 

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/441591.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

【开源】JAVA+Vue.js实现高校宿舍调配管理系统

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能需求2.1 学生端2.2 宿管2.3 老师端 三、系统展示四、核心代码4.1 查询单条个人习惯4.2 查询我的室友4.3 查询宿舍4.4 查询指定性别全部宿舍4.5 初次分配宿舍 五、免责说明 一、摘要 1.1 项目介绍 基于JAVAVueSpringBootMySQL的…

Day24:安全开发-PHP应用文件管理模块显示上传黑白名单类型过滤访问控制

目录 文件管理模块-上传-过滤机制 文件管理模块-显示-过滤机制 思维导图 PHP知识点 功能:新闻列表,会员中心,资源下载,留言版,后台模块,模版引用,框架开发等 技术:输入输出&#…

泛微OA服务器获取 token

泛微OA服务器获取 token 文章目录 泛微OA服务器获取 token一、泛微官方方法1 ecology 系统配置2 发放/生成许可证(appid)3 限制许可证使用ip地址(该步骤也可以跳过)4 使用 postman 注册5 获取 token6 访问业务系统接口 二、java 代码获取 token三、封装到…

【Redis项目实战】使用Springcloud整合Redis分布式锁+RabbitMQ技术实现高并发预约管理处理系统

🎉🎉欢迎光临🎉🎉 🏅我是苏泽,一位对技术充满热情的探索者和分享者。🚀🚀 🌟特别推荐给大家我的最新专栏《Redis实战与进阶》 本专栏带你Redis从入门到入魔 这是苏泽的个…

一次生产环境上的dockerd启动失败原因分析

今夜原计划对 生产环境 上的 SDN 组件进行一次紧急扩容操作的,但业务基础环境中的 Docker-Engine 启动不起来了、原定计划也就无法继续进行了。 尽管查清了基础业务环境中的故障原因,但金主DD说今天先不干了,那就整理整理思路写篇流水账吧 。…

Linux环境下使用线程方式操作UART读写功能

目录 概述 1 Linux环境下UART设备 2 轮询方式操作UART功能实现 2.1 打开串口函数:usr_serial_open 2.2 关闭串口函数: usr_serial_close 2.3 发送数据函数: usr_serial_sendbytes 2.4 接收数据函数: thread_uart_readbytes …

波卡 Alpha 计划启动,呼唤先锋创新者重新定义 Web3 开发

原文:https://polkadot.network/blog/the-polkadot-alpha-program-a-new-era-for-decentralized-building-collaboration/ 编译:OneBlock 区块链领域不断发展,随之而来的是发展和创新机会的增加。而最新里程碑是令人振奋的 Polkadot Alpha …

生态,带给用友新机会? | ToB产业观察

ITValue 近年来,不少厂商都将生态调整到战略级别,但做生态往往需要实打实、接地气的生态策略。 作者|杨丽 首发|钛媒体APP ITValue 3月初,用友召开了新一年的首场生态发布会,为接下来一年动作定调&#xff…

17、电源管理入门之Power supply子系统

目录 1. Power supply框架都做些什么 2. 相关数据结构和接口 2.1 数据结构 2.2 接口 3. 充电驱动 3.1 Charger Manager 3.2 Fuel Gauge 3.3 Charger IC 4. 怎样基于power supply class编写PSY driver 参考资料: 对于便携设备来说,电源管理更加的重要,因为电池电量…

数据库系统概念(第一周)

⚽前言 🏐四个基本概念 一、数据 定义 种类 特点 二、数据库 三、数据库管理系统(DBMS) 四、 数据库系统(DBS) 🏀数据库系统和文件系统对比 文件系统的弊端 🥎数据视图 数据抽象 …

jeecgboot 新建子模块 使用@EXCEL实现实现导入导出功能

一,用框架生成增删改查模块 二,在实体类entity 需要导入导出的字段上加上注解Excel 三,在controller类上继承jeecgboot通用controller JeecgController 并且在JeecgController里增加导出模板的方法 /*** 导出excel空模板** param req…

融资项目——网关微服务

1. 网关的路由转发功能 在前后端分离的项目中&#xff0c;网关服务可以将前端的相关请求转发到相应的后端微服务中。 2. 网关微服务的配置 首先需要创建一个网关微服务&#xff0c;并添加依赖。 <!-- 网关 --><dependency><groupId>org.springframework.cl…

相似矩阵及其对角化

目录 相似矩阵 矩阵的相似对角化 对称矩阵的相似对角化 相似矩阵 矩阵的相似对角化 对称矩阵的相似对角化

循序渐进丨MogDB 数据库新特性之SQL PATCH绑定执行计划

1 SQL PATCH 熟悉 Oracle 的DBA都知道&#xff0c;生产系统出现性能问题时&#xff0c;往往是SQL走错了执行计划&#xff0c;紧急情况下&#xff0c;无法及时修改应用代码&#xff0c;DBA可以采用多种方式针对于某类SQL进行执行计划绑定&#xff0c;比如SQL Profile、SPM、SQL …

鸿蒙实战多媒体运用:【音频组件】

音频组件用于实现音频相关的功能&#xff0c;包括音频播放&#xff0c;录制&#xff0c;音量管理和设备管理。 图 1 音频组件架构图 基本概念 采样 采样是指将连续时域上的模拟信号按照一定的时间间隔采样&#xff0c;获取到离散时域上离散信号的过程。 采样率 采样率为每…

macos m1 arm芯片 使用jpype报错 FileNotFoundError: [Errno 2] JVM DLL not found

startJVM(jpype.getDefaultJVMPath()) 报错 Traceback (most recent call last):File "/Users/thomas990p/PycharmProjects/tuya/volcano-biz-scripts/WenKongFa/FinalCode/java2python/CallJavaAPI.py", line 12, in <module>startJVM(jpype.getDefaultJVMPa…

寻找两个正序数组的中位数[困难]

优质博文IT-BLOG-CN 一、题目 给定两个大小分别为m和n的正序&#xff08;从小到大&#xff09;数组nums1和nums2。请你找出并返回这两个正序数组的 中位数 。 算法的时间复杂度应该为O(log (mn)) 。 示例 1&#xff1a; 输入&#xff1a;nums1 [1,3], nums2 [2] 输出&…

【漏洞复现】帮管客 CRM jiliyu SQL注入漏洞

免责声明&#xff1a;文章来源互联网收集整理&#xff0c;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;所产生的一切不良后果与文章作者无关。该…

用 Axios 提升前端异步请求的效率

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

代码随想录 -- 栈和队列

文章目录 栈实现队列描述题解 用队列实现栈描述题解 有效的括号描述题解 删除字符串中的所有相邻重复项描述题解 逆波兰表达式求值描述题解 滑动窗口最大值描述题解&#xff1a;暴力题解&#xff1a;单调队列 前 K 个高频元素描述题解 栈实现队列 题目链接 描述 使用两个栈实…