Linux笔记 --- 传统链表

news2024/9/24 5:21:54

目录

链表

单向链表

单向循环链表

双向链表

        设计表

        初始化

        在auchor后插入节点,

        在auchor前插入节点

        删除节点


传统链表

        通过使用链表我们可以将一个数组中的数据分开到不同位置存放并使用指针指向他们,使之逻辑相连,解决了顺序存储所需要一大块内存的问题,同时删除插入和扩展节点非常便利。为此,我们需要在定义链表时预留一个指针指向其他数据存放的地址,使得节点逻辑连贯,根据不同情况我们可以设置单向或者双向指针

单向链表

      单向链表指的就是节点中只包含一个指针,该指针用来指向相邻节点。对链表的操作,最基本的就是初始化空链表、创建新节点、插入节点、删除节点、移动节点、查找节点和遍历链表,下面先给出节点的设计代码,然后针对以上所述的操作各个击破。

       第一,设计节点
       节点的设计非常重要,关乎后续对链表各种操作,而单向(循环)链表节点的设计就非常简单,假设我们要处理的数据类型叫datatype,我们只需要在节点中增加一个指向本节点类型的指针即可:

typedef struct node
{
    int data;
    struct node *next;
}listnode,*singly_list;

        第二,初始化

        空链表分为有头节点的空链表和不带头节点的空链表,在不带有头节点的空链表情况下插入时要先判断头节点是否为空,因此我们一般更倾向于创建带有头节点的空链表,创建函数如下:

singly_list init_list (void)
{
    singly_list mylist = malloc(sizeof(listnode));
    if(mylist != NULL)
    {
        mylist->next = NULL;
    }

    return mylist;
}

        第三,插入节点

        链表最大的又是就是插入删除非常简单,单向链表中插入节点只需要修改两个指针,将新节点指向插入位置后一个节点,将前一个节点指向新节点

void insert_node(singly_list p,singly_list new)
{
    if(p == NULL || new == NULL)
        return;
    new->next = p->next;
    p->next = new;
}

        第四,删除节点 

        对于单向链表来说,没有指向前置节点的指针,因此我们要先创建一个指针寻找到前置指针,然后再进行删除

        

bool remove_node(singly_list mylist,singly_list delete)
{
    if(is_empty(mylist))
        return false;

    singly_list p = mylist;
    while (p != NULL && p->next != delete)
    {
        p = p->next;
    }
    
    if(p == NULL)
        return false;
    
    p->next = delete->next;
    delete->next = NULL;
    
    return true;
}

        第五,移动节点

        因为我们在前面已经将插入和删除封装进了函数,因此我们移动节点将会很简便

void move_node(singly_list mylist , singly_list p , singly_list anchor)
{
    if(mylist == NULL || p == NULL || anchor == NULL)
        return ;
    
    remove_node(mylist,p);
    insert_node(anchor,p);
}

         第六,根据内容查找指针

        

singly_list remove_node(singly_list mylist,int data)
{
    if(is_empty(mylist))
        return NULL;

    singly_list p;

    // p = mylist;
    // while (p != NULL && p->next->data != data)
    // {
    //     p = p->next;
    // }
    
    // if(p == NULL)
    //     return false;
    
    // p = p->next;

    for(p = mylist->next ; p != NULL ; p = p->next)
    {
        if (p->data == data)
        {
            break;
        }
        
    }
    
    return p;
}

用了两种方法,逻辑相同酌情使用

单向循环链表

        所谓单线循环链表就是单向链表中最后一个节点指向头节点,初始化方式如下

linklist init_list (void)
{
    linklist head = malloc(sizeof(listnode));
    head->next = head;

    return head;
}

        删除节点,对于单向循环链表来说不是必须指定头节点,可以直接从需要删除的节点开始轮询

void remove_node(linklist delete)
{
    linklist temp = delete;

    while (temp->next != delete)
    {
        temp = temp->next;
    }

    temp->next = delete->next;
    delete->next = NULL;
}

        移动节点,相比于单链表循环链表不需要从头节点开始轮询所以可以减少参数

void move_node(linklist p , linklist anchor)
{
    if(p == NULL || anchor == NULL)
        return ;
    
    remove_node(p);
    insert_node(anchor,p);
}

        查找节点,查找节点方面,循环列表跟单链表的区别就是判断查找结束的条件不同

linklist find_node(linklist mylist,int data)
{
    if(is_empty(mylist))
        return NULL;

    linklist p;
    for(p = mylist->next ; p != mylist ; p = p->next)
    {
        if (p->data == data)
        {
            break;
        }
        
    }
    
    return p == mylist ? NULL : p;
}

双向链表

        设计表

        相较于单链表来说双向链表多了一个指向前一个节点的指针

typedef struct node
{
    int data;
    struct node *next;
    struct node *prev;
}listnode,*double_list;

        初始化

        比单链表多一个指向自己的指针

double_list init_list (void)
{
    double_list mylist = malloc(sizeof(listnode));
    if(mylist != NULL)
    {
        mylist->prev = mylist->next = NULL;
    }
    return mylist;
}

        在auchor后插入节点

        在双向链表中需要操作四个指针

void insert_next(double_list new,double_list auchor)
{
    if(new == NULL||auchor == NULL);
        return;

    new->prev = auchor;
    new->next = auchor->next;
    
    auchor->next = new;
    new->next->prev = new;
}

 

        在auchor前插入节点

void insert_prev(double_list new,double_list auchor)
{
    if(new == NULL||auchor == NULL);
        return;

    new->prev = auchor->prev;
    new->next = auchor;

    new->prev->next = new;
    auchor->prev = new; 
}

        删除节点

        

void remove_node(double_list delete)
{
    if(delete == NULL);
        return;

    delete->prev->next = delete->next;
    delete->next->prev = delete->prev;

    delete->next = NULL;
    delete->prev = NULL;
}

        移动节点

        分为移动到目标前后

void move_next(double_list p,double_list auchor)
{
    remove_node(p);
    insert_next(p,auchor);
}

void move_prev(double_list p,double_list auchor)
{
    remove_node(p);
    insert_prev(p,auchor);
}

        查找节点

double_list find_node(double_list mylist,int data)
{
    if(is_empty(mylist))
        return NULL;

    double_list p;
    for(p = mylist->next ; p != mylist ; p = p->next)
    {
        if (p->data == data)
        {
            break;
        }
        
    }
    
    return p == mylist ? NULL : p;
}

传统链表的坏处

        传统的双向循环链表概念简单,操作方便,但存在有致命的缺陷,用一句话来概括就是:每一条链表都是特殊的,不具有通用性。换句话说,对于每一种不同的数据,所构建出来的传统链表都是跟这些数据相关的,所有的链表操作函数也都是数据相关的,换一种数据节点,则所有的操作函数都需要一一重写编写,这种缺陷对于一个具有成千上万种数据节点的工程来说是灾难性的,是不可接受的。
        简而言之,对于每个不同类型的节点我们没办法使用同一套函数操作他们,这在大型工程中很不方便
        究其原因,传统节点不仅包含了表达链表逻辑的指针,更包含了某一个具体类型的数据,而指针无法跟数据分开,于是出现了这样的问题

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

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

相关文章

软件更新中的风险识别与质量保证机制分析

​ ​ 您好,我是程序员小羊! “微软蓝屏”事件暴露了网络安全哪些问题? 近日,一次由微软视窗系统软件更新引发的全球性“微软蓝屏”事件,不仅成为科技领域的热点新闻,更是一次对全球IT基础设施韧性与安全性…

ChatTTS文本转语音本地部署结合内网穿透实现远程使用生成AI音频

文章目录 前言1. 下载运行ChatTTS模型2. 安装Cpolar工具3. 实现公网访问4. 配置ChatTTS固定公网地址 前言 本篇文章主要介绍如何快速地在Windows系统电脑中本地部署ChatTTS开源文本转语音项目,并且我们还可以结合Cpolar内网穿透工具创建公网地址,随时随…

Rabbitmq的死信队列与如何利用死信队列实现延迟队列

如果设置了队列的 TTL 属性,那么一旦消息过期,就会被队列丢弃(如果配置了死信队列被丢到死信队列中)。而如果仅设置消息的 TTL 属性,即使消息过期,也不一定会被马上丢弃,因为消息是否过期是在即将投递到消费者之前判定…

Unity复制资源目录并添加新的引用关系

有时候需要复制一个场景目录制作新的场景,打包场景也是独立资源,不希望资源复用。我们直接使用CtrlD复制资源,里面的预设,材质等都还是指向原有的,所以废话不多说,直接上代码。 操作窗口 首先是制作一个复…

电机控制器功率模块液冷散热参数计算

电机控制器功率模块液冷散热参数计算 1.概述2.热量与流量的关系3.功率模块损耗发热量计算4.案例计算 1.概述 该文档做为评估分析电机控制器功率模块在液冷散热条件下的相关参数参考计算说明。 2.热量与流量的关系 首先我们要确认产生热量的位置和数量。对于电机控制器来说&am…

DyFusion:基于动态融合的交叉注意三维目标检测 论文解析

目录 概况 创新点详解 1、跨注意力动态融合 Cross-Attention Dynamic Fusion (1)特征提取 (2)体素特征编码 (3) BEV特征提取 (4)特征动态融合 ①线性变换 ②对Q(BEV特征)和…

【CNN】卷积神经网络的相关介绍及计算

文章目录 传统神经网络结构卷积神经网络结构输入的区域大小计算特征值卷积结果计算公式卷积参数共享池化层最大池化特征图变化经典网络 传统神经网络结构 传统神经网络(左边的图2D的)可以叫wxb、全连接层、FC、MLP、多层感知机、多个线性层堆在一起&…

Python 爬虫入门(八):爬虫工程化及Scrapy简介「详细介绍」

Python 爬虫入门(八):爬虫工程化及Scrapy简介「详细介绍」 前言1. Python1.1 Python 简介1.2 Python 爬虫的优势1.3 必须掌握的 Python 基础知识1.3.1 基本语法1.3.2. 函数和模块1.3.3 文件操作1.3.4 数据处理1.3.5 类和对象1.3.6 异常处理 2…

CAP+RabbitMQ

CAP(C# APM for Microservices)是一个开源的C#库,用于在分布式系统(如SOA或微服务系统)中实现事件总线及最终一致性(分布式事务)。CAP提供了多种消息队列(MQ)实现的支持&…

手把手教你写一个图形化的端口扫描工具

前言 关于学习群 由于我使用masscan进行纯端口扫描的时候,遇到扫描不出结果的情况,我就考虑了自己写一个端口扫描脚本,还挺好用。 库介绍 1、asyncio asyncio 是 Python 的一个库,用于编写单线程并发代码。使用 asyncio&#…

MacBook2024非常出色的虚拟机软件Parallels Desktop19.3中文免费版本

最近我被问得最多的一个问题就是:能不能在一台设备上同时使用Windows系统和macOS系统?答案当然是肯定的,你只需要一款虚拟机软件就能轻松实现。今天,我就来为大家安利一款非常出色的虚拟机软件——Parallels Desktop19。 这款软件…

【C++】模拟实现queue

🦄个人主页:修修修也 🎏所属专栏:实战项目集 ⚙️操作环境:Visual Studio 2022 ​​ 一.了解项目功能 📌了解queue官方标准 在本次项目中我们的目标是模拟实现一个queue,先一起看一下C标准文档中queue的定义:cplusplus : C queue标准文档htt…

中英文字翻译,这几款软件值得收藏!

在这个全球化的时代,语言不再是沟通的障碍,而翻译软件则成为了我们跨越语言鸿沟的得力助手。今天,就让我们一起探索三款让英文翻译变得前所未有的简单与高效的神奇软件,无论是学习、工作还是旅行,它们都能成为你不可或…

kickstart无人值守以及pxe实现服务器自动部署

使用背景 在企业中安装多台操作系统时会面临的问题:当安装Linux操作系统时,安装过程会需要回答很多关于设定的问题 这些问题必须手动选择,否则无法进行安装 。当只安装1台Linux系统,手动选择设定工作量比较轻松 当安装多台Linux&a…

PSO_GA混合算法优化PID参数(附代码)

由于PSO算法本身的缺陷,其存在容易出现早熟收敛、后期迭代效率不高、搜索精度不高的问题,在线性递减惯性权重PSO算法的基础上,与GA遗传算法相结合,针对PSO易陷入局部最优,通过采用GA杂交变异的思想,增加了粒子的多样性,跳出局部最优,增强混合算法的全局搜索能力,提高搜…

完美解决pip命令版本冲突导致对应版本模块包无法安装的问题

解决步骤 使用pip更新/降低指定模块包命令格式降低pip自身至指定版本的命令再次换源安装指定模块包 在对 FasterNet 这篇论文源码复现过程中,我们首先需要安装相关依赖文件( path/to/your/requirements.txt) -extra-index-url https://down…

CentOS7 VMware虚拟机基于NAT配置网络IP

目录 前言 VMnet8 虚拟网络编辑 ens33 ping 防火墙 前言 平时学习时一直需要用到Linux服务器,一般都是在Windows上安装VMware来创建一个虚拟机。创建的虚拟机需要配置网络才能够访问外网,可以通过以下两种方式来配置虚拟机网络 桥接模式NAT模式&…

给儿童掏耳朵用什么工具好?TOP4机型实测数据大公开

作为一名专业的个护测评师,我深知宝宝掏耳朵是一件多难的事情,由于宝宝的耳朵属于盲区。在为他操作时,很容易伤及宝宝的耳膜。因此,帮宝宝掏耳朵时工具的选择非常的重要。然而市场上许多跨界大牌存在隐患。某些网红品牌&#xff0…

视频发光字体特效怎么做 会声会影字体怎么淡化退出 视频剪辑制作教程

视频字体样式在视频制作中起着重要的作用,它可以帮助传达信息、增强视觉吸引力、提供情感表达、强调关键信息和提供文化背景解读等。这篇文章以会声会影为例,来一起看看发光字体制作,字体怎么淡化退出等内容。 你可以在这里免费下载会声会影…

Spring-Kafka确认机制报错:No Acknowledgment available as an argument

问题出现 在spring boot集成kafka时报错,报错信息: No Acknowledgment available as an argument, the listener container must have a MANUAL AckMode to populate the Acknowledgment.翻译: Acknowledgment 参数不可用,监听…