无头单向非循环链表(详解)

news2024/11/19 17:27:19

无头单向非循环链表

  • 链表的种类的简单介绍
  • 链表的定义
    • typedef的运用
  • 节点的创建
  • 遍历
  • 头插
  • 尾插
  • 头删
  • 尾删
  • 查找节点位置
  • 任意位置插入
  • 任意位置删除

链表的种类的简单介绍

链表的种类有很多
1.分有头链表和无头链表
2.分循环链表和非循环链表
3.分单向链表和双向链表

这里的话,我就讲解2种类型的链表,第一种是无头单向非循环链表,第二种是有头双向循环链表
这里讲解第一种,第二种将会在下一篇博客中讲解

链表的定义

在这里插入图片描述

如图所示,链表分为指针域和数据域,
指针域一般命名为next指向下一个指针,起连接的作用,使数据连续,
数据域如果a1, a2所示,用来存放链表中这个节点的数据
无头链表的话,代表这第一个节点,也就是头结点,存放的数据是有效的
如果是有头节点的话,数据域存放的数据是无效的,是一个垃圾值。

typedef的运用

typedef 实际上也就是重定义
可以用来重定义结构或者数据的类型
用typedef的话,修改起来比较方便,根据我的理解跟宏定义的作用相似


typedef int SqListType;

struct SqListNode
{
	SqListType  date;
	struct SqListNode* next;
};

typedef struct SqListNode SqList;

如果所示,这里用结构体来定义链表
SqListType代表着这是int类型
SqList代表着 这是 struct SqListNode类型

使用typedef 的作用就是方便命名,便于修改

节点的创建

节点的创建,首先的话,也就是考察C语言的动态内存管理,用malloc函数或者用realloc函数
当然,
1.我们这里使用malloc函数来开辟空间
2.开辟完之后,给这个节点的数据域赋值,
3.给指针域初始化,
4.然后返回这个节点

SqList* creatNode(SqListType date)
{
    SqList* node = (SqList*)malloc(sizeof(SqListType));

    node->date = date;
    node->next = NULL;

    return node;
}

当然,这里函数的参数,加一个const,效果应该会更好些,因为这创建节点所传的数据本来就是个常数。

遍历

链表的遍历的话,同样挺简单的,因为通过观察可以知道
链表的最后一个节点,也就是尾节点
他的指针域没有指向下一个节点
说明,尾结点的指针域为NULL,也就是尾结点的next为空

void printDate(SqList* phead)
{ 
    SqList* cur = phead;

    while (cur)
    {
        printf("%d ", cur->date);
        cur = cur->next;
    }
    printf("\n");
}

这里的话
遍历肯定是用循环
如果不是尾结点的话,就打印这个节点的数据域
然后该节点等于下一个节点(也就是节点的移动,移动到下一个节点)
如果cur = tail(尾结点)->next的时候
当前节点运动到,尾结点的下一个节点,结束循环

头插

头插的话,也就是,在链表的头部前面在插入一个节点
同样不难,也就三步
不过这里要分2种情况
第一种,如果该链表是空链表的话,就直接让当前的头结点 = 新节点
第二种,如果该链表不是空链表
1.创建新节点(直接调用之前写的创建新节点的函数就行)
2.然后新节点成为头节点
3.新节点的指针域指向原来的头结点

void front_back(SqList** pphead, SqListType date)
{
    SqList* new = creatNode(date);
    if (NULL == *pphead)
    {
        *pphead = new;
    }
    else
    {
        //连节点
        SqList* head = *pphead;
        *pphead = new;
        new->next = head;
    }
}

当然这里使用了二级指针,如果是值的改变,使用二级指针
因为形参不影响实参
如果不涉及到值的改变,用一级指针
当然,如果你要用二级指针也可以

尾插

尾插的话,跟头插类似
也就比头插多了一个步骤,因为链表的头结点是已知的,不需要我们找
但是链表的尾结点是未知的,所以,
1.找到链表的尾结点
2.创建新节点
3.链表的尾结点指向新节点

当然,注意这里也要判断下,链表是否为空

void push_back(SqList** pphead, SqListType date)
{
    SqList* newNode = creatNode(date);

    if (NULL == *pphead)
    {
        *pphead = newNode;
    }
    else
    {
        SqList* tail = *pphead;
        while (NULL != tail->next)
        {
            tail = tail->next;
        }
        tail->next = newNode;
    }
}

头删

头删的话,也就是删除链表的第一个节点
然后链表头结点的下一个节点,成为该链表新的头节点
当然,也要判断链表是否为空
如果,链表为空的话,就直接退出这个函数

当然链表的删除,就直接用free函数,释放这个节点的内存就行

具体代码如下:


void pop_front(SqList** pphead)
{
    if (NULL == *pphead)
    {
        printf("空链表");
        return;
    }
    else
    {
        SqList* Next = (* pphead)->next;
        free(*pphead);
        *pphead = Next;
    }

> 这里是引用

    /*SLTNode* next = (*pphead)->next;
    free(*pphead);

    *pphead = next;*/
}

当然,这里需要注意的是,如果你先删除了头节点,那么你头节点的下一个节点的位置就找不到,
所以,你必须先要记录头节点下一个节点的位置,在进行删除

尾删

尾删的话,跟头删差不多
找到尾结点的位置,和尾结点的上一个节点的位置
删除尾结点
尾结点的上一个节点成为新的尾结点
同样要注意:
1.链表是否为空的情况
2.尾结点的指针域要置空
(虽然说,你用free函数删除,但是要避免这个不为空,是野指针的情况)

查找节点位置

查找的话,也挺简单的
就挨个遍历,这个链表
如果这个节点的数据域等于你要查找的数据,那么就返回这个节点的位置
如果说找不到的话,就返回空


SqList* findDate(SqList* phead, SqListType date)
{
    SqList* p = phead;

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

    return p;
}

任意位置插入

任意位置插入的话,这里我是结合前面的查找函数使用
通过给出的数据,通过查找函数,返回这个节点的位置
根据这个位置,在这个位置之后插入新的节点

插入的思想,跟头插类似
1.新节点的下一个节点指向原来位置节点的下一个节点
2.原来位置的节点指向下一个新节点

当然同样要考虑链表是否为空的情况


// pos前面插入date
void insert(SqList** pphead, SqList* pos, SqListType date)
{
    if (NULL == *pphead)
    {
        *pphead = creatNode(date);
        (*pphead)->next = NULL;
    }
    else
    {
        SqList* new = creatNode(date);
        SqList* pre = *pphead;

        while (pos != pre->next)
        {
            pre = pre->next;
        }

        pre->next = new;
        new->next = pos;
    }
   
}

任意位置删除

任意位置删除的思想,其实跟那个尾删差不多
当然也要考虑,链表是否为空的情况

用查找函数,找到要删除节点的位置
1.要知道要删除节点,前一个节点的位置,后一个节点的位置已知
2,要删除节点的前一个节点指向删除节点的后一个节点

void pop_back(SqList** pphead)
{
    if (NULL == *pphead) // 没有节点
    {
        printf("空链表");
        return;
    }
    else if(NULL !=(*pphead)->next) //只有一个节点
    {
        free(*pphead);
        *pphead = NULL;
    }
    else
    {
        SqList* tail = *pphead;
        SqList* pre = NULL;
        //找到尾结点和尾结点的前一个节点 
        while( NULL != tail->next)
        {
            pre = tail;
            tail = tail->next;
        }

        free(tail);
        pre->next = NULL;
    }
}

当然,这里要注意,链表只有一个节点的情况
就直接,删除头结点,也就是头删

好了,无头单向非循环链表的讲解就到这里,下一篇博客,讲解有头单向循环链表。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1017784.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

RecyclerView源码解析(四):RecyclerView对ViewHolder的回收

RecyclerView源码解析(四):RecyclerView对ViewHolder的回收 导言 前面几篇文章我们已经介绍了RecyclerView绘图的三大流程和其四层缓存机制,不过对于我来说还有一个疑问,那就是RecyclerView是如何将分离的ViewHolder进…

MATLAB:电机控制(Motor Control)

目录 前言1、Overview1.1、Specific objectives1.2、Resources1.3 、Industrial context1.4 、Architecture of the system1.5 、Approach/Steps 2、MODELLING THE MOTOR AND THE LOAD2.1Simulate a DC motor by its physical model2.2、Modelling the motor / load by its mat…

堆内存与栈内存

文章目录 1. 栈内存2. 堆内存3. 区别和联系参考资料 1. 栈内存 栈内存是为线程留出的临时空间 每个线程都有一个固定大小的栈空间,而且栈空间存储的数据只能由当前线程访问,所以它是线程安全的。栈空间的分配和回收是由系统来做的,我们不需…

《C++ primer plus》精炼(OOP部分)——对象和类(5)

“学习是照亮心灵的火炬,它永不熄灭,永不止息。” 文章目录 类的自动和强制类型转换原始类型转换为自定义类型将自定义类型转换为原始类型 类的自动和强制类型转换 原始类型转换为自定义类型 可以用一个参数的构造函数来实现,例如&#xff…

【Linux操作系统】信号的产生捕获

🔥🔥 欢迎来到小林的博客!!       🛰️博客主页:✈️林 子       🛰️博客专栏:✈️ Linux       🛰️社区 :✈️ 进步学堂       &#x1f6f0…

destoon关于archiver归档的性能优化

今天在处理一个项目时候发现archiver单个模块归档超过百万数据,打开速度就特慢,所以打开archiver下index.php文件进行分析,发现有句sql作怪,查询需要三四分钟,所以要修改这个。 $result $db->query("SELECT …

login (mobile email usercode)

手机、邮箱、用户编码登录 package login;/*** 常量类(改造拉到你自己项目里面)** author ZengWenFeng* date 2023.09.17* email 117791303qq.com* mobile 13805029595*/ public class Constant {// 登录界面的登录方式:手机、邮箱、用户名public static final Str…

YOLOv8学习

1 YOLOv8训练自己的数据集 1.1 部署和运行 1.1.1 第一步,下载代码 源码地址 1.1.2 第二步,创建环境 默认已经安装好conda conda create -n yolopy38 python3.8conda activate yolopy38安装所需要的包,先cd到代码目录下 pip install -r…

深眸科技自研工业AI视觉检测设备,检测精度99.9%加速智造进程

随着机器视觉技术的持续升级,国内制造行业不断发展,工艺水平持续优化,产品的数量和种类与日俱增。当前社会将产品质量标准提高,在满足正常的性能使用外,还需要具有良好的表面外观质量。但在工业制造过程中,…

【C语言】【数据存储】用%d打印char类型数据,猜结果是啥

题目代码如下&#xff1a; #include <stdio.h> int main() {char a -1;signed char b-1;unsigned char c-1;printf("a%d,b%d,c%d",a,b,c);return 0; }解题关键&#xff1a; 1.二进制存储&#xff1a;原码&#xff0c;反码&#xff0c;补码 互换 2.截断 3.整型…

密码学入门——Feistel网络

文章目录 参考书一、引入二、Feistel网络计算流程三、Feistel网络的解密四、Feistel网络的性质 参考书 图解密码技术&#xff0c;第三版 一、引入 DES的基本结构是由Horst Feistel设计的&#xff0c;因此也被成为Feistel网络&#xff08;Feistel结构&#xff0c;Feistel密码…

《动手学深度学习 Pytorch版》 6.6 卷积神经网络

import torch from torch import nn from d2l import torch as d2l6.6.1 LeNet LetNet-5 由两个部分组成&#xff1a; - 卷积编码器&#xff1a;由两个卷积核组成。 - 全连接层稠密块&#xff1a;由三个全连接层组成。模型结构如下流程图&#xff08;每个卷积块由一个卷积层、…

分布式电源接入对配电网影响分析(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…

汽车电子——产品标准规范汇总和梳理(电磁兼容)

文章目录 前言 一、辐射发射 二、传导发射 三、沿电源线瞬态传导发射 四、辐射抗扰 五、大电流注入抗扰 六、磁场抗扰 七、便携式发射机抗扰 八、沿电源线瞬态抗扰 九、非电源线瞬态抗扰 十、电快速脉冲群抗扰 十一、静电抗扰 总结 前言 见《汽车电子——产品标准规…

Oracle数据库安装卸载

文章目录 一、数据库版本说明二、软件的下载和安装1.下载软件2.安装数据3.创建数据库4.PLSQL 三、数据库的卸载1.关闭相关服务3.卸载软件3.删除注册信息 四、用户和权限 一、数据库版本说明 1998年Oracle8i&#xff1a;i指internet&#xff0c;表示oracle向互联网发展&#xf…

bootstrap柵格

.col-xs- 超小屏幕 手机 (<768px) .col-sm- 小屏幕 平板 (≥768px) .col-md- 中等屏幕 桌面显示器 (≥992px) .col-lg- 大屏幕 大桌面显示器 (≥1200px) 分为12个格子 -后面的1代表占12分子1也就是一份 1.中等屏幕 <div class"container-fluid a">&l…

ARM Linux DIY(十二)NES 游戏

文章目录 前言交叉编译工具链使能 Cnes 游戏模拟器移植游戏手柄调试 前言 很多小伙伴为了不让自己的 V3s 吃灰&#xff0c;进而将其打造成游戏机。 我们 DIY 的板子具备屏幕、扬声器、USB Host&#xff08;可以接游戏手柄&#xff09;&#xff0c;当然也要凑一凑热闹。 交叉编…

SpringBootTest

SpringBootTest注解 --基于SpringBoot2.5.7版本 可以在运行基于Spring Boot的测试的测试类上指定的注释。在常规的Spring TestContext框架之上提供了以下特性: 默认提供SpringBootContextLoader作为ContextLoader&#xff0c;也通过 ContextConfiguration(loader…)来自定义 若…

docker安装zookeeper(单机版)

第一步&#xff1a;拉取镜像 docker pull zookeeper第二步&#xff1a;启动zookeeper docker run -d -e TZ"Asia/Shanghai" -p 2181:2181 -v /home/sunyuhua/docker/zookeeper:/data --name zookeeper --restart always zookeeper

基于改进莱维飞行和混沌映射的粒子群优化BP神经网络预测股票价格研究(Matlab代码实现)

&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️&#x1f4a5;&#x1f4a5; &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻辑清晰&#xff0c;为了方便读者。 ⛳️座右铭&a…