数据结构(三)——双向链表,循环链表,内核链表,栈和队列

news2024/11/15 11:03:18

双链表
产生原因:单链表只有一个指向后继的指针,如果要访问某节点的前驱结点,只能从头遍历,也就是访问后继节点的时间复杂度为1,访问前驱结点的时间复杂度为n。                        而引入双链表使得在插入、删除的时间复杂度只为1,缺点就是更加浪费空间。

循环链表
和单链表区别在于,最后一个结点的指针不是NULL,而是改为指向头结点。

优点是对表头和表尾进行操作的时间复杂度都是1

内核链表 (与普通链表区别,是数据包含节点)  

   一种链表结构能够操作多种类型的数据对象; 
    节点包含数据变成数据包含节点。

如上图,内核链表头结点结构为:

struct list_head {
    struct list_head *next;
    struct list_head *prev;
};

其余节点为数据包含节点,例如:

typedef struct data {
    struct list_head node; //小节点
    int data;                      //数据
}data_t;

其操作代码如下:和队列
1.栈和队列是特殊的表状结构
    表可以在任意位置插入和删除
    栈和队列只允许在固定位置插入和删除

2.栈:分为顺序栈(空增栈) 和 链式栈

     LIFO 结构  
    先进后出,后进先出 (Last In First Out)的线性表
    栈顶:允许入栈出栈的一端称为栈顶
    栈底:不允许入栈和出栈的一端称为栈底

    入栈(压栈):将数据元素放入栈顶
    出栈(弹栈):将数据元素从栈顶位置取出

    空栈:不含任何元素的空表。

    顺序栈分类:空增栈;空减栈; 满增栈;满减栈(学的是空增栈)

     1. 栈的常见基本操作

     初始化(InitStack创)->进栈(Push增)->出栈(Pop删)->查栈是否为空(IsEmpty)、  查栈是否已满(IsFull)、销毁栈(DestroyStack销)

     2. 空增栈(顺序栈)

        其操作代码如下:

//存放数据的类型
typedef int DataType;

//标签类型,定义顺序栈结构体
typedef struct stack 
{
    DataType *pData;
    int Top;
    int tLen;
}SeqStack;
SeqStack *CreateSeqStack(int MaxLen)
{
    SeqStack *pTmpStack = NULL;

    //1.申请标签空间
    pTmpStack = malloc(sizeof(SeqStack));
    if (NULL == pTmpStack)
    {
        return NULL;
    }

    //2.对每个成员赋初值
    pTmpStack->tLen = MaxLen;
    pTmpStack->Top = 0;
    pTmpStack->pData = malloc(MaxLen * sizeof(DataType));
    if (NULL == pTmpStack->pData)
    {
        return NULL;
    }

    //3.申请存放数据的空间

    //4.返回标签地址 

    return pTmpStack;
}
int IsFullSeqStack(SeqStack *pTmpStack)//判断栈满、空
{
    return pTmpStack->tLen == pTmpStack->Top ? 1 : 0;
}
int IsEmptySeqStack(SeqStack *pTmpStack)
{
    return 0 == pTmpStack->Top ? 1 : 0;
}
int PushSeqStack(SeqStack *pTmpStack, DataType TmpData)//进栈操作push
{
    if (IsFullSeqStack(pTmpStack))
    {
        return -1;
    }
    pTmpStack->pData[pTmpStack->Top] = TmpData;
    pTmpStack->Top++;
    return 0;
}
DataType PopSeqStack(SeqStack *pTmpStack) //出栈
{
    if (IsEmptySeqStack(pTmpStack))
    {
        return -1;
    }

    pTmpStack->Top--;

    return pTmpStack->pData[pTmpStack->Top];
}

int DestroySeqStack(SeqStack **ppTmpStack)//销毁栈
{
    free((*ppTmpStack)->pData);
    free(*ppTmpStack);
    *ppTmpStack = NULL;

    return 0;
}

     3.链式栈

        采用链式存储的栈称为链式栈,链栈的优点是便于多个栈共享存储空间和提高其效率,且不存在栈满上溢的情况。通常采用单链表实现,并规定所有操作都是在单链表的表头进行的。这里规定链栈没有头节点,Lhead指向栈顶元素

对于空栈来说,链表原定义是头指针指向空,那么链栈的空其实就是top=NULL的时候。

链栈的结构代码如下(用到内核链表 即list.h):

struct list_head {
    struct list_head *next;
    struct list_head *prev;
};  //内核链表小节点

链式栈入栈时类似于头插法,先进后出,出栈时第一个节点出栈;

示例代码main.c如下:

#include "list.h"
#include <stdio.h>

typedef struct data 
{
    struct list_head node;
    int data;
}data_t;

int main(void)
{
    
    struct list_head *ptmpnode = NULL;
    data_t d[5] = {
        {{NULL, NULL}, 1},
        {{NULL, NULL}, 2},
        {{NULL, NULL}, 3},
        {{NULL, NULL}, 4},
        {{NULL, NULL}, 5},
    };
    int i = 0;

    //定义链表空节点,并初始化
    struct list_head head;
    INIT_LIST_HEAD(&head);

    //将5个数据头插法插入链表中
    for (i = 0; i < 5; i++)
    {
        list_add(&d[i].node, &head);
    }
    
    //只要链表不为空将第一个节点出栈
    while (!list_empty(&head))
    {   
        ptmpnode = head.next;
        printf("%d ", list_entry(ptmpnode, data_t, node)->data);
        list_del(head.next);
    }
    printf("\n");

    return 0;
}

      4.性能分析
    链式栈的进栈push和出栈pop操作都很简单,时间复杂度均为O(1)。
     对比一下顺序栈与链栈,它们在时间复杂度上是一样的,均为O(1)。对于空间性能,顺序栈需要事先确定一个固定的长度,可能会存在内存空间浪费的问题,但它的优势是存取时定位很方便,而链式栈则要求每个元素都有指针域,这同时也增加了一些内存开销,但对于栈的长度无限制。所以它们的区别和线性表中讨论的一样,如果栈的使用过程中元素变化不可预料,有时很小,有时非常大,那么最好是用链栈,反之,如果它的变化在可控范围内,建议使用顺序栈会更好一些

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

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

相关文章

C语言代码练习

今日练习&#xff1a; 34、通过指向结构体变量的指针变量变量输出结构体变量中的信息。 35、建立一个简单链表&#xff0c;它由3个学生数据的结点组成&#xff0c;要求输出各结点中的数据。36、从键盘输入一些字符&#xff0c;逐个把他们送到磁盘上去&#xff0c;直到用户输入一…

【电机控制】永磁同步电机FOC控制—电流环PI参数整定

0. 前言 在了解电流环PI参数整定之前我们需要有以下几点基础知识&#xff1a; 1、了解什么是传递函数、传递函数的零点和极点。 2、了解极点对系统稳定性的影响。 有基础的小伙伴可以跳着看。 1. 传递函数与零点极点 1.1 传递函数 系统传递函数G(s)的定义是&#xff1a;在指零…

Pytorch – YOLOv9自定义资料训练

本篇将讲解目前最新推出的YOLOv9搭配Roboflow进行自定义资料标注训练流程&#xff0c;透过Colab上进行实作说明&#xff0c;使大家能够容易的了解YOLOv9的使用。 ►YOLO框架下载与导入 ►Roboflow的资料收集与标注 进入Roboflow官网&#xff0c;点选右上Sign up注册自己的帐号…

网站设计公司设计费用

网站设计公司的设计费用往往是一个让人头疼的问题。设计费用的高低涉及到多个因素&#xff0c;包括公司规模、项目复杂性、设计师经验等。本文将深入探讨网站设计公司的设计费用&#xff0c;并提供一些建议&#xff0c;帮助您在有限预算下实现最佳性价比。 1. 项目规模与复杂性…

GitHub 上 Stars 数量最多的 8 个开源 CRUD 项目

继续我们的 GitHub Star 系列&#xff01;这是本系列的第四篇文章&#xff0c;之前的内容&#xff1a; GitHub Star 数量前 12 的开源无代码工具GitHub Star 数量前 15 的开源低代码项目GitHub Star 数量前 11 的开源内部工具 本期我们来盘点 CRUD 项目。在软件开发中&#x…

爬虫练习(猫眼电影解密)

问题 随便拿一篇电影做样例。我们发现猫眼的页面数据在预览窗口中全是小方框。在当我们拿到源码以后&#xff0c;数据全是加密后的。所以我们需要想办法破解加密&#xff0c;拿到数据。 破解过程 1.源码获取问题与破解 分析 在我们刚刚请求url的时候是可以得到数据的&#xff…

[Linux] 操作系统 入门详解

标题&#xff1a;[Linux] 操作系统 水墨不写bug 目录 一、冯 . 诺依曼体系结构 1.冯诺依曼体系结构简介 2.对冯诺依曼体系结构的理解 二、操作系统定位 1.为什么需要操作系统&#xff1f; 2.操作系统是什么&#xff1f; 三、系统调用和库函数 正文开始&#xff1a; …

可交互、会学习、自成长机器人——李德毅院士

在以“农业无人农场”为主题的中国工程科技论坛上&#xff0c;中国工程院院士、欧亚科学院院士、中国人工智能学会和中国指挥与控制学会名誉理事长&#xff0c;中科原动力首席科学家李德毅院士应邀做题为《机器具身交互智能》的演讲。李德毅院士表示&#xff0c;智能机器不但把…

CentOS7单机环境安装k8s集群

目录 1、环境准备 2、安装依赖工具 3、配置 Kubernetes 的国内 Yum 源 4. 安装 Kubernetes 组件 5、初始化 Kubernetes 集群 1. 容器运行时没有正常运行 1.1. 可能的原因 1.2. 解决办法 2. 初始化拉取镜像卡住 2.1. 使用国内的镜像源&#xff08;无法解决问题&#x…

机器学习之监督学习(二)二元逻辑回归

机器学习之监督学习&#xff08;二&#xff09;逻辑回归(二元分类问题&#xff09; 1. 分类 classification2.二元分类逻辑回归 binary-classified logistic regression模块1: sigmoid 激活函数 sigmoid function模型公式模块2: 决策边界 decision boundary代价函数梯度下降欠拟…

【Redis】Redis 主从复制原理与配置详解:解决单点故障与性能瓶颈的最佳方案

目录 主从复制配置建立复制断开复制安全性只读传输延迟 拓扑⼀主⼀从结构一主多从结构树形主从结构 原理复制过程数据同步 psync全量复制部分复制实时复制 小结 主从复制 这部分相关操作不需要记忆!!! 后续⼯作中如果⽤到了能查到即可. 重点理解流程和原理. 单点问题&#xff1…

onvif应用--IPC鉴权(认证)

一、鉴权原理 1&#xff09;onvif的用户验证&#xff0c;是基于WS_UsernameToken&#xff0c;所谓的WS_UsernameToken加密&#xff0c;就是将用户名、密码、Nonce、Created都包含在了header里面 参数 意义 username待认证的用户名Nonce客户端随机产生的字符串Created请求认证…

arXiv风评被害?

arXiv “风评被害”&#xff1f; arXiv是一个在学术界具有重要影响力的开放预印本论文网站&#xff0c;自三十多年前创立以来&#xff0c;它已经成为了物理学、计算机科学、统计学等科学论文最重要的发布平台之一&#xff0c;同时也是众多科研人员分享和交流研究成果的重要渠道…

单片机工程师:创新与挑战之路

摘要&#xff1a;本文全面深入地探讨了单片机工程师这一职业角色。详细阐述了单片机工程师的职责范围、所需技能&#xff0c;包括硬件设计、软件编程、调试与测试等方面。分析了单片机在不同领域的应用&#xff0c;如工业控制、消费电子、智能家居等。同时&#xff0c;探讨了单…

【计算机组成原理】计算机系统的基本组成

文章目录 计算机硬件的基本组成早期的冯诺依曼机冯诺依曼结构冯诺依曼机的特点 现代计算机现代计算机的结构 各硬件的工作原理主存储器主存储器的基本组成 运算器运算器的基本组成 控制器控制器的基本组成 计算机软件 计算机硬件的基本组成 早期的冯诺依曼机 冯诺依曼在研究 …

图纸文件怎么加密?2024六款图纸加密软件推荐,个个好用不踩雷!

想象一下&#xff0c;公司的设计图纸被无意间泄露&#xff0c;结果对手提前推出了相似的产品。为了避免这种令人头疼的情况发生&#xff0c;图纸加密就显得尤为重要。 别担心&#xff0c;今天我们就带你了解2024年六款超好用的图纸加密软件&#xff0c;让你的图纸“安全感”爆…

业务复杂度治理方法论--十年系统设计经验总结

一、复杂度综述 1、什么是复杂度 软件设计的核心在于降低复杂性。 --《软件设计的哲学》 业界对于复杂度并没有统一的定义&#xff0c;斯坦福教授John Ousterhout从认知负担和工作量方面给出了一个复杂度量公式 &#xfeff; &#xfeff;&#xfeff; 子模块的复杂度cp乘…

快充协议方案的工作原理及场景应用

快充协议芯片是支持各种快充快充协议的芯片&#xff0c;它们能智能识别插入的设备类型&#xff0c;并根据设备的需求调整充电电压和电流&#xff0c;从而实现快速充电。 XSP08Q芯片是内置快充功能的协议芯片&#xff0c;它基于先进的充电技术&#xff0c;通过协商电压和电流&a…

【数据结构】二叉树顺序存储结构堆的应用以及解决TOP-K问题

文章目录 前言1. 堆的应用1.1 堆排序1.2 TOP-K问题 2. 结语 前言 前面我们学习了堆这个数据结构&#xff0c;这种数据结构是一种顺序结构存储的完全二叉树&#xff0c;现在我们来看一看堆的应用。 1. 堆的应用 1.1 堆排序 版本一&#xff1a;基于已有数组建堆、取堆顶元素完…

Linux CentOS 部署Docker

1. yum 配置 &#xff08;1&#xff09;更新yum yum update -y 如果不升级更新yum 可能在后续docker部署后再更新容器会出现oci runtime error等 &#xff08;2&#xff09;安装yum工具类准备 yum install -y yum-utils device-mapper-persistent-data lvm2 &#xff08;3&…