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

数据结构基础详解(C语言):单链表_定义_初始化_插入_删除_查找_建立操作_纯c语言代码注释讲解

单链表理论知识详解

文章目录

  • 单链表理论知识详解
  • 1.单链表的定义
  • 2.单链表的初始化
  • 3.单链表的插入和删除
    • 3.1 单链表的插入
      • 3.1.1 按位序插入
      • 3.1.2 在指定结点的前后插入
        • 一.后插操作
        • 二.前插操作
  • 4.单链表的删除
    • 4.1 按位序删除
      • 4.2 指定结点的删除
  • 5.单链表的查找
    • 5.1 按位序查找
    • 5.2 按值查找
    • 补充一个:求表的长度
  • 6. 单链表的建立(带头结点的建立)
    • 6.1 尾插法建立单链表
    • 6.2 头插法建立单链表
  • 本文完整代码

1.单链表的定义

线性表的链式存储.
优点:不要求大片连续空间,改变容量方便
缺点:不可随机存取,要耗费一定空间存放指针

typedef struct LNode{int data;struct LNode *next;
}LNode, *LinkList;

typedef 取别名
将struct LNode 取别名为别的,方便书写
比如我们要声明一个该结构体的时候
由原先的struct LNode a; 可以直接写为LNode a;
由原先的struct LNode *p; 可以直接写为LinkList a;

2.单链表的初始化

带头结点的初始化,头结点就是多一个结点,指向第一个存放数据的结点.
不带头结点,会使处理数据的逻辑更复杂,对空表和非空表需要不同的代码逻辑.
单链表的初始化本质:为头结点分配一个堆空间,将头结点指针域置为空,加上判断内存是否能分配

#include <stdio.h>
#include <stdlib.h>
//这是带有头结点的单链表初始化
void InitList() {LinkList L;//定义头指针变量 L=(LNode*)malloc(sizeof(LNode));//头指针指向分配的头结点内存空间 L->next=NULL;return true;
}
int main()
{InitList( );
}

3.单链表的插入和删除

3.1 单链表的插入

3.1.1 按位序插入

按位序插入,比如说有5个元素,插入到第三个元素的位置
注意在有头结点时,位序5,意味着是结点6
假如我们要插入的位序是3,意味着我们要寻找的是位序2,也就是结点3,当j=i-1时我们跳出循环,先操作,后j++,j代表当前结点值从0开始,也就是我们在j=3的时候应该跳出循环,所以先操作,后j++,就是j<i-1,j=i的时候就跳出循环

传入什么? 表+插入位置+插入的值
分为几步?
首先是非法操作的判断,是否合法.
第二步是,寻找要插入的位置,插入第几个位置,就找到他前一个位置即i-1,让此时的指针p落在该点处,即我们可以操作他的next域
第三步,先判断吐过p指向空,插入操作不合法,若合法,分配堆空间给一个新的结点s,s的数据域是传入值e,s的指针域指向原先的i(i-1的next域,即p当前的next域),然后将i-1的next域指向新的i

核心思想:先连后断

bool ListInsert(LinkList L,int i,int e)
{if(i<1)return false;LNode *p=L;  //为什么需要p指针,因为我们不能动表头指针int j=0;    //用来判断当前指针在第几个结点处,j=0,意思是在头结点处while(p!=NULL&&j<i-1) //P不能为空,为空咋插入啊,操作不合法,i=j的时候跳出循环{p=p->next; j++; }    //通过这个循环,我们就能找到A的指向B的next域,在他俩中间插入Cif(p==NULL)return false;  //上个循环判断它是否为空,为空不执行,为空的具体操作写在了这,为空就结束LNode *s=(LNode *)malloc(sizeof(LNode));s->data=e;s->next=p->next;p->next=s;return true; 
}

3.1.2 在指定结点的前后插入

一.后插操作

分两步
判断操作是否合法(p指针是否为空+s是否能分配)
插入元素操作

InsertNextNode(LNode *p,int e)
{if(p==NULL)return false;LNode *s=(LNode *)malloc(sizeof(LNode));	if(s==NULL)return false;s->data=e;s->next=p->next;p->next=s;return true; 
}
二.前插操作

前插操作我们这里不讨论从前遍历一遍,到最后的那种方法
而是考虑,用后插法再交换他们的数据域这种形式可以将时间复杂度降低到o(1)

bool InsertPriorNode(LNode *p,int e)
{if(p==NULL)return false;LNode *s=(LNode *)malloc(sizeof(LNode));	if(s==NULL)return false;s->next=p->next;p->next=s;s->data=p->data;p->data=e;return true; 
}

4.单链表的删除

4.1 按位序删除

第一步与之前的查找的相同的,现查找位序-1的点
然后再进行删除操作

bool ListDelete(LinkList L,int i,int &e)
{if(i<1)return false;LNode *p=L;  //为什么需要p指针,因为我们不能动L头指针int j=0;  //用来判断当前指针在第几个结点处,j=0,意思是在头结点处while(p!=NULL&&j<i-1) //P不能为空,为空咋插入啊,操作不合法,i=j的时候跳出循环{p=p->next; j++; } if(p==NULL) return false;if(p->next==NULL) return false;LNode *q=p->next;  //方便操作搞出了一个q,直接用p也行,就是写起来不直观e=q->data;p->next=q->next;free(q);return true; 
}

4.2 指定结点的删除

指定删除结点p,我们思考,给你结点p删除它,需要找到前一个结点,但是那样做太麻烦了,不如交换指定结点和后一个结点的数据域,再删除新的后继结点

bool DeleteNode(LNode *p)
{if(p==NULL)return false;LNode *q=p->next;p->data=q->data;p->next=q->next;free(q);return true;
}

5.单链表的查找

5.1 按位序查找

返回值是位序结点的指针

LNode * GetElem(LinkList L,int i)
{if(i<0)return NULL;LNode *p=L;int j=0;while(p!=NULL&&j<i){p=p->next;j++;}return p;} 

5.2 按值查找

LNode * LocateElem(LinkList L,int e)
{LNode *p=L->next; //从第一个结点处开始查值while(p!=NULL&&p->data!=e){p=p->next;}return p; 
}

补充一个:求表的长度

int Length(LinkList L){int len=0;  //不包括头结点 LNode *p=L;while(p->next!=NULL){p=p->next;len++;}return len;
}

6. 单链表的建立(带头结点的建立)

单链表的建立包括了头结点的建立(初始化)

6.1 尾插法建立单链表

- 在尾插法中,LNode *s,*r=L;这个写法,其实是为了简化代码,实际上*s不需要赋值,
- 因为在接下来的代码中会给结点s分配堆空间,结点s的位置就会变成随机的,
- 实际上,我们只需要让r=L就行,声明一个s即可
  • 声明输入值x,分配头结点,声明s和r指针
  • 循环分配s结点再把它加入链表,再循环的输入x值
  • 链表尾指针置空
LinkList List_Tailnsert(LinkList &L)
{int x;L=(LinkList)malloc(sizeof(LNode)); //初始化头结点LNode *s,*r=L;                     //定义上表尾指针和待随机分配的结点指针scanf("%d",&x);while(x!=9999) //输出9999表示结束{s=(LNode *)malloc(sizeof(LNode));s->data=x;r->next=s;r=s;scanf("%d",&x);}r->next=NULL;return L; 
}

6.2 头插法建立单链表

  • 头插法相比于尾插法,我们要把头指针置空,因为分配的头指针很可能指向神秘的空间有脏数据
LinkList List_Headlnsert(LinkList L)
{int x;L=(LinkList)malloc(sizeof(LNode));L->next=NULL; //初始链表头指针指向NULLLNode *s;scanf("%d",&x);while(x!=9999) //输出9999表示结束{s=(LNode *)malloc(sizeof(LNode));s->data=x;s->next=L->next;L->next=s;scanf("%d",&x);}return L; 
}

本文完整代码

#include <stdio.h>
#include <stdlib.h>
typedef struct LNode{int data;struct LNode *next;
}LNode ,*LinkList;void InitList() {LinkList L;//定义头指针变量 L=(LNode*)malloc(sizeof(LNode));//头指针指向分配的头结点内存空间 L->next=NULL;return true;
}
bool ListInsert(LinkList L,int i,int e)
{if(i<1)return false;LNode *p=L;  //为什么需要p指针,因为我们不能动L头指针int j=0;  //用来判断当前指针在第几个结点处,j=0,意思是在头结点处while(p!=NULL&&j<i-1) //P不能为空,为空咋插入啊,操作不合法,i=j的时候跳出循环{p=p->next; j++; } if(p==NULL)return false;LNode *s=(LNode *)malloc(sizeof(LNode));s->data=e;s->next=p->next;p->next=s;return true; 
}InsertNextNode(LNode *p,int e)
{if(p==NULL)return false;LNode *s=(LNode *)malloc(sizeof(LNode));	if(s==NULL)return false;s->data=e;s->next=p->next;p->next=s;return true; 
}
bool InsertPriorNode(LNode *p,int e)
{if(p==NULL)return false;LNode *s=(LNode *)malloc(sizeof(LNode));	if(s==NULL)return false;s->next=p->next;p->next=s;s->data=p->data;p->data=e;return true; 
}bool ListDelete(LinkList L,int i,int &e)
{if(i<1)return false;LNode *p=L;  //为什么需要p指针,因为我们不能动L头指针int j=0;  //用来判断当前指针在第几个结点处,j=0,意思是在头结点处while(p!=NULL&&j<i-1) //P不能为空,为空咋插入啊,操作不合法,i=j的时候跳出循环{p=p->next; j++; } if(p==NULL) return false;if(p->next==NULL) return false;LNode *q=p->next;  //方便操作搞出了一个q,直接用p也行,就是写起来不直观e=q->data;p->next=q->next;free(q);return true; 
}bool DeleteNode(LNode *p)
{if(p==NULL)return false;LNode *q=p->next;p->data=q->data;p->next=q->next;free(q);return true;
}LNode * GetElem(LinkList L,int i)
{if(i<0)return NULL;LNode *p=L;int j=0;while(p!=NULL&&j<i){p=p->next;j++;}return p;
} 
LNode * LocateElem(LinkList L,int e)
{LNode *p=L->next; //从第一个结点处开始查值while(p!=NULL&&p->data!=e){p=p->next;}return p; 
}int Length(LinkList L){int len=0;  //不包括头结点 LNode *p=L;while(p->next!=NULL){p=p->next;len++;}return len;
}
LinkList List_Tailnsert(LinkList L)
{int x;L=(LinkList)malloc(sizeof(LNode));LNode *s,*r=L;scanf("%d",&x);while(x!=9999) //输出9999表示结束{s=(LNode *)malloc(sizeof(LNode));s->data=x;r->next=s;r=s;scanf("%d",&x);}r->next=NULL;return L; 
}LinkList List_Headlnsert(LinkList L)
{int x;L=(LinkList)malloc(sizeof(LNode));LNode *s;scanf("%d",&x);while(x!=9999) //输出9999表示结束{s=(LNode *)malloc(sizeof(LNode));s->data=x;s->next=L->next;L->next=s;scanf("%d",&x);}return L; 
}int main()
{InitList();int e=-1;
}

相关文章:

数据结构基础详解(C语言):单链表_定义_初始化_插入_删除_查找_建立操作_纯c语言代码注释讲解

单链表理论知识详解 文章目录 单链表理论知识详解1.单链表的定义2.单链表的初始化3.单链表的插入和删除3.1 单链表的插入3.1.1 按位序插入3.1.2 在指定结点的前后插入一.后插操作二.前插操作 4.单链表的删除4.1 按位序删除4.2 指定结点的删除 5.单链表的查找5.1 按位序查找5.2 …...

【智能时代的创新工具】LangChain快速入门指南:轻松掌握语言模型的集成与运用

一、LangChain&#xff1a;连接语言模型与现实世界的桥梁 1.1 LangChain的定义与重要性 LangChain是一个开源的Python库&#xff0c;它旨在为开发人员提供一种简便的方式来集成和运用语言模型。它不仅仅是一个简单的API调用工具&#xff0c;而是一个具有丰富功能的框架&#x…...

文献阅读:细胞分辨率全脑图谱的交互式框架

文献介绍 文献题目&#xff1a; An interactive framework for whole-brain maps at cellular resolution 研究团队&#xff1a; Daniel Frth&#xff08;瑞典卡罗林斯卡学院&#xff09;、Konstantinos Meletis&#xff08;瑞典卡罗林斯卡学院&#xff09; 发表时间&#xff…...

YAML基础语言深度解析

引言 YAML&#xff08;YAML Aint Markup Language&#xff0c;即YAML不是一种标记语言&#xff09;是一种直观、易于阅读的数据序列化格式&#xff0c;常用于配置文件、数据交换和程序间的通信。其设计目标是易于人类阅读和编写&#xff0c;同时也便于机器解析和生成。在本文中…...

xcode使用

1. 界面 1.1. Build Settings,Build Phases和Build Rules三个设置项 Build Settings(编译设置): 每个选项由标题(Title)和定义(Definition)组成。这里主要定义了Xcode在编译项目时的一些具体配置 Build Phases(编译资源):用于指定编译过程中项目所链接的原文件,依赖对象,库…...

OV2640引脚的定义(OV2640 FPC模组规格书(接口线序))

OV2640是一款由Omni Vision公司生产的1/4寸CMOS UXGA&#xff08;1632x1222&#xff09;图像传感器。这款传感器以其小巧的体积、低工作电压和强大的功能而著称&#xff0c;它集成了单片UXGA摄像头和影像处理器&#xff0c;能够通过SCCB总线控制输出各种分辨率的8/10位影像数据…...

CTFSHOW 萌新 web10 解题思路和方法(passthru执行命令)

点击题目链接&#xff0c;分析页面代码。发现代码中过滤了system、exec 函数&#xff0c;这意味着我们不能通过system(cmd命令)、exec&#xff08;cmd命令&#xff09;的方式运行命令。 在命令执行中&#xff0c;常用的命令执行函数有&#xff1a; system(cmd_code);exec(cmd_…...

深入Java数据库连接和JDBC

引言 Java数据库连接(JDBC)是Java语言中用于执行SQL语句的标准API。通过JDBC,开发者可以方便地与关系型数据库进行交互。然而,直接使用JDBC API面临着数据库连接管理复杂、性能瓶颈等问题。数据库连接池作为一种解决方案,可以有效地管理数据库连接,提高应用程序的性能。…...

灰狼优化算法(GWO)与长短期记忆网络(LSTM)结合的预测模型(GWO-LSTM)及其Python和MATLAB实现

#### 一、背景 在现代数据科学和人工智能领域&#xff0c;预测模型的准确性和效率是研究者和工程师不断追求的目标&#xff0c;尤其是在时间序列预测、金融市场分析、气象预测等领域。长短期记忆&#xff08;LSTM&#xff09;网络是一种解决传统递归神经网络&#xff08;RNN&a…...

电路板热仿真覆铜率,功率,结温,热阻率信息计算获取方法总结

🏡《电子元器件学习目录》 目录 1,概述2,覆铜率3,功率4,器件尺寸5,结温6,热阻1,概述 电路板热仿真操作是一个复杂且细致的过程,旨在评估和优化电路板内部的热分布及温度变化,以确保电子元件的可靠性和性能。本文简述在进行电路板的热仿真时,元器件热信息的计算方法…...

C#中多线程编程中的同步、异步、串行、并行及并发及死锁

在C#中&#xff0c;多线程编程是一个强大的功能&#xff0c;它允许程序同时执行多个任务。然而&#xff0c;这也带来了复杂性&#xff0c;特别是在处理同步、异步、串行、并行、并发以及死锁等问题时。下面我将详细解释这些概念&#xff0c;并给出一些C#中的示例和注意事项。 …...

【Lampiao靶场渗透】

文章目录 一、IP地址获取 二、信息收集 三、破解SSH密码 四、漏洞利用 五、提权 一、IP地址获取 netdiscover -i eth0 Arp-scan -l Nmap -sP 192.168.78.0/24 靶机地址&#xff1a;192.168.78.177 Kali地址&#xff1a;192.168.78.128 二、信息收集 nmap -sV -p- 192.…...

使用WebSocket实现log日志流的实时展示-从轮询到通知

场景介绍 最近开发一个系统&#xff0c;其中一个模块需要展示实时的执行过程&#xff0c;过程日志可能比较多。以前的方案都是前端定时轮询&#xff0c;比如每秒查一次后端接口&#xff0c;将拉取回来的日志重新展示。轮询方案简单容易实现&#xff0c;但是比较消耗资源&#…...

UE5 从零开始制作跟随的大鹅

文章目录 二、绑定骨骼三、创建 ControlRig四、创建动画五、创建动画蓝图六、自动寻路七、生成 goose八、碰撞 和 Physics Asset缺点 # 一、下载模型 首先我们需要下载一个静态网格体&#xff0c;这里我们可以从 Sketchfab 中下载&#xff1a;Goose Low Poly - Download Free …...

O’Reilly

--江上往来人&#xff0c;但爱鲈鱼美。 --君看一叶舟&#xff0c;出没风波里。 OReilly OReilly出版社出版的技术类图书 俗称动物系列 应该是每个技术人员的必备手册。 OReilly动物系列&#xff08;中译本&#xff09; 简介" 动物系列作为 OReilly 书籍的典型代表被普遍…...

优盘驱动器未格式化:数据拯救行动指南

优盘困境&#xff1a;驱动器未格式化的挑战 在日常的数据存储与传输中&#xff0c;优盘以其便携性和高容量成为了我们不可或缺的伙伴。然而&#xff0c;当您尝试访问优盘时&#xff0c;突然弹出的“驱动器未被格式化”提示却如同晴天霹雳&#xff0c;让人措手不及。这一状况不…...

4.Handler mappings

处理程序映射 简介 在早期版本的 Spring 中&#xff0c;用户需要在 Web 应用程序上下文中定义一个或多个 HandlerMapping bean 以将传入的 Web 请求映射到适当的处理程序。随着注解控制器的引入&#xff0c;通常不再需要这样做&#xff0c;因为 RequestMappingHandlerMapping…...

《学会 SpringMVC 系列 · 消息转换器 MessageConverters》

&#x1f4e2; 大家好&#xff0c;我是 【战神刘玉栋】&#xff0c;有10多年的研发经验&#xff0c;致力于前后端技术栈的知识沉淀和传播。 &#x1f497; &#x1f33b; CSDN入驻不久&#xff0c;希望大家多多支持&#xff0c;后续会继续提升文章质量&#xff0c;绝不滥竽充数…...

深度学习项目 -7-使用 Python 的手写数字识别

一、前言 该文章仅作为个人学习使用 二、正文 项目源代码&#xff1a;深度学习项目 - 使用 Python 进行手写数字识别 - DataFlair (data-flair.training) 数据集&#xff1a;​​​​​​​https://drive.google.com/open?id1hJiOlxctFH3uL2yTqXU_1f6c0zLr8V_K Python 深…...

MySQL —— 库,数据类型 与 表

库与基础操作 1.1 查看数据库 使用 show databases; 可以查看当前 MySQL 目前有多少个数据库 5 rows 表示有 5 行&#xff0c;这里是表示的是有效的数据&#xff0c;不包括 第一行的指引 set 表示结果集合 0.01 sec 表示这个 sql 语句一共运行了0.01 秒&#xff0c;一般情况…...

服务器硬防的应用场景都有哪些?

服务器硬防是指一种通过硬件设备层面的安全措施来防御服务器系统受到网络攻击的方式&#xff0c;避免服务器受到各种恶意攻击和网络威胁&#xff0c;那么&#xff0c;服务器硬防通常都会应用在哪些场景当中呢&#xff1f; 硬防服务器中一般会配备入侵检测系统和预防系统&#x…...

学校招生小程序源码介绍

基于ThinkPHPFastAdminUniApp开发的学校招生小程序源码&#xff0c;专为学校招生场景量身打造&#xff0c;功能实用且操作便捷。 从技术架构来看&#xff0c;ThinkPHP提供稳定可靠的后台服务&#xff0c;FastAdmin加速开发流程&#xff0c;UniApp则保障小程序在多端有良好的兼…...

三体问题详解

从物理学角度&#xff0c;三体问题之所以不稳定&#xff0c;是因为三个天体在万有引力作用下相互作用&#xff0c;形成一个非线性耦合系统。我们可以从牛顿经典力学出发&#xff0c;列出具体的运动方程&#xff0c;并说明为何这个系统本质上是混沌的&#xff0c;无法得到一般解…...

HTML前端开发:JavaScript 常用事件详解

作为前端开发的核心&#xff0c;JavaScript 事件是用户与网页交互的基础。以下是常见事件的详细说明和用法示例&#xff1a; 1. onclick - 点击事件 当元素被单击时触发&#xff08;左键点击&#xff09; button.onclick function() {alert("按钮被点击了&#xff01;&…...

.Net Framework 4/C# 关键字(非常用,持续更新...)

一、is 关键字 is 关键字用于检查对象是否于给定类型兼容,如果兼容将返回 true,如果不兼容则返回 false,在进行类型转换前,可以先使用 is 关键字判断对象是否与指定类型兼容,如果兼容才进行转换,这样的转换是安全的。 例如有:首先创建一个字符串对象,然后将字符串对象隐…...

在QWebEngineView上实现鼠标、触摸等事件捕获的解决方案

这个问题我看其他博主也写了&#xff0c;要么要会员、要么写的乱七八糟。这里我整理一下&#xff0c;把问题说清楚并且给出代码&#xff0c;拿去用就行&#xff0c;照着葫芦画瓢。 问题 在继承QWebEngineView后&#xff0c;重写mousePressEvent或event函数无法捕获鼠标按下事…...

作为测试我们应该关注redis哪些方面

1、功能测试 数据结构操作&#xff1a;验证字符串、列表、哈希、集合和有序的基本操作是否正确 持久化&#xff1a;测试aof和aof持久化机制&#xff0c;确保数据在开启后正确恢复。 事务&#xff1a;检查事务的原子性和回滚机制。 发布订阅&#xff1a;确保消息正确传递。 2、性…...

Qemu arm操作系统开发环境

使用qemu虚拟arm硬件比较合适。 步骤如下&#xff1a; 安装qemu apt install qemu-system安装aarch64-none-elf-gcc 需要手动下载&#xff0c;下载地址&#xff1a;https://developer.arm.com/-/media/Files/downloads/gnu/13.2.rel1/binrel/arm-gnu-toolchain-13.2.rel1-x…...

Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement

Cilium动手实验室: 精通之旅---13.Cilium LoadBalancer IPAM and L2 Service Announcement 1. LAB环境2. L2公告策略2.1 部署Death Star2.2 访问服务2.3 部署L2公告策略2.4 服务宣告 3. 可视化 ARP 流量3.1 部署新服务3.2 准备可视化3.3 再次请求 4. 自动IPAM4.1 IPAM Pool4.2 …...

通过MicroSip配置自己的freeswitch服务器进行调试记录

之前用docker安装的freeswitch的&#xff0c;启动是正常的&#xff0c; 但用下面的Microsip连接不上 主要原因有可能一下几个 1、通过下面命令可以看 [rootlocalhost default]# docker exec -it freeswitch fs_cli -x "sofia status profile internal"Name …...