做购物平台网站 民治/网络营销的三大核心
单链表
文章目录
- 单链表
- 1.链表
- 1.1链表的概念和结构
- 1.2链表的分类
- 2.单链表的模拟实现
- 2.1单链表的打印
- 2.2单链表的尾插
- 2.3单链表的头插
- 2.4单链表的尾删
- 2.5单链表的头删
- 2.6单链表的查找
- 2.7单链表的中间插入(在结点前插入)
- 2.8单链表的中间删除(删除该结点)
- 2.9单链表的中间插入(在结点后插入)
- 2.10单链表的中间删除(删除该结点的后继)
- 2.11单链表的销毁
- 3.单链表的优缺点
- 4. 链表的经典OJ题目训练
1.链表
1.1链表的概念和结构
概念:链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的 。
现实中 数据结构中
1.2链表的分类
实际中链表的结构非常多样,以下情况组合起来就有8种链表结构(
2*2*2
):
单向或者双向
带头或者不带头(哨兵位的头结点)
循环或者非循环
虽然有这么多的链表的结构,但是我们实际中最常用还是两种结构:
- 无头单向非循环链表:结构简单,一般不会单独用来存数据。实际中更多是作为其他数据结构的子结构,如哈希桶、图的邻接表等等。这种结构在笔试面试中出现很多。
- 带头双向循环链表:结构最复杂,一般用在单独存储数据。实际中使用的链表数据结构,都是带头双向循环链表。另外这个结构虽然结构复杂,但是使用代码实现以后会发现结构会带来很多优势。
2.单链表的模拟实现
SList.h
中
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>typedef int SLTDateType;//单链表结点结构
typedef struct SLTNode
{SLTDateType data;struct SLTNode* next;
}SLTNode;//单链表打印
void SLTPrint(SLTNode* phead);//尾插
void SLTPushBack(SLTNode** pphead, SLTDateType x);
//头插
void SLTPushFront(SLTNode** pphead, SLTDateType x);//尾删
void SLTPopBack(SLTNode** pphead);
//头删
void SLTPopFront(SLTNode** pphead);//查找
SLTNode* SLTFind(SLTNode* phead, SLTDateType x);
//结点前插入
void SLTInsert(SLTNode** pphead,SLTNode* pos, SLTDateType x);
//删除该结点
void SLTErase(SLTNode** pphead, SLTNode* pos);//结点后插入
void SLTInsertAfter(SLTNode* pos, SLTDateType x);
//删除该结点的后继
void SLTEraseAfter(SLTNode* pos);
//单链表的销毁
void SLTDestroy(SLTNode** pphead);//free完所有结点,将phead置空
SList.c
中
💡ps:单链表是使用一个SLTNode*
的指针plist
(头指针)来维护的。
⚠注意1:
由于要通过函数接口来实现单链表的增删查改(修改单链表),就要进行址传递,传入&plist
对于不需要修改单链表的接口,直接传入plist即可
⚠注意2:
由于单链表的初始化比较简单,我们在测试文件中(test.c)中,直接
SLTNode* plist = NULL
即可单链表的销毁并不是简单地对头指针进行
free
,而是要对每个结点进行free
2.1单链表的打印
void SLTPrint(SLTNode* phead)
{SLTNode* cur = phead;while (cur){printf("%d->", cur->data);cur = cur->next;}printf("NULL\n");
}
💡ps:由于一个结点存着下一个结点的地址,所以我们可以通过cur = cur->next
的方式,来找下一个结点,遍历下去。
2.2单链表的尾插
SLTNode* BuyNewnode(SLTDateType x)
{SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));if (newnode == NULL){perror("malloc fail\n");return NULL;}else{newnode->data = x;newnode->next = NULL;}return newnode;
}//链表的插入操作是不需要对phead进行判空的(因为空链表,phead就是NULL)
//尾插
void SLTPushBack(SLTNode** pphead, SLTDateType x)
{assert(pphead);//防止使用者传参时,传的plist而不是&plist特殊情况,如果是空链表,找不到尾结点,所以直接将newnode作为phead//1.构造新结点SLTNode* newnode = BuyNewnode(x);//特殊情况:空链表if (*pphead == NULL){*pphead = newnode;return;}else//一般情况:非空链表{//2.找到尾结点SLTNode* tail = *pphead;while (tail->next != NULL){tail = tail->next;}//3.嫁接tail->next = newnode;}}
💡ps:对于单链表的尾部操作,需要先找到尾结点。时间复杂度:O(N)。
而且对于空链表的情况无法找到尾结点,需要特殊处理。
2.3单链表的头插
//头插
void SLTPushFront(SLTNode** pphead, SLTDateType x)
{assert(pphead);SLTNode* newnode = BuyNewnode(x);newnode->next = *pphead;*pphead = newnode;SLTInsert(pphead, *pphead, x);
}
💡ps:头部操作只需要注意连接关系即可,时间复杂度为:O(1)
2.4单链表的尾删
//尾删
void SLTPopBack(SLTNode** pphead)
{assert(pphead);assert(*pphead);//删除操作,链表不可为空//特殊情况,如果链表只有一个结点是找不到前驱的,要进行特殊处理SLTNode* tail = *pphead;if (tail->next == NULL)//1个结点的情况{free(tail);*pphead = NULL;}else//多个结点的情况{SLTNode* prev = NULL;//1.找到尾结点和尾结点的前驱while (tail->next != NULL){prev = tail;//每次去下一个,用prev记录下来tail = tail->next;}//2.删除尾结点,进行嫁接和NULLfree(tail);tail = NULL;prev->next = NULL;}}
💡ps:找尾,时间复杂度为O(N)
由于尾删需要找尾结点的前驱,而只有一个结点的链表无法找到尾结点前驱,需要进行特殊处理。
2.5单链表的头删
void SLTPopFront(SLTNode** pphead)
{assert(pphead);assert(*pphead);SLTNode* first = *pphead;*pphead = first->next;free(first);
}
💡ps:时间复杂度为O(N)
2.6单链表的查找
//查找
SLTNode* SLTFind(SLTNode* phead, SLTDateType x)
{SLTNode* cur = phead;while (cur){if (cur->data == x){return cur;}else{cur = cur->next;}}return NULL;
}
2.7单链表的中间插入(在结点前插入)
//结点前插入
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDateType x)
{assert(pphead);assert(pos);SLTNode* newnode = BuyNewnode(x);//特殊情况//头插if (pos == *pphead){SLTPushFront(pphead, x);}SLTNode* prev = *pphead;//1.找pos的前驱while (prev->next != pos){prev = prev->next;}//2.嫁接prev->next = newnode;newnode->next = pos;
}
💡ps:由于需要找结点pos的前驱,时间复杂度O(N)
当pos为首结点时,无法找到pos的前驱需要进行特殊处理(头插操作)
2.8单链表的中间删除(删除该结点)
//删除该结点
void SLTErase(SLTNode** pphead, SLTNode* pos)
{assert(pphead);assert(*pphead);assert(pos);//特殊情况//头删if (*pphead == pos){SLTPopFront(pphead);}SLTNode* prev = *pphead;//1.找前驱while (prev->next != pos){prev = prev->next;}//2.嫁接prev->next = pos->next;free(pos);
}
💡ps:由于需要找结点pos的前驱,时间复杂度O(N)
当pos为首结点时,无法找到pos的前驱需要进行特殊处理(头删操作)
2.9单链表的中间插入(在结点后插入)
//结点后插入
void SLTInsertAfter(SLTNode* pos, SLTDateType x)
{assert(pos);SLTNode* newnode = BuyNewnode(x);newnode->next = pos->next;pos->next = newnode;
}
2.10单链表的中间删除(删除该结点的后继)
//删除该结点的后继
void SLTEraseAfter(SLTNode* pos)
{assert(pos);assert(pos->next);//不能尾删SLTNode* next = pos->next;pos->next = next->next;free(next);next = NULL;
}
2.11单链表的销毁
void SLTDestroy(SLTNode** pphead)//free完所有结点,将phead置空
{SLTNode* cur = *pphead;while (cur){SLTNode* next = cur->next;free(cur);cur = next;}*pphead = NULL;
}
3.单链表的优缺点
优点:
1. 头部操作,效率很高,时间复杂度为O(1)
2. 结点之间不是连续存储的,在进行插入操作时,无法考虑增容。
缺点:
1. 不支持随机访问,即使知道是第几个结点,也要进行遍历才能找到该结点。
2. 尾部操作要找结点,效率低下(如果使用一个直接来指向尾结点,也可实现O(1)的效率)
💡ps:对于空链表进行尾部操作时,需要进行特殊处理,这个时候我们可以构造一个哨兵位的头结点,使问题简化。
4. 链表的经典OJ题目训练
-
删除链表中等于给定值 val 的所有结点。 OJ链接
-
反转一个单链表。 OJ链接
-
给定一个带有头结点 head 的非空单链表,返回链表的中间结点。如果有两个中间结点,则返回第二个中间结点。OJ链接
-
输入一个链表,输出该链表中倒数第k个结点。 OJ链接
-
将两个有序链表合并为一个新的有序链表并返回。新链表是通过拼接给定的两个链表的所有结点组成的。OJ链接
-
编写代码,以给定值x为基准将链表分割成两部分,所有小于x的结点排在大于或等于x的结点之前 。OJ链接
-
链表的回文结构。OJ链接
-
输入两个链表,找出它们的第一个公共结点。OJ链接
-
给定一个链表,判断链表中是否有环。 OJ链接
-
给定一个链表,返回链表开始入环的第一个结点。 如果链表无环,则返回 NULL OJ链接
-
给定一个链表,每个结点包含一个额外增加的随机指针,该指针可以指向链表中的任何结点或空结点。
要求返回这个链表的深度拷贝。OJ链接
-
其他 。ps:链表的题当前因为难度及知识面等等原因还不适合我们当前学习,以后大家自己下去以后 Leetcode OJ链接 + 牛客 OJ链接
相关文章:

【数据结构】单链表:头部操作我很行,插入也不用增容!!!
单链表 文章目录单链表1.链表1.1链表的概念和结构1.2链表的分类2.单链表的模拟实现2.1单链表的打印2.2单链表的尾插2.3单链表的头插2.4单链表的尾删2.5单链表的头删2.6单链表的查找2.7单链表的中间插入(在结点前插入)2.8单链表的中间删除(删除该结点)2.9单链表的中间插入(在结点…...

SpringBoot——使用WebSocket功能
springboot自带websocket,通过几个简单的注解就可以实现websocket的功能; 启动类跟普通的springboot一样: /*** 2023年3月2日下午4:16:57*/ package testspringboot.test7websocket;import org.springframework.boot.SpringApplication; im…...

博弈论小课堂:非零和博弈(实现双赢)【纳什均衡点】
文章目录 引言I 非零和博弈1.1 囚徒问题1.2 博弈中双方的收益矩阵II 在现实中找均衡点2.1 博弈通常不是一次性的,而是反复进行的2.2 博弈论讲的都是阳谋的策略2.3 人类还处于文明的初级阶段,人的道德水准不容高估2.4 乌合之众效应2.5 很多时候看似是双赢,其实是在更大范围内…...

数组中的逆序对
解题思路1: 看到这个题目,我们的第一反应是顺序扫描整个数组。每扫描到一个数组的时候,逐个比较该数字和它后面的数字的大小。如果后面的数字比它小,则这两个数字就组成了一个逆序对。假设数组中含有n个数字。由于每个数字都要和…...

C++基础了解-01-基础语法
基础语法 一、基础语法 C 程序可以定义为对象的集合,这些对象通过调用彼此的方法进行交互。现在让我们简要地看一下什么是类、对象,方法、即时变量。 对象 - 对象具有状态和行为。例如:一只狗的状态 - 颜色、名称、品种,行为 -…...

phpmyadmin 文件包含(CVE-2014-8959)
0x01 漏洞介绍 phpMyAdmin是phpMyAdmin团队开发的一套免费的、基于Web的MySQL数据库管理工具。该工具能够创建和删除数据库,创建、删除、修改数据库表,执行SQL脚本命令等。phpMyAdmin的GIS编辑器中libraries/gis/GIS_Factory.class.php脚本存在目录遍历漏洞。远程攻击者可借助…...

SpringBoot集成MyBatis
目录 实现步骤 1. 在项目的 pom.xml 配置文件中引入如下依赖 2. 在项目的 application.properties 配置文件中添加如下依赖 3. 新建 UserMapper.class 接口类,添加如下 3 个方法 4. 在 /resources/mybatis/mapper 路径(需要手动创建文件夹)下创建 UserMapper.xm…...

MySQL-索引
索引介绍索引是对数据库表中一列或者多列的值进行排序的一种结构,使用索引可提高数据库中特定数据的查询速度。索引是一个单独的、存储在磁盘上的数据库结构,它们包含着对数据表里所有记录的引用指针。使用索引用于快速找出在某个或多个列中有一特定值得…...

【STM32存储器映射-寄存器基地址-偏移】
前言 在学习STM32的时候,我们看到很多的寄存器编程, 比方说LED灯: //GPIOB.5端口输出高电平GPIOB->ODR|1<<5; //PB.5 输出高GPIOE->ODR|1<<5; //PE.5输出高 //GPIOB端口全部输出高电平*(unsigned int*)(0x4001 …...

【华为OD机试2023】最多颜色的车辆 C++ Java Python
【华为OD机试2023】最多颜色的车辆 C++ Java Python 前言 如果您在准备华为的面试,期间有想了解的可以私信我,我会尽可能帮您解答,也可以给您一些建议! 本文解法非最优解(即非性能最优),不能保证通过率。 Tips1:机试为ACM 模式 你的代码需要处理输入输出,input/cin接收…...

特斯拉后端面试(部分)
HR告知如果面试通过要转.net-_- round1 有没有用过Java新版本,知道有哪些特性吗?A:没有。Q:我们基本在用JDK11,有的新项目用到JDK17了。参考答案1: ZGC: A Scalable Low-Latency Garbage Collector Epsi…...

【python】使用python将360个文件夹里的照片,全部复制到指定的文件夹中,并且按照顺序重新命名
最近要做一个图像生成的课题,在网上找了一个混合的数据集。这个数据集中一共有360个文件夹,然后文件夹中有6-9张不等的照片,我的目标就是编写python代码将所有的照片取出来,放到一个指定的文件夹里,并且从1开始按照顺序…...

【C语言】3天速刷C语言(初识)
【声明】本篇博客只用于对与刚学习C语言的同学的一个初始了解,具体内容请继续关注本专栏后续内容。什么是C语言C语言是一门通用计算机编程语言,广泛应用于底层开发。C语言的设计目标是提供一种能以简易的方式编译、处理低级存储器、产生少量的机器码以及…...

如何搞定MySQL锁(全局锁、表级锁、行级锁)?这篇文章告诉你答案!太TMD详细了!!!
概述 锁是计算机协调多个进程或线程并发访问某一资源的机制。在数据库中,除传统的计算资源(CPU、RAM、I/O)的争用以外,数据也是一种供许多用户共享的资源。如何保证数据并发访问的一致性、有效性是所有数据库必须解决的一个问题&…...

云计算生态该怎么做?阿里云计算巢打了个样
2023 年 2 月 23 日至 24 日,由阿里云主办的「阿里云计算巢加速器」于杭州阿里云谷园区集结。 阿里云计算巢加速器于 2022 年 8 月正式启动招募,最终百奥利盟、极智嘉、EMQ、KodeRover、MemVerge 等 30 家创新企业入选计算加速器,覆盖了人工智…...

小樽C++ 多章⑧ (贰) 指针与数组
目录 1.C中数组变量名某些情况可以看成是指针 2.C语言的scanf 输入语句,printf 输出语句 3.用指针来当动态数组 小樽C 多章⑧ (壹) 指针变量https://blog.csdn.net/weixin_44775255/article/details/129031168 小樽C 多章⑧ (叁) 指针与字符串、(肆) 函数与指针…...

MXNet的机器翻译实践《编码器-解码器(seq2seq)和注意力机制》
机器翻译就是将一种语言翻译成另外一种语言,输入和输出的长度都是不定长的,所以这里会主要介绍两种应用,编码器-解码器以及注意力机制。编码器是用来分析输入序列,解码器用来生成输出序列。其中在训练时,我们会使用一些…...

RK3588平台开发系列讲解(同步与互斥篇)自旋锁介绍
平台内核版本安卓版本RK3588Linux 5.10Android 12文章目录 一、自旋锁介绍二、自旋锁相关的函数1、普通场景2、进程上下文和下半部3、中断相关三、相关结构体四、函数实现1、初始化2、获取自旋锁沉淀、分享、成长,让自己和他人都能有所收获!😄 📢本篇介绍自旋锁的使用和基…...

Linux系统CPU占用率较高问题排查思路
作为工程师,在日常工作中我们会遇到 Linux服务器上出现CPU负载达到100%居高不下的情况,如果CPU 持续跑高,则会影响业务系统的正常运行,带来企业损失。对于CPU过载问题通常使用以下两种方式即可快速定位:方法一第一步&a…...

源码解析——HashMap
源码解析——HashMap1. 什么 是HashMap2. 为什么要使用HashMap3. HashMap的使用4. 源码解析4.1 关键问题4.1 存储结构4.2 HashMap 的容量和负载因子4.3 初始化过程4.3 put() 方法实现原理4.3.1 hash()4.3.2 resize()4.4 get() 方法实现原理5. 面试题总结6. ConcurrentHashmap(J…...

Elasticsearch 核心技术(六):内置的 8 种分词器详解 + 代码示例
❤️ 博客主页:水滴技术 🚀 支持水滴:点赞👍 收藏⭐ 留言💬 🌸 订阅专栏:大数据核心技术从入门到精通 文章目录一、内置分词器1. Standard(标准分词器)英文示例中文示例…...

Mysql8.0的特性
Mysql8.0的特性 建议使用8.0.17及之后的版本,更新的内容比较多。 新增降序索引 -- 如下所示,我们可以在创建索引时 在字段名后面指定desc进行降序排序 create table t1(c1 int,c2 int,index idx_c1_c2(c1,c2 desc));group by 不再隐式排序 mysql5.7的版…...

JDK动态代理(tedu)(内含源代码)
JDK动态代理(tedu)(内含源代码) 源代码下载链接地址:https://download.csdn.net/download/weixin_46411355/87546187 目录JDK动态代理(tedu)(内含源代码)源代码下载链接…...

【数据结构】二叉搜索树
1、什么是二叉搜索树二叉搜索树又称为二叉排序树,二叉也就说明它跟二叉树一样最多只能有两个度,它可以是棵空树,也可以不是棵空树,当它不是棵空树的时候需要具备以下的性质:若它的左树不为空,那么它的左树上…...

抢跑数字中国建设,青岛市统计系统考察团赴实在智能调研统计数字员工
当前,数据要素价值不断显现,数字经济正引领着政企业加快数字技术的应用,融通创新工作机制,推进高质量转型。近日,中共中央、国务院印发了《数字中国建设整体布局规划》。《规划》指出,到2025年,…...

深浅拷贝——利用模拟实现basic_string深入理解
深浅拷贝——利用模拟实现basic_string深入理解 一、深浅拷贝的基本概念 深拷贝和浅拷贝都是指在对象复制时,复制对象的内存空间的方式。 1.1 深浅拷贝的不同之处 浅拷贝是指将一个对象的所有成员变量都直接拷贝给另一个对象,包括指针成员变量&#…...

大模型分布式系统
背景:模型越来越大,训练复杂度越来越高,需要训练的时间也是越来越长。那么我们该如何在现有的硬件基础上对模型做训练呢。模型规模的扩大,对硬件(算力、内存)的发展提出要求。然而,因为 内存墙 …...

【时序】时序预测任务模型选择如何选择?
时间序列是什么时间序列是一种特殊类型的数据集,其中一个或多个变量随着时间的推移被测量。 在时间序列中,观测值是随着时间的推移而测量的。你的数据集中的每个数据点都对应着一个时间点。这意味着你的数据集的不同数据点之间存在着一种关系。这对可以应用于时间序列数据集的…...

重温数据结构与算法之深度优先搜索
文章目录前言一、实现1.1 递归实现1.2 栈实现1.3 两者区别二、LeetCode 实战2.1 二叉树的前序遍历2.2 岛屿数量2.3 统计封闭岛屿的数目2.4 从先序遍历还原二叉树参考前言 深度优先搜索(Depth First Search,DFS)是一种遍历或搜索树或图数据结…...

STM32F103驱动LD3320语音识别模块
STM32F103驱动LD3320语音识别模块LD3320语音识别模块简介模块引脚定义STM32F103ZET6开发板与模块接线测试代码实验结果LD3320语音识别模块简介 基于 LD3320,可以在任何的电子产品中,甚至包括最简单的 51 作为主控芯片的系统中,轻松实现语音识…...