快速通关单链表秘籍
1.单链表概念与结构
1.1 概念
链表是一种逻辑结构连续,物理结构不连续的存储结构,数据结构的逻辑顺序是通过链表中的指针链接次序实现。
光看定义有点不好理解,我们举个简单例子!
我们都看过火车吧,我们看到的火车是有一节一节的车厢相连接,这个链接的纽带我们可以抽象的看作指针链接,我们通过车厢链接去找到下一节车厢,在单链表中我们可以通过指针链接去找到下一个节点。当我们需要增加(或减少)节车厢时,可以额外增加(或减少)几节。链表也是如此,这也是链表相对于顺序表的一大优点:可以随意增(减)容。
由此我们可以抽象出单链表的基本结构:
1.2 结点结构
火车的每一节车厢叫车厢,链表的每一节“车厢”叫结点。
链表里面的每一节“车厢”都是独立像内存申请的空间,我们称作“结点”。
根据这幅图,我们plist就是头结点,通过plist里的存放的地址我们可以找到下一结点的位置,要找到下一节点,我们就必须的有它对应的地址,因此节点不仅存放了相应的数据还有下一结点的地址!
所以结点的结构:数据+下一结点的地址。
同理我们也可以去修改对应的地址,去访问不同的结点空间。例如:修改plist的值,plist=0x0012FFA0,再去访问结点访问的就是数据2对应的结点了。
注意:结点都是独立申请的(即需要插入数据时才去申请一块结点的空间),我们需要通过指针变量保存下一结点的地址才能找到下一个结点。
1.3 链表的性质
1. 链表在逻辑结构上是连续的,物理结构是不连续的!
2. 结点是独立的,是从堆上申请的。
3. 从堆上申请下来的结点,是按一定策略分配的,可能申请的空间连续,也可能不连续。
这里有人可能不知道什么是堆区,这里留了一张大概的图片有助于理解:
1.4 链表结点的结构
typedef int SLTDataType;//这里重命名,可以更改数据的类型
typedef struct SListNode
{SLTDataType data;//节点里面的数据struct SListNode* Next;//节点里存放的下一个结点的地址
}SLTNode;
2. 链表的实现
2.1 手动构造一个链表
void test()
{SLTNode SL;SLTNode* node1 = (SLTNode*)malloc(sizeof(SLTNode));SLTNode* node2 = (SLTNode*)malloc(sizeof(SLTNode));SLTNode* node3 = (SLTNode*)malloc(sizeof(SLTNode));SLTNode* node4 = (SLTNode*)malloc(sizeof(SLTNode));node1->data = 1;node2->data = 2;node3->data = 3;node4->data = 4;node1->next = node2;node2->next = node3;node3->next = node4;node4->next = NULL;SLTNode* plist = node1;//头结点
}
2.2 尾插
//头插
void SLPushFront(SLTNode** pphead, SLDataType x)
{assert(pphead);SLTNode* newnode = BuyNode(x);if (*pphead == NULL){*pphead = newnode;}else{newnode->next = *pphead;*pphead = newnode;}
}
2.3 头插
//头插
void SLPushFront(SLTNode** pphead, SLDataType x)
{assert(pphead);SLTNode* newnode = BuyNode(x);if (*pphead == NULL){*pphead = newnode;}else{newnode->next = *pphead;*pphead = newnode;}
}
2.4 尾删
//尾删
void SLPopBack(SLTNode** pphead)
{assert(pphead);SLTNode* pcur = *pphead;SLTNode* prev = NULL;if ((*pphead)->next == NULL){free(*pphead);*pphead = NULL;}else{while (pcur->next){prev = pcur;pcur = pcur->next;}prev->next = NULL;free(pcur);pcur = NULL;}
}
2.5 头删
//头删
void SLPopFront(SLTNode** pphead)
{assert(pphead && *pphead);SLTNode* next = (*pphead)->next;free(*pphead);*pphead = next;
}
2.6 指定位置之前插入数据
//在指定位置之前插⼊数据
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{assert(pphead);SLTNode* newnode = BuyNode(x);SLTNode* prev = *pphead;if (*pphead == pos)SLPushFront(pphead, x);else{while (prev->next != pos){prev = prev->next;}prev->next = newnode;newnode->next = pos;}
}
2.7 在指定位置之后插入数据
//在指定位置之后插⼊数据
void SLTInsertAfter(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{assert(pphead);SLTNode* newnode = BuyNode(x);newnode->next = pos->next;pos->next = newnode;
}
2.8 删除指定位置之前的数据
//删除指定位置之前的数据
void SLTErase(SLTNode** pphead, SLTNode* pos)
{assert(pphead && pos);SLTNode* prev = *pphead;//当只有一个节点的时候if (*pphead == pos)SLPopFront(pphead);else{while (prev->next != pos){prev = prev->next;}prev->next = pos->next;free(pos);pos = NULL;}
}
2.9 删除pos之后的结点
//删除pos之后的结点
void SLTEraseAfter(SLTNode* pos)
{assert(pos);SLTNode* next = pos->next;pos->next = pos->next->next;free(next);next = NULL;
}
2.10 销毁链表
//销毁链表
void SLTDestroy(SLTNode** pphead)
{assert(pphead);SLTNode* pcur = *pphead;SLTNode* next = *pphead;while (pcur){next = pcur->next;free(pcur);pcur = next;}*pphead = NULL;
}
3. 单链表实现代码
SList.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 SLPushBack(SLTNode** pphead,SLTDataType x);
//打印链表
void SLPrint(SLTNode* phead);
//头插
void SLPushFront(SLTNode** pphead, SLTDataType x);
//尾删
void SLPopBack(SLTNode** pphead);
//头删
void SLPopFront(SLTNode** pphead);
//在指定位置之前插⼊数据
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x);
//查找
SLTNode* SLTFind(SLTNode* phead, SLTDataType x);
//在指定位置之后插⼊数据
void SLTInsertAfter(SLTNode** pphead, SLTNode* pos, SLTDataType x);
//删除指定位置之前的数据
void SLTErase(SLTNode** pphead, SLTNode* pos);
//删除pos之后的结点
void SLTEraseAfter(SLTNode* pos);
//销毁链表
void SLTDestroy(SLTNode** pphead);
SList.c文件
#include "SList.h"SLTNode* BuyNode(SLTDataType x)
{SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));if (newnode == NULL){perror("malloc fail!");exit(1);}newnode->data = x;newnode->next = NULL;
}
//打印链表
void SLPrint(SLTNode* phead)
{SLTNode* pcur = phead;while (pcur){printf("%d -> ", pcur->data);pcur = pcur->next;}printf("NULL\n");
}
//尾插
void SLPushBack(SLTNode** pphead, SLTDataType x)
{SLTNode* newnode = BuyNode(x);//这里需要讨论两种情况:空链表和非空链表SLTNode* pcur = *pphead;//空链表if(*pphead==NULL){*pphead = newnode;}else//非空链表{while (pcur->next){pcur = pcur->next;}pcur->next=newnode;}
}
//头插
void SLPushFront(SLTNode** pphead, SLTDataType x)
{assert(pphead);SLTNode* newnode = BuyNode(x);if (*pphead == NULL){*pphead = newnode;}else{newnode->next = *pphead;*pphead = newnode;}
}
//尾删
void SLPopBack(SLTNode** pphead)
{assert(pphead);SLTNode* pcur = *pphead;SLTNode* prev = NULL;if ((*pphead)->next == NULL){free(*pphead);*pphead = NULL;}else{while (pcur->next){prev = pcur;pcur = pcur->next;}prev->next = NULL;free(pcur);pcur = NULL;}
}
//头删
void SLPopFront(SLTNode** pphead)
{assert(pphead && *pphead);SLTNode* next = (*pphead)->next;free(*pphead);*pphead = next;
}
//查找
SLTNode* SLTFind(SLTNode* phead, SLTDataType x)
{assert(phead);SLTNode* pcur = phead;while (pcur){if (pcur->data == x){return pcur;}pcur = pcur->next;}return NULL;
}
//在指定位置之前插⼊数据
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{assert(pphead);SLTNode* newnode = BuyNode(x);SLTNode* prev = *pphead;//当只有一个结点的时候if (*pphead == pos)SLPushFront(pphead, x);else{while (prev->next != pos){prev = prev->next;}prev->next = newnode;newnode->next = pos;}
}
//在指定位置之后插⼊数据
void SLTInsertAfter(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{assert(pphead && pos);SLTNode* newnode = BuyNode(x);newnode->next = pos->next;pos->next = newnode;
}
//删除指定位置之前的数据
void SLTErase(SLTNode** pphead, SLTNode* pos)
{assert(pphead && pos);SLTNode* prev = *pphead;//当只有一个节点的时候if (*pphead == pos)SLPopFront(pphead);else{while (prev->next != pos){prev = prev->next;}prev->next = pos->next;free(pos);pos = NULL;}
}
//删除pos之后的结点
void SLTEraseAfter(SLTNode* pos)
{assert(pos);SLTNode* next = pos->next;pos->next = pos->next->next;free(next);next = NULL;
}
//销毁链表
void SLTDestroy(SLTNode** pphead)
{assert(pphead);SLTNode* pcur = *pphead;SLTNode* next = *pphead;while (pcur){next = pcur->next;free(pcur);pcur = next;}*pphead = NULL;
}
test.c 文件
#include "SList.h"//void test()
//{
// SLTNode sl;
// SLTNode* node1 = (SLTNode*)malloc(sizeof(SLTNode));
// SLTNode* node2 = (SLTNode*)malloc(sizeof(SLTNode));
// SLTNode* node3 = (SLTNode*)malloc(sizeof(SLTNode));
// SLTNode* node4 = (SLTNode*)malloc(sizeof(SLTNode));
// node1->data = 1;
// node2->data = 2;
// node3->data = 3;
// node4->data = 4;
// node1->next = node2;
// node2->next = node3;
// node3->next = node4;
// node4->next = NULL;
//}
void test()
{SLTNode SL;SLTNode* plist = NULL;SLPushBack(&plist, 1);SLPushBack(&plist, 2);SLPushBack(&plist, 3);SLPushBack(&plist, 4);SLPrint(plist);//SLPushFront(&plist, 1);//SLPushFront(&plist, 2);//SLPushFront(&plist, 3);//SLPushFront(&plist, 4);//SLPopBack(&plist);//SLPopBack(&plist);//SLPopBack(&plist);//SLPopBack(&plist);//SLPopFront(&plist);//SLPrint(plist);//SLPopFront(&plist);//SLPrint(plist);//SLPopFront(&plist);//SLPrint(plist);//SLPopFront(&plist);//SLPrint(plist);SLTNode* find = SLTFind(plist, 3);//if (find)// printf("找到了\n");//else// printf("未找到\n");//SLTInsert(&plist, find, 6);//SLPrint(plist);//SLTInsertAfter(&plist, find, 5);//SLPrint(plist);//SLTErase(&plist, find);//SLPrint(plist);SLTEraseAfter(find);SLPrint(plist);
}
int main()
{test();return 0;
}
相关文章:

快速通关单链表秘籍
1.单链表概念与结构 1.1 概念 链表是一种逻辑结构连续,物理结构不连续的存储结构,数据结构的逻辑顺序是通过链表中的指针链接次序实现。 光看定义有点不好理解,我们举个简单例子! 我们都看过火车吧,我们看到的火车…...

springboot+vue实现在线书店(图书商城)系统
今天教大家如何设计一个图书商城 , 基于目前主流的技术:前端vue,后端springboot。 同时还带来的项目的部署教程。 视频演示 在线书城 图片演示 一. 系统概述 商城是一款比较庞大的系统,需要有商品中心,库存中心,订单…...
C++二项式定理:原理、实现与应用
背景 鉴于复习,问了问清言二项式定理的应用…只好多找些资源…肝要死了… 一、引言 二项式定理是数学中一个基本定理,主要用于展开二项式的幂次。在C编程中,理解并实现二项式定理及其拓展具有重要意义,可以解决组合数学、概率论…...
使用GmSSL v3.1.1实现SM2证书认证
1、首先使用gmssl命令生成根证书、客户端公私钥,然后使用根证书签发客户端证书; 2、然后编写代码完成认证功能,使用根证书验证客户端证书是否由自己签发,然后使用客户端证书验证客户端私钥对随机数的签名是否正确。 第一部分生成根…...
远程实时控制安卓模拟器技术scrcpy
先运行模拟器 ~/Library/Android/sdk/emulator/emulator -avd Medium_Phone_API_25 再检查adb device /Users/xmkjsoft/Downloads/scrcpy-macos-x86_64-v3.2/adb devices 再开始实时获取模拟器画面 /Users/xmkjsoft/Downloads/scrcpy-macos-x86_64-v3.2/scrcpy --video-cod…...

Spring AI(6)——向量存储
向量数据库是一种特殊类型的数据库,在 AI 应用中发挥着至关重要的作用。 在向量数据库中,查询与传统关系型数据库不同。它们执行的是相似性搜索,而非精确匹配。当给定一个向量作为查询时,向量数据库会返回与该查询向量“相似”的…...
Spring Data Elasticsearch 中 ElasticsearchOperations 构建查询条件的详解
Spring Data Elasticsearch 中 ElasticsearchOperations 构建查询条件的详解 前言一、引入依赖二、配置 Elasticsearch三、创建模型类(Entity)四、使用 ElasticsearchOperations 进行 CRUD 操作1. 保存数据(Create)2. 获取数据&am…...
react-router基本写法
1. 创建项目并安装所有依赖 npx create-react-app react-router-pro npm i 2. 安装所有的 react router 包 npm i react-router-dom 3. 启动项目 npm run start router/index.js // 创建路由实例 绑定path elementimport Layout from "/pages/Layout"; import…...

【Matlab】最新版2025a发布,深色模式、Copilot编程助手上线!
文章目录 一、软件安装1.1 系统配置要求1.2 安装 二、新版功能探索2.1 界面图标和深色主题2.2 MATLAB Copilot AI助手2.3 绘图区升级2.4 simulink2.5 更多 延迟一个月,终于发布了🤭。 一、软件安装 1.1 系统配置要求 现在的电脑都没问题,老…...
智能语音助手的未来:从交互到融合
摘要 随着人工智能技术的不断进步,智能语音助手已经成为我们生活中不可或缺的一部分。从简单的语音指令到复杂的多模态交互,语音助手正在经历一场深刻的变革。本文将探讨智能语音助手的发展历程、当前的技术瓶颈以及未来的发展方向,特别是其在…...

uniapp,小程序中实现文本“展开/收起“功能的最佳实践
文章目录 示例需求分析实现思路代码实现1. HTML结构2. 数据管理3. 展开/收起逻辑4. CSS样式 优化技巧1. 性能优化2. 防止事件冒泡3. 列表更新处理 实际效果总结 在移动端应用开发中,文本内容的"展开/收起"功能是提升用户体验的常见设计。当列表项中包含大…...

思维链框架:LLMChain,OpenAI,PromptTemplate
什么是思维链,怎么实现 目录 什么是思维链,怎么实现思维链(Chain of Thought)在代码中的实现方式1. 手动构建思维链提示2. 少样本思维链提示3. 自动思维链生成4. 思维链与工具使用结合5. 使用现有思维链框架:LLMChain,OpenAI,PromptTemplate思维链实现的关键要点思维链(C…...
HOT100 (哈希双指针)
哈希 1.两数之和(unordered_map) 给定一个整数数组 nums 和一个整数目标值 target,返回满足条件的数组下标 思路:用umap,一边遍历,一边装; class Solution {public:vector<int> twoSum(vector<int>& nums, int target) {unordered_map<int,int> u…...

使用 QGIS 插件 OpenTopography DEM Downloader 下载高程数据(申请key教程)
使用 QGIS 插件 OpenTopography DEM Downloader 下载高程数据 目录 使用 QGIS 插件 OpenTopography DEM Downloader 下载高程数据📌 简介🛠 插件安装方法🌍 下载 DEM 数据步骤🔑 注册 OpenTopography 账号(如使用 Cope…...

计算机组成与体系结构:替换策略(MRU LRU PLRU LFU)
目录 🎲 MRU(最近最常使用) 🪜 操作流程: 🎲 LRU(最近最少使用) 🪜 操作流程: 示例 🔍 Age Bits(年龄位) 核心思想…...

websocket入门详解
入门websocket的基础应该掌握一下问题: 1、什么是握手? 2、什么是websocket? 3、websocket和http的区别,应用场景 4、html前端简单代码演示 5、springboot整合websocket使用 6、使用vueelementui打造简单聊天室 7、使用web…...
《数字藏品社交化破局:React Native与Flutter的创新实践指南》
NFT,这种非同质化代币,赋予了数字资产独一无二的身份标识,从数字艺术作品到限量版虚拟物品,每一件NFT数字藏品都承载着独特的价值与意义。当React Native和Flutter这两大跨平台开发框架遇上NFT数字藏品,一场技术与创意…...

(6)python开发经验
文章目录 1 QListWidget样式显示异常2 模块编码错误3 qtcreator开发pyqt编码错误 更多精彩内容👉内容导航 👈👉Qt开发 👈👉python开发 👈 1 QListWidget样式显示异常 main.py import sys from PySide6.QtWi…...

HPC软件使用之ANSYS Fluent
目录 一、软件介绍 二、脚本编写 2.1 jou文件 2.2 slurm脚本文件 三、作业提交及查看 四、案例演示 4.1 网格模型 4.2 jou脚本 4.3 slurm脚本 4.4 计算 4.5 结果查看 从本文开始,我们将介绍如何在超级计算机上使用科学计算、工程仿真计算软件开展计算&am…...

YOLO11解决方案之距离计算探索
概述 Ultralytics提供了一系列的解决方案,利用YOLO11解决现实世界的问题,包括物体计数、模糊处理、热力图、安防系统、速度估计、物体追踪等多个方面的应用。 测量两个物体之间的间距被称为特定空间内的距离计算,YOLO11使用两个边界框的中心…...

论文学习_Precise and Accurate Patch Presence Test for Binaries
摘要:打补丁是应对软件漏洞的主要手段,及时将补丁应用到所有受影响的软件上至关重要,然而这一点在实际中常常难以做到,研究背景。因此,准确检测安全补丁是否已被集成进软件发行版本的能力,对于防御者和攻击…...

Ascend的aclgraph(九)AclConcreteGraph:e2e执行aclgraph
1回顾 前面的几章内容探讨了aclgraph运行过程中的涉及到的关键模块和技术。本章节将前面涉及到的模块串联起来,对aclgraph形成一个端到端的了解。 先给出端到端运行的代码,如下: import torch import torch_npu import torchair import log…...
JSX语法介绍
文章目录 JSX介绍JSX的引入JSX的全称babel转换工具 JSX的基本语法创建组件的第一种方式创建组件父组件传值给子组件 class 关键字的介绍class的基本用法:使用class创建对象使用 class 实现 JS 中的继承 创建组件的第二种方式:使用 class 关键字父组件传值…...
增强 HTNN 服务网格功能:基于 Istio 的BasicAuth 与 ACL 插件开发实战
目录 1.引言 什么是HTNN? 为什么开发 BasicAuth 和 ACL 插件? 2.技术背景 技术栈概览 Istio 与服务网格简述 HTNN 框架与插件机制概览 3.插件开发详解:BasicAuth 与 ACL 3.1 BasicAuth插件 功能点 实现细节 3.2 ACL插件 功能点 …...

c++从入门到精通(四)--动态内存,模板与泛型编程
文章目录 动态内存直接管理内存Shared_ptr类Unique_ptrWeak_ptr动态数组allocator类文本查询程序 模板与泛型编程定义模板函数模板类模板模板参数成员模板控制实例化 模板实参推断重载与模板可变参数模板模板特例化 动态内存 c中动态内存的管理是通过new和delete运算符来实现的…...
C盘清理秘籍:快速提升系统性能
C盘清理的重要性 C盘作为系统盘,存储着操作系统和关键程序文件。随着使用时间的增加,C盘空间会逐渐被占用,导致系统运行缓慢、程序启动延迟等问题。定期清理C盘可以有效提升系统性能,延长硬盘寿命。 清理临时文件 Windows系统在…...
从 Vue3 回望 Vue2:组件设计升级——Options API vs Composition API
文章目录 从 Vue3 回望 Vue2:组件设计升级——Options API vs Composition API1、组件范式:框架设计思想的投影2、Vue2:Options API 的结构与局限结构清晰:新手友好、职责分明核心痛点:逻辑分散,难以聚合复…...

寻找两个正序数组的中位数 - 困难
************* Python topic: 4. 寻找两个正序数组的中位数 - 力扣(LeetCode) ************* Give the topic an inspection. Do the old topic will give you some new sparks. Before that, I do some really good craetive things about my logo. …...

国产密码新时代!华测国密 SSL 证书解锁安全新高度
在数字安全被提升到国家战略高度的今天,国产密码算法成为筑牢网络安全防线的关键力量。华测国密SSL证书凭借其强大性能与贴心服务,为企业网络安全保驾护航,成为符合国家安全要求的不二之选! 智能兼容,告别浏览器适配…...

【金仓数据库征文】从云计算到区块链:金仓数据库的颠覆性创新之路
目录 一、引言 二、金仓数据库概述 2.1 金仓数据库的背景 2.2 核心技术特点 2.3 行业应用案例 三、金仓数据库的产品优化提案 3.1 性能优化 3.1.1 查询优化 3.1.2 索引优化 3.1.3 缓存优化 3.2 可扩展性优化 3.2.1 水平扩展与分区设计 3.2.2 负载均衡与读写分离 …...