手搓单链表(无哨兵位)(C语言)
目录
SLT.h
SLT.c
SLTtest.c
测试示例
单链表优劣分析
SLT.h
#pragma once#include <stdio.h>
#include <assert.h>
#include <stdlib.h>typedef int SLTDataType;typedef struct SListNode
{SLTDataType data;struct SListNode* next;
}SLTNode;//打印单链表
void SLTPrint(SLTNode* phead);
//创建节点
SLTNode* BuySLTNode(SLTDataType x);
//尾插
void SLTPushBack(SLTNode** pphead, SLTDataType x);
//尾删
void SLTPopBack(SLTNode** pphead);
//头插
void SLTPushFront(SLTNode** pphead, SLTDataType x);
//头删
void SLTPopFront(SLTNode** pphead);//单链表查找
SLTNode* SLTFind(SLTNode* phead, SLTDataType x);
//在pos之前插入
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x);
//删除pos位置
void SLTErase(SLTNode** pphead, SLTNode* pos);//单链表在pos位置之后插入x
void SListInsertAfter(SLTNode* pos, SLTDataType x);
//单链表删除pos位置之后的值
void SListEraseAfter(SLTNode* pos);//销毁单链表
void SLTDestroy(SLTNode** pphead);
SLT.c
#include "SLT.h"//打印单链表
void SLTPrint(SLTNode* phead)
{SLTNode* cur = phead;while (cur){printf("%d->", cur->data);cur = cur->next;}printf("NULL\n");
}//创建节点
SLTNode* BuySLTNode(SLTDataType x)
{SLTNode* node = (SLTNode*)malloc(sizeof(SLTNode));if (node == NULL){perror("SLTBuysNode");exit(-1);}node->data = x;node->next = NULL;return node;
}//尾插
void SLTPushBack(SLTNode** pphead, SLTDataType x)
{assert(pphead);if (*pphead == NULL){*pphead = BuySLTNode(x);}else{SLTNode* tail = *pphead;while (tail->next){tail = tail->next;}tail->next = BuySLTNode(x);}
}//尾删
void SLTPopBack(SLTNode** pphead)
{assert(pphead);assert(*pphead);if ((*pphead)->next == NULL){free(*pphead);*pphead = NULL;}else{SLTNode* tail = *pphead;while (tail->next->next){tail = tail->next;}free(tail->next->next);tail->next = NULL;}
}//头插
void SLTPushFront(SLTNode** pphead, SLTDataType x)
{assert(pphead);SLTNode* newnode = BuySLTNode(x);newnode->next = *pphead;*pphead = newnode;
}//头删
void SLTPopFront(SLTNode** pphead)
{assert(pphead);assert(*pphead);SLTNode* newhead = (*pphead)->next;free(*pphead);*pphead = newhead;
}// 单链表查找
SLTNode* SLTFind(SLTNode* phead, SLTDataType x)
{SLTNode* cur = phead;while (cur){if (cur->data == x){//找到了return cur;}cur = cur->next;}//找不到return NULL;
}//在pos之前插入
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{assert(pphead);if (*pphead == pos){SLTNode* newnode = BuySLTNode(x);newnode->next = *pphead;*pphead = newnode;}else{SLTNode* cur = *pphead;while (cur->next != pos){cur = cur->next;}SLTNode* newnode = BuySLTNode(x);cur->next = newnode;newnode->next = pos;}}// 删除pos位置
void SLTErase(SLTNode** pphead, SLTNode* pos)
{assert(pphead);assert(*pphead && pos);if (*pphead == pos){SLTNode* newhead = (*pphead)->next;free(*pphead);*pphead = newhead;}else{SLTNode* cur = *pphead;while (cur->next != pos){cur = cur->next;}SLTNode* pos_next = pos->next;free(pos);cur->next = pos_next;}}// 单链表在pos位置之后插入x
void SListInsertAfter(SLTNode* pos, SLTDataType x)
{assert(pos);SLTNode* newnode = BuySLTNode(x);newnode->next = pos->next;pos->next = newnode;
}// 单链表删除pos位置之后的值
void SListEraseAfter(SLTNode* pos)
{assert(pos && pos->next);SLTNode* pos_next_next = pos->next->next;free(pos->next);pos->next = pos_next_next;
}//销毁单链表
void SLTDestroy(SLTNode** pphead)
{assert(pphead);assert(*pphead);while (*pphead){SLTNode* newhead = (*pphead)->next;free(*pphead);*pphead = newhead;}
}
SLTtest.c
#include "SLT.h"void SLTtest1()
{SLTNode* phead = NULL;SLTPrint(phead);SLTPushBack(&phead, 1);SLTPushBack(&phead, 2);SLTPushBack(&phead, 3);SLTPushBack(&phead, 4);SLTPushBack(&phead, 5);SLTPrint(phead);SLTPopBack(&phead);SLTPrint(phead);SLTPopBack(&phead);SLTPrint(phead);SLTPopBack(&phead);SLTPrint(phead);SLTPopBack(&phead);SLTPrint(phead);SLTPopBack(&phead);SLTPrint(phead);/*SLTPopBack(&phead);SLTPrint(phead);*/
}
void SLTtest2()
{SLTNode* phead = NULL;SLTPrint(phead);SLTPushFront(&phead, 1);SLTPushFront(&phead, 2);SLTPushFront(&phead, 3);SLTPushFront(&phead, 4);SLTPushFront(&phead, 5);SLTPrint(phead);/*SLTDestroy(&phead);SLTPrint(phead);*//*SLTPopFront(&phead);SLTPrint(phead);SLTPopFront(&phead);SLTPrint(phead);SLTPopFront(&phead);SLTPrint(phead);SLTPopFront(&phead);SLTPrint(phead);SLTPopFront(&phead);SLTPrint(phead);*//*SLTPopFront(&phead);SLTPrint(phead);*/
}
void SLTtest3()
{SLTNode* phead = NULL;SLTPrint(phead);SLTPushFront(&phead, 1);SLTPushFront(&phead, 2);SLTPushFront(&phead, 3);SLTPushFront(&phead, 4);SLTPushFront(&phead, 5);SLTPrint(phead);//在pos位置之前插入删除SLTInsert(&phead, phead, 10);SLTPrint(phead);SLTInsert(&phead, NULL, 20);SLTPrint(phead);SLTNode* pos = SLTFind(phead, 3);SLTInsert(&phead, pos, 30);SLTPrint(phead);//删除pos位置的值SLTErase(&phead, phead);SLTPrint(phead);pos = SLTFind(phead, 3);SLTErase(&phead, pos);SLTPrint(phead);pos = SLTFind(phead, 20);SLTErase(&phead, pos);SLTPrint(phead);
}void SLTtest4()
{SLTNode* phead = NULL;SLTPrint(phead);SLTPushFront(&phead, 1);SLTPushFront(&phead, 2);SLTPushFront(&phead, 3);SLTPushFront(&phead, 4);SLTPushFront(&phead, 5);SLTPrint(phead);//在pos位置之后插入SListInsertAfter(phead, 10);SLTPrint(phead);SLTNode* pos = SLTFind(phead, 3);SListInsertAfter(pos, 30);SLTPrint(phead);pos = SLTFind(phead, 1);SListInsertAfter(pos, 10);SLTPrint(phead);//删除pos位置之后的值SListEraseAfter(phead);SLTPrint(phead);pos = SLTFind(phead, 4);SListEraseAfter(pos);SLTPrint(phead);}
int main()
{//测试尾插尾删//SLTtest1();//测试头插头删//SLTtest2();//在pos位置之前插入删除//SLTtest3();//在pos位置之后插入删除//SLTtest4();return 0;
}
测试示例
尾插尾删:

头插头删:

在pos位置之前插入:

删除pos位置的值:

在pos位置之后插入删除:

单链表优劣分析
单链表在逻辑上连续,在物理上不一定连续,用多少申请多少空间,因此不存在空间浪费且申请空间开销小;插入删除元素时无需挪动元素,只需要改变指向即可,但除头插头删,在pos位置之后插入删除外需要先遍历链表,效率低下;不支持随机访问;缓存利用率低。
总结:单链表具有较大的缺陷,相较于顺序表而言没有明显的优势,因此在实践中几乎没有应用场景。
相关文章:
手搓单链表(无哨兵位)(C语言)
目录 SLT.h SLT.c SLTtest.c 测试示例 单链表优劣分析 SLT.h #pragma once#include <stdio.h> #include <assert.h> #include <stdlib.h>typedef int SLTDataType;typedef struct SListNode {SLTDataType data;struct SListNode* next; }SLTNode;//打印…...
代码随想录算法训练营第18天|二叉树
513. 找树左下角的值 最左边的结点的特性 1.只能是叶子结点, 2.必须考虑是最底层,所以要考虑树的深度 3.同样的深度考虑左子树 考虑迭代法,层序遍历 递归优点难搞的 /*** Definition for a binary tree node.* function TreeNode(val, left, righ…...
使用tftpd更新开发板内核
我们升级内核可以通过原厂提供的升级软件来进行,比如瑞芯微的RKDevTool.exe,只不过这种方式必须通过指定的OTG升级口,还得借助按键进入loader模式后才可以。 其实还可以利用一些通用的工具来进行升级,比如tftpd工具。 下载地址p…...
MySQL数据库整体知识点简述
目录 第一章:数据库系统概述 第二章:信息与数据模型 第3章 关系模型与关系规范化理论 第四章——数据库设计方法 第六-七章——MySQL存储引擎与数据库操作管理 第九章——索引 第10章——视图 第11章——MySQL存储过程与函数 第12章——MySQL 触…...
深入理解MySQL索引下推优化
在MySQL中,索引的使用对于查询性能至关重要。然而,即使有合适的索引,有时查询性能仍然不尽如人意。索引下推(Index Condition Pushdown,ICP)是一项能够进一步优化查询性能的技术。本文将详细讲解索引下推的…...
论文降重技巧:AI工具如何助力论文原创性提升?
论文降重一直是困扰各界毕业生的“拦路虎”,还不容易熬过修改的苦,又要迎来降重的痛。 其实想要给论文降重达标,我有一些独家秘诀。话不多说直接上干货! 1、同义词改写(针对整段整句重复) 这是最靠谱也是…...
el-date-picker的使用,及解决切换type时面板样式错乱问题
这里选择器的类型可以选择日月年和时间范围,根据类型不同,el-date-picker的面板也展示不同,但是会出现el-date-picker错位,或者面板位置和层级等问题。 源代码: <el-selectv-model"dateType"placeholder&…...
Flutter 中的 ToggleButtonsTheme 小部件:全面指南
Flutter 中的 ToggleButtonsTheme 小部件:全面指南 Flutter,作为由 Google 开发的跨平台 UI 框架,为开发者提供了丰富的组件来构建现代化的应用程序。ToggleButtons 是 Material Design 组件库中的一个组件,它允许用户从一组选项…...
新手教程之使用LLaMa-Factory微调LLaMa3
文章目录 为什么要用LLaMa-Factory什么是LLaMa-FactoryLLaMa-Factory环境搭建微调LLaMA3参考博文 为什么要用LLaMa-Factory 如果你尝试过微调大模型,你就会知道,大模型的环境配置是非常繁琐的,需要安装大量的第三方库和依赖,甚至…...
Java函数笔记
1. Statement.executeQuery 和 Statement.executeUpdate 作用: 用于执行SQL查询和更新操作。 问题: 容易导致SQL注入攻击。 解决方法: 使用PreparedStatement进行参数化查询。 // 不安全的做法 Statement stmt connection.createStat…...
Maven实战: 从工程创建自定义archetype
在上一节中(创建自定义archetype)我们手动创建了一个项目模板,经过5步能创建出一个项目模板,如果我有一个现成的项目,想用这个项目作为模板来生成其他项目呢?Maven提供了基于项目生成archetype模板的能力,我们分3步来讲…...
初识JAVA中的包装类,时间复杂度及空间复杂度
目录: 一.包装类 二.时间复杂度 三.空间复杂度 一.包装类: 在Java中,由于基本类型不是继承自Object,为了在泛型代码中可以支持基本类型,Java 给每个基本类型都对应了一个包装类型。 1 基本数据类型和对应的包装类 &am…...
RapidMiner如何利用Hugging Face中的模型实现更有趣的事
RapidMiner Studio最新发布的功能更新,重点是嵌入Hugging Face和Open AI,Hugging face中含有大量的可用模型,包含翻译、总结、文本生成等等强大的模型,Open AI更不必说了,生成界的鼻祖。那么今天主要介绍一下RapidMine…...
Vue3 自定义Hooks函数的封装
1、如何理解vue3中的自定义hooks 在Vue 3中,自定义hooks允许开发者封装和重用逻辑代码。自定义hooks是使用Composition API时创建的函数,这些函数可以包含任意的组合逻辑,并且可以在多个组件之间共享。 自定义hooks通常遵循这样的命名约定&…...
python的DataFrame和Series
Series、DataFrame 创建 pd.Series() pd.DataFrame() # 字典{列名:[值1,值2],} [[]] [()] numpy Pandas的底层的数据结构,就是numpy的数组 ndarray 常用属性 shape (行数,) (行数,列数) values → ndarray index 索引名 siz…...
ARP欺骗的原理与详细步骤
ARP是什么: 我还记得在计算机网络课程当中,学过ARP协议,ARP是地址转换协议,是链路层的协议,是硬件与上层之间的接口,同时对上层提供服务。在局域网中主机与主机之间不能直接通过IP地址进行通信,…...
25、DHCP FTP
DHCP 动态主机配置协议 DHCP定义: 服务器配置好了地址池 192.168.233.10 192.168.233.20 客户端从地址池当中随机获取一个ip地址,ip地址会发生变化,使用服务端提供的ip地址,时间限制,重启之后也会更换。 DHCP优点&a…...
spark学习记录-spark基础概念
背景需求 公司有项目需要将大容量数据进行迁移,经过讨论,采用spark框架进行同步、转换、解析、入库。故此,这里学习spark的一些基本的概念知识。 Apache Spark 是一个开源的大数据处理框架,可以用于高效地处理和分析大规模的数据…...
BGP数据包+工作过程
BGP数据包 基于 TCP的179端口工作;故BGP协议中所有的数据包均需要在tcp 会话建立后; 基于TCP的会话来进行传输及可靠性的保障; 首先通过TCP的三次握手来寻找到邻居; Open 仅负责邻居关系的建立,正常进收发一次即可;携带route-id; Keepli…...
【C语言】详解函数(庖丁解牛版)
文章目录 1. 前言2. 函数的概念3.库函数3.1 标准库和头文件3.2 库函数的使用3.2.1 头文件的包含3.2.2 实践 4. 自定义函数4.1 自定义函数的语法形式4.2 函数的举例 5. 形参和实参5.1 实参5.2 形参5.3 实参和形参的关系 6. return 语句6. 总结 1. 前言 一讲到函数这块ÿ…...
IDEA运行Tomcat出现乱码问题解决汇总
最近正值期末周,有很多同学在写期末Java web作业时,运行tomcat出现乱码问题,经过多次解决与研究,我做了如下整理: 原因: IDEA本身编码与tomcat的编码与Windows编码不同导致,Windows 系统控制台…...
Flask RESTful 示例
目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题: 下面创建一个简单的Flask RESTful API示例。首先,我们需要创建环境,安装必要的依赖,然后…...
边缘计算医疗风险自查APP开发方案
核心目标:在便携设备(智能手表/家用检测仪)部署轻量化疾病预测模型,实现低延迟、隐私安全的实时健康风险评估。 一、技术架构设计 #mermaid-svg-iuNaeeLK2YoFKfao {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg…...
23-Oracle 23 ai 区块链表(Blockchain Table)
小伙伴有没有在金融强合规的领域中遇见,必须要保持数据不可变,管理员都无法修改和留痕的要求。比如医疗的电子病历中,影像检查检验结果不可篡改行的,药品追溯过程中数据只可插入无法删除的特性需求;登录日志、修改日志…...
如何在看板中体现优先级变化
在看板中有效体现优先级变化的关键措施包括:采用颜色或标签标识优先级、设置任务排序规则、使用独立的优先级列或泳道、结合自动化规则同步优先级变化、建立定期的优先级审查流程。其中,设置任务排序规则尤其重要,因为它让看板视觉上直观地体…...
OkHttp 中实现断点续传 demo
在 OkHttp 中实现断点续传主要通过以下步骤完成,核心是利用 HTTP 协议的 Range 请求头指定下载范围: 实现原理 Range 请求头:向服务器请求文件的特定字节范围(如 Range: bytes1024-) 本地文件记录:保存已…...
Springcloud:Eureka 高可用集群搭建实战(服务注册与发现的底层原理与避坑指南)
引言:为什么 Eureka 依然是存量系统的核心? 尽管 Nacos 等新注册中心崛起,但金融、电力等保守行业仍有大量系统运行在 Eureka 上。理解其高可用设计与自我保护机制,是保障分布式系统稳定的必修课。本文将手把手带你搭建生产级 Eur…...
服务器--宝塔命令
一、宝塔面板安装命令 ⚠️ 必须使用 root 用户 或 sudo 权限执行! sudo su - 1. CentOS 系统: yum install -y wget && wget -O install.sh http://download.bt.cn/install/install_6.0.sh && sh install.sh2. Ubuntu / Debian 系统…...
【C++特殊工具与技术】优化内存分配(一):C++中的内存分配
目录 一、C 内存的基本概念 1.1 内存的物理与逻辑结构 1.2 C 程序的内存区域划分 二、栈内存分配 2.1 栈内存的特点 2.2 栈内存分配示例 三、堆内存分配 3.1 new和delete操作符 4.2 内存泄漏与悬空指针问题 4.3 new和delete的重载 四、智能指针…...
【LeetCode】算法详解#6 ---除自身以外数组的乘积
1.题目介绍 给定一个整数数组 nums,返回 数组 answer ,其中 answer[i] 等于 nums 中除 nums[i] 之外其余各元素的乘积 。 题目数据 保证 数组 nums之中任意元素的全部前缀元素和后缀的乘积都在 32 位 整数范围内。 请 不要使用除法,且在 O…...
