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

单链表基础操作

文章目录

    • abstract
    • 定义结点结构
    • 初始化链表
    • 遍历链表
    • 求表长
    • 查找结点
      • 根据序号查找结点
      • 根据值查找结点
    • 插入结点
      • 首尾位置插入
      • 一般位置插入(通用插入)
      • 找到尾元素|尾指针相关操作
    • 删除结点

abstract

单链表是一种简单的动态数据结构,它由一系列结点组成,每个结点包含一个数据域和一个指向下一个结点的指针。

带头结点的单链表的头结点不存储数据,仅用于指向第一个真正存储数据的结点。

以下是C语言中单链表的一些常用操作:(默认带有头结点)

定义结点结构

另见:链表@单链表相关概念和代码表述-CSDN博客

typedef struct Node
{int data;struct Node *next;
} Node;
typedef Node *LinkList;
//为了提高可读性,利用typedef和Node类型定义一个LinkList类型,效果:ListList L;等价于Node *L;// typedef *Node LinkList;//这种定义是错误的

初始化链表

Node* initList() {Node* head = (Node*)malloc(sizeof(Node));head->next = NULL;return head;
}

遍历链表

遍历链表并打印每个结点的数据:

void printList(Node* head) {Node* p = head->next; // 从首元开始while (p != NULL) {printf("%d -> ", p->data);p = p->next;}printf("NULL\n");
}

求表长

int Length(Node* L){int len=0;//记录链表长度Node *p=L;//p初始化为头指针while(p->next!=NULL){p=p->next;//正式更新p,最后一趟(p->next是尾元,p是倒数第二个结点)p会被此语句更新为尾元len++;//刷新此时p所指结点的位序}//退出循环时,p是尾结点,其后继为NULLreturn len;
}

或者

int Length(Node* L){int len=0;//记录链表长度Node *p=L->next;//p初始化为首元(可能为空)while(p){//最有一次进入循环是p为尾元的情况len++;//刷新此时p所指结点的位序p=p->next;}//离开是p==NULLreturn len;
}

查找结点

分两两种类型:按序号查找和安值查找

根据序号查找结点

Node *getElem(Node*L,int i){Node *p=L;//辅助指针初始化为头指针(头结点指针);int j=0;//指示p指向第几个结点(头结点是第0个结点),从而判断p是否为目标结点可以通用判断j==i来实现while(p!=NULL && j<i){//这种判断条件允许参数i=0;这会返回头结点(而非首元)p=p->next; //p->next从首元开始j++; }//最后一次进入循环是p为尾元或者j=i-1;离开循环时p是尾元的后继NULL,即p==NULL或j==i;如果是NULL说明找不到想要的结点(越界)return p;
}
//这里用不着p指向尾元,所以while条件中用了p!=NULL

根据值查找结点

Node* LocateElem(Node* head, int e) {Node* p = head->next; // 从首元开始while(p!=NULL && p->data!=e){p=p->next;}return p;}
Node* LocateElem(Node* head, int e) {Node* p = head->next; // 从首元开始//判断条件分开写也可以while (p != NULL) {if (p->data == e) return p;p = p->next;}return NULL;
}

插入结点

在带头结点的单链表中,我们可以在任意位置插入一个新结点。

首尾位置插入

// 头插法
void insertAtHead(Node* head, int data) {Node* newNode = (Node*)malloc(sizeof(Node));newNode->data = data;newNode->next = head->next;head->next = newNode;
}// 尾插法
void insertAtTail(Node* head, int data) {Node* newNode = (Node*)malloc(sizeof(Node));newNode->data = data;newNode->next = NULL;//通过遍历找到最后一个结点,链接新结点Node* p = head;//辅助指针遍历while (p->next != NULL) {p = p->next;}//退出时说明p指向尾结点(非空)//链接尾部新结点p->next = newNode;
}

一般位置插入(通用插入)

找到要插入位置的前驱结点,然后执行插入

#define bool int
#define true 1
#define false 0bool ListInsert(Node*L,int i,ElemType e){Node*p=L;int j=0;//指示当前p所指的结点位序//找到要插入的位置结点的前驱(第i-1)个结点while(p!=NULL && j<i-1){p=p->next;j++;}//离开循环时,若干长度足够,那么是由于j==i-1,否则p==NULL发生越界//检查j的合法性(越界)if(p==NULL){return false;}//新建结点Node *s=(Node*)malloc(sizeof(Node));s->data=e;//插入结点s->next=p->next;p->next=s;return true;
}

找到尾元素|尾指针相关操作

读者可能会考虑以下写法来遍历整个链表

Node* p = head->next;//首元
while (p) {p = p->next;
}//离开循环时p已经是NULL而不是尾结点了,这往往不是我们想要的,尤其是要后续访问或删除尾结点的操作将无法直接利用p进行

因此该写法不利于后续灵活处理,通常把循环语句中的判断语句写成(p->next!=NULL)

或者配合break语句也可以找出最后一个非空结点的指针p

Node* p = head->next;//首元
while (p) {//也可以是while(1)if(p->next==NULL){break;}p = p->next;//可以保证这个赋值内容是非空的
}//退出时说明p指向尾结点(非空)

这种写法虽然也可以,但是简洁和紧凑程度不如下面的做法

 while (p->next != NULL) {p = p->next;
}

删除结点

删除指定位置的结点,可以是根据位置删除或者根据值删除:

若根据位序删除(位序范围 1 ∼ n 1\sim{n} 1n,其中 n n n为链表长度)

根据值删除结点

// 根据值删除结点
void deleteByValue(Node* head, int value) {Node* p = head;while (p->next != NULL && p->next->data != value) {p = p->next;}if (p->next != NULL) {Node* toDelete = p->next;p->next = toDelete->next;free(toDelete);}
}

找到目标结点的前驱,然后执行删除

#define bool int
#define true 1
#define false 0
bool ListDelete(Node *L, int i, ElemType *e)
{Node *p = L;int j = 0;// 找到第i个结点的前驱(第i-1个结点)while (p && j < i - 1){p = p->next;j++;}// 如果此时p是尾结点(后继结点为空,不用删除)或者空指针(没有后继),两种情况都说明i不合法if (p == NULL || p->next == NULL){return false;}Node *q = p->next;*e = q->data; // 返回被删除的值p->next = q->next;//更新后继(断开q结点)free(q);//释放q的内存空间return true;
}

相关文章:

单链表基础操作

文章目录 abstract定义结点结构初始化链表遍历链表求表长查找结点根据序号查找结点根据值查找结点 插入结点首尾位置插入一般位置插入(通用插入)找到尾元素|尾指针相关操作 删除结点 abstract 单链表是一种简单的动态数据结构&#xff0c;它由一系列结点组成&#xff0c;每个结…...

Asp.net MVC在VSCore中的页面的增删改查(以Blog项目为例),用命令代码

在VSCore中的页面的增删改查(以Blog项目为例) 1.创建项目&#xff08;无解决方案&#xff09;复杂项目才需要 dotnet new mvc -o Blog2.控制器 BlogsController.cs 控制器&#xff08;Controller&#xff09;名字和视图&#xff08;View&#xff09;中的文件名要一模一样 u…...

【Leecode】Leecode刷题之路第66天之加一

题目出处 66-加一-题目出处 题目描述 个人解法 思路&#xff1a; todo代码示例&#xff1a;&#xff08;Java&#xff09; todo复杂度分析 todo官方解法 66-加一-官方解法 方法1&#xff1a;找出最长的后缀9 思路&#xff1a; 代码示例&#xff1a;&#xff08;Java&#…...

使用 VLC 在本地搭建流媒体服务器 (详细版)

提示&#xff1a;详细流程 避坑指南 Hi~&#xff01;欢迎来到碧波空间&#xff0c;平时喜欢用博客记录学习的点滴&#xff0c;欢迎大家前来指正&#xff0c;欢迎欢迎~~ ✨✨ 主页&#xff1a;碧波 &#x1f4da; &#x1f4da; 专栏&#xff1a;音视频 目录 借助VLC media pl…...

Ubuntu 常用解压与压缩命令

.zip文件 unzip FileName.zip # 解压 zip DirName.zip DirName # 将DirName本身压缩 zip -r DirName.zip DirName # 压缩&#xff0c;递归处理&#xff0c;将指定目录下的所有文件和子目录一起压缩 zip DirName.zip DirName 行为&#xff1a; 只压缩 DirName 目录本身&#xff…...

【深度学习】四大图像分类网络之AlexNet

AlexNet是由Alex Krizhevsky、Ilya Sutskever&#xff08;均为Hinton的学生&#xff09;和Geoffrey Hinton&#xff08;被誉为”人工智能教父“&#xff0c;首先将反向传播用于多层神经网络&#xff09;在2012年ImageNet图像分类竞赛中提出的一种经典的卷积神经网络。AlexNet在…...

Day1——GitHub项目共同开发

MarkDowm解释 Markdown是一种轻量级标记语言&#xff0c;它允许人们使用易读易写的纯文本格式编写文档&#xff0c;然后转换成结构化的HTML代码。Markdown的目的是让文档的编写和阅读变得更加容易&#xff0c;同时也不失HTML的强大功能。以下是Markdown的一些基本概念和用法&a…...

基于PHP的香水销售系统的设计与实现

摘 要 时代科技高速发展的背后&#xff0c;也带动了经济的增加&#xff0c;人们对生活质量的要求也不断提高。香水作为一款在人际交往过程中&#xff0c;给对方留下良好地第一印象的产品&#xff0c;在生活中也可以独自享受其为生活带来的点缀。目前香水市场体量庞大&#xff…...

A-star算法

算法简介 A*&#xff08;A-star&#xff09;算法是一种用于图形搜索和路径规划的启发式搜索算法&#xff0c;它结合了最佳优先搜索&#xff08;Best-First Search&#xff09;和Dijkstra算法的思想&#xff0c;能够有效地寻找从起点到目标点的最短路径。A*算法广泛应用于导航、…...

前端用原生js下载File对象文件,多用于上传附件时,提交之前进行点击预览,或打开本地已经选择待上传的附件列表

用于如上图场景&#xff0c;已经点击选择了将要上传的文件&#xff0c;在附件列表里面用户希望点击下载文件&#xff0c;以核实自己是否选中了需要上传的文件&#xff0c;此刻就需要 用到下面的方法&#xff1a; // 下载File对象文件 downloadByFileObject(file, { fileName }…...

服务器记录所有用户docker操作,监控删除容器/镜像的人

文章目录 使用场景安装auditd添加docker审计规则设置监控日志大小与定期清除查询 Docker 操作日志查看所有用户&#xff0c;所有操作日志查看特定用户的 Docker 操作查看所有用户删除容器/镜像日志过滤特定时间范围内日志 使用场景 多人使用的服务器&#xff0c;使用的docker …...

关于使用天地图、leaflet、ENVI、Vue工具实现 前端地图上覆盖上处理的农业地块图层任务

1.项目框架搭建 项目地址&#xff1a;Webgis: 一个关于webgis、天地图、Leaflet、Vue、数据库的学习框架。 ①git到本地&#xff0c;vscode打开。 ② 配置后端 搜索下载MySQL插件&#xff08;前提&#xff1a;电脑中装有MySQL才可应用&#xff09;。 连接数据库。 配置基本…...

基于yolov4深度学习网络的排队人数统计系统matlab仿真,带GUI界面

目录 1.算法仿真效果 2.算法涉及理论知识概要 3.MATLAB核心程序 4.完整算法代码文件获得 1.算法仿真效果 matlab2022a仿真结果如下&#xff08;完整代码运行后无水印&#xff09;&#xff1a; 仿真操作步骤可参考程序配套的操作视频。 2.算法涉及理论知识概要 在现代社会…...

用 React 编写一个笔记应用程序

这篇文章会教大家用 React 编写一个笔记应用程序。用户可以创建、编辑、和切换 Markdown 笔记。 1. nanoid nanoid 是一个轻量级和安全的唯一字符串ID生成器&#xff0c;常用于JavaScript环境中生成随机、唯一的字符串ID&#xff0c;如数据库主键、会话ID、文件名等场景。 …...

如何离线安装dockerio

如何离线安装dockerio 一、下载Docker离线安装包二、上传离线安装包三、解压安装包四、复制文件到系统目录五、配置Docker服务六、设置文件权限并重新加载配置七、启动Docker服务八、设置开机自启动九、验证安装Docker是一个开源的容器化平台,用于开发、发布和运行应用程序。离…...

LocalDateTime序列化(跟redis有关)

使用过 没成功&#xff0c;序列化后是[2024 11 10 17 22 20]差不多是这样&#xff0c; 反序列化后就是&#xff1a; [ 2024 11 10.... ] 可能是我漏了什么 这是序列化后的&#xff1a; 反序列化后&#xff1a; 方法&#xff08;加序列化和反序列化注解&#xff09;&…...

【redis】如何跑

在 Windows 上配置 Redis 需要一些额外的步骤&#xff0c;因为 Redis 官方并没有为 Windows 提供原生支持。不过&#xff0c;可以通过以下方法来安装和配置 Redis。 方法一&#xff1a;使用 Windows 版 Redis&#xff08;非官方版本&#xff09; 下载 Redis for Windows Redis…...

Scala学习记录,全文单词统计

package test32 import java.io.PrintWriter import scala.io.Source //知识点 // 字符串.split("分隔符"&#xff1a;把字符串用指定的分隔符&#xff0c;拆分成多个部分&#xff0c;保存在数组中) object test {def main(args: Array[String]): Unit {//从文件1.t…...

【MyBatis】验证多级缓存及 Cache Aside 模式的应用

文章目录 前言1. 多级缓存的概念1.1 CPU 多级缓存1.2 MyBatis 多级缓存 2. MyBatis 本地缓存3. MyBatis 全局缓存3.1 MyBatis 全局缓存过期算法3.2 CacheAside 模式 后记MyBatis 提供了缓存切口&#xff0c; 采用 Redis 会引入什么问题&#xff1f;万一遇到需强一致场景&#x…...

学习ASP.NET Core的身份认证(基于Session的身份认证3)

开源博客项目Blog中提供了另一种访问控制方式&#xff0c;其基于自定义类及函数的特性类控制访问权限。本文学习并测试开源博客项目Blog的访问控制方式&#xff0c;测试程序中直接复用开源博客项目Blog中的相关类及接口定义&#xff0c;并在其上调整判断逻辑。   首先是接口A…...

Linux 文件类型,目录与路径,文件与目录管理

文件类型 后面的字符表示文件类型标志 普通文件&#xff1a;-&#xff08;纯文本文件&#xff0c;二进制文件&#xff0c;数据格式文件&#xff09; 如文本文件、图片、程序文件等。 目录文件&#xff1a;d&#xff08;directory&#xff09; 用来存放其他文件或子目录。 设备…...

Lombok 的 @Data 注解失效,未生成 getter/setter 方法引发的HTTP 406 错误

HTTP 状态码 406 (Not Acceptable) 和 500 (Internal Server Error) 是两类完全不同的错误&#xff0c;它们的含义、原因和解决方法都有显著区别。以下是详细对比&#xff1a; 1. HTTP 406 (Not Acceptable) 含义&#xff1a; 客户端请求的内容类型与服务器支持的内容类型不匹…...

Java 语言特性(面试系列1)

一、面向对象编程 1. 封装&#xff08;Encapsulation&#xff09; 定义&#xff1a;将数据&#xff08;属性&#xff09;和操作数据的方法绑定在一起&#xff0c;通过访问控制符&#xff08;private、protected、public&#xff09;隐藏内部实现细节。示例&#xff1a; public …...

Unity3D中Gfx.WaitForPresent优化方案

前言 在Unity中&#xff0c;Gfx.WaitForPresent占用CPU过高通常表示主线程在等待GPU完成渲染&#xff08;即CPU被阻塞&#xff09;&#xff0c;这表明存在GPU瓶颈或垂直同步/帧率设置问题。以下是系统的优化方案&#xff1a; 对惹&#xff0c;这里有一个游戏开发交流小组&…...

基于Docker Compose部署Java微服务项目

一. 创建根项目 根项目&#xff08;父项目&#xff09;主要用于依赖管理 一些需要注意的点&#xff1a; 打包方式需要为 pom<modules>里需要注册子模块不要引入maven的打包插件&#xff0c;否则打包时会出问题 <?xml version"1.0" encoding"UTF-8…...

相机Camera日志分析之三十一:高通Camx HAL十种流程基础分析关键字汇总(后续持续更新中)

【关注我,后续持续新增专题博文,谢谢!!!】 上一篇我们讲了:有对最普通的场景进行各个日志注释讲解,但相机场景太多,日志差异也巨大。后面将展示各种场景下的日志。 通过notepad++打开场景下的日志,通过下列分类关键字搜索,即可清晰的分析不同场景的相机运行流程差异…...

EtherNet/IP转DeviceNet协议网关详解

一&#xff0c;设备主要功能 疆鸿智能JH-DVN-EIP本产品是自主研发的一款EtherNet/IP从站功能的通讯网关。该产品主要功能是连接DeviceNet总线和EtherNet/IP网络&#xff0c;本网关连接到EtherNet/IP总线中做为从站使用&#xff0c;连接到DeviceNet总线中做为从站使用。 在自动…...

【OSG学习笔记】Day 16: 骨骼动画与蒙皮(osgAnimation)

骨骼动画基础 骨骼动画是 3D 计算机图形中常用的技术&#xff0c;它通过以下两个主要组件实现角色动画。 骨骼系统 (Skeleton)&#xff1a;由层级结构的骨头组成&#xff0c;类似于人体骨骼蒙皮 (Mesh Skinning)&#xff1a;将模型网格顶点绑定到骨骼上&#xff0c;使骨骼移动…...

A2A JS SDK 完整教程:快速入门指南

目录 什么是 A2A JS SDK?A2A JS 安装与设置A2A JS 核心概念创建你的第一个 A2A JS 代理A2A JS 服务端开发A2A JS 客户端使用A2A JS 高级特性A2A JS 最佳实践A2A JS 故障排除 什么是 A2A JS SDK? A2A JS SDK 是一个专为 JavaScript/TypeScript 开发者设计的强大库&#xff…...

如何更改默认 Crontab 编辑器 ?

在 Linux 领域中&#xff0c;crontab 是您可能经常遇到的一个术语。这个实用程序在类 unix 操作系统上可用&#xff0c;用于调度在预定义时间和间隔自动执行的任务。这对管理员和高级用户非常有益&#xff0c;允许他们自动执行各种系统任务。 编辑 Crontab 文件通常使用文本编…...