朝花夕拾 · 数据结构 | 队列与栈篇

[朝花夕拾]基于C#的模拟仿真平台设计(部分)及服务器异步通信代码 在14年和某研究所合作的一个项目,使用C#构建CS架构的仿真平台。 阅读详情

一.队列

1.队列的顺序存储

1.队列的定义
队列(Qucue)简称队,也是一种操作受限的线性表,只允许在表的一端进行插入,而在表的另一端进行删除。向队列中插入元素称为入队或进队;删除元素称为出队或离队。这和我们日常生活中的排队是一致的,最早排队的也是最早离队的,其操作的特性是先进先出(FirstInFirst Out,FIFO),如图所示。

队头(Front):允许删除的一端,也称队首。
队尾(Rear):允许插入的一端。
空队列:不含任何元素的空表。

顺序队列的两种定义:

1.

typedef int Data_t;

typedef struct node
{
    Data_t data;
    struct node *pnext;
}Node_t;

typedef struct lqueue
{
    Node_t *phead;
    Node_t *ptail;
    int clen;
}LQue_t;

2.

typedef struct{
Data_t data[MaxSize];    //用数组存放队列元素
int front,rear;            //队首指针和队尾指针
}SqQueue;

以第一种定义为例,以下为相关CRUD功能实现

LQue_t * create_link_queue()
{
    LQue_t *pque = malloc(sizeof(LQue_t)); 
    if (NULL == pque)
    {
        printf("malloc error\n");
        return NULL;
    }  
    pque->phead = NULL;
    pque->ptail = NULL;
    pque->clen = 0;

    return pque;
}
int is_empty(LQue_t *plink)
{
    return NULL == plink->phead;
}
int insert_link_queue(LQue_t* pque,int data)
{
    Node_t *p = malloc(sizeof(Node_t));
    p->data = data;
    p->pnext = NULL;
    if(p == NULL)
    {
        printf("malloc error\n");
        return -1;
    }
    if(pque->phead == NULL)
    {
        pque->phead = p;
        pque->ptail = p;
    }
    else
    {
        pque->ptail->pnext = p;
        pque->ptail = p;
    }
    pque->clen++;
      return 0;
}
void show_link_queue(LQue_t* pque)
{
    if(is_empty(pque))
    {
        return;
    }
    Node_t *ptmp = pque->phead;
    while(ptmp)
    {
        printf("%d ",ptmp->data);
        ptmp = ptmp->pnext;
    }
    printf("\n");
}
int pop_link_queue(LQue_t* pque,Data_t *pdata)
{
    if(is_empty(pque))
    {
        return -1;
    }
    Node_t *pnode = pque->phead;
    pque->phead = pnode->pnext;
    *pdata = pnode->data;
    free(pnode);
    pque->clen--;
    if(pque->clen == 0)
    {
        pque->ptail = NULL;
    }
    return 0;
}
int get_link_queue_head(LQue_t *pque,Data_t *pdata)
{
    if(is_empty(pque))
    {
        return -1;
    }
    *pdata = pque->phead->data;;
    return 0;
}
void destory_link_queue(LQue_t *pque)
{
//    if(is_empty(pque))
//   {
//        return ;
//    }
//    while(pque->phead)
//   {
//    Node_t *pfree = pque->phead;
//    pque->phead = pfree->pnext;
//   free(pfree);
//   pque->clen--;
//   }
//   pque->clen = 0;
//   free(pque);
    while (!is_empty_link_queue(pque))
    {
        pop_link_queue(pque, NULL);
    }
    free(pque);
}

2.链式队列

3.循环队列

由于上述顺序队列存在“假溢出”的问题,这里引出循环队列的概念。将顺序队列臆造为一个环状的空间,即把存储队列元素的表从逻辑上视为一个环,称为循环队列。当队首指针Q.front=MaxSize-1后,再前进一个位置就自动到0,这可以利用除法取模运算(%)来实现。

为了区分是队空还是队满的情况,有三种处理方式:

1)牺牲一个单元来区分队空和队满,入队时少用一个队列单元,这是一种较为普遍的做法,约定以“队首指针在队尾指针的下一位置作为队满的标志”,如图3.7(d2)所示。队满条件: (Q.rear+1)%MaxSize==Q.front。队空条件:Q.front==Q.rear。队列中元素的个数:(Q.rear-Q.front+MaxSize)%MaxSize。

2)类型中增设size数据成员,表示元素个数。若删除成功,则size减1,若插入成功,则 size 加 1,队空时 Q.size==0;队满时 Q.size==MaxSize,两种情况都有Q.front==Q.rear.

3)类型中增设tag数据成员,以区分是队满还是队空。删除成功置tag=0,若导致Q.front==Q.rear,则为队空;插入成功置tag=1,若导致Q.front==Q.rear,则为队满。

循环链表定义

typedef struct seq_que
{
    Data_t* base;
    int head;
    int tail;
}SQue_t; 

基本功能:

SQue_t* create_seq_queue()
{
    SQue_t* psq = malloc(sizeof(SQue_t));
    if (NULL == psq)
    {
        printf("malloc error\n");
        return NULL;
    }
    psq->base = malloc(sizeof(Data_t)*SEQ_MAX_LEN);
    if (NULL == psq)
    {
        printf("malloc error\n");
        return NULL;
    }
    psq->head = 0;
    psq->tail = 0;
    return psq;
}
int push_seq_queue(SQue_t *psq,Data_t data)
{
    if(is_full_seq_queue(psq))
    {
        return -1;
    }
    psq->base[psq->tail] = data;
    psq->tail = (psq->tail+1)%SEQ_MAX_LEN;
    return 0;
}
int is_full_seq_queue(SQue_t* psq)
{
    return (psq->tail+1)%SEQ_MAX_LEN == psq->head;
}
int is_empty_seq_queue(SQue_t *psq)
{

    return psq->tail == psq->head;
}
void show_seq_queue(SQue_t*psq)
{
    if(is_empty_seq_queue(psq))
    {
        return ;
    }
    int tmp = psq->head;
    while(tmp<psq->tail)
    {
        printf("%d ",psq->base[tmp]);
        tmp++;
    }
    printf("\n");
}
int pop_seq_queue(SQue_t *psq,Data_t *pdata)
{

    if(is_empty_seq_queue(psq))
    {
        return -1;
    }
    if(pdata = NULL)
    {
        return -1;
    }
    *pdata = psq->base[psq->head];
    psq->head = (psq->head+1)%SEQ_MAX_LEN;
    return 0;
}
void destory(SQue_t *psq)
{
    free(psq->base);
    psq->base = NULL;
    free(psq);
}

4.队列的应用

1.队列在层次遍历中的应用

2.队列在计算机系统中的应用

二.栈

1.链式栈

栈结构:只允许从一端进行插入和删除数据的线性存储结构,成为栈结构。

数据插入和删除的这端成为栈顶,另一端成为栈底;

数据的插入称为入栈/压栈,数据的删除称为出栈/弹栈。

顺序栈:
满增栈、空增栈、满减栈、空减栈
满栈、空栈:根据所在位置是否存有元素确定
栈顶所在位置一直存有元素称为满栈,先移动栈顶再存数据。
栈顶所在位置一直没有元素称为空栈,先存数据再移动栈顶。
增栈、减栈:根据栈的生长方向确定。
入栈数据时,栈顶向内存高地址移动,称为增栈,入栈数据时,栈顶向内存低地址移动,称为减栈。

与内存中栈的区别:

前者是线性表的一种实现形式,是一种逻辑数据结构,由开发人员自己管理(开辟和释放内存空间);后者是由操作系统管理,存放局部变量和形参等数据,二者都是先进后出结构。

链式栈的结构定义:

typedef int Data_t;

typedef struct node
{
    Data_t data;
    struct node *pnext;
}Node_t;

typedef struct stack
{
    Node_t *ptop;
    int clen;
}Stack_t;

基本功能实现:

#include<stdio.h>
#include"stack.h"
#include<stdlib.h>


Stack_t *create_stack()
{
    Stack_t *pstack = malloc(sizeof(Stack_t));
    if(NULL == pstack)
    {
        printf("malloc error\n");
        return NULL;
    }
    pstack->clen = 0;
    pstack->ptop = NULL;
    return pstack;
}
int push_stack(Stack_t *pstack, Data_t data)
{
    Node_t *pnode = malloc(sizeof(Node_t));
    if(NULL == pnode)
    {
        printf("malloc error\n");
        return -1;
    }
    pnode->data = data;
    pnode->pnext = pstack->ptop;
    pstack->ptop = pnode;
    pstack->clen++;
    return 0;
}
int pop_stack(Stack_t *pstack, Data_t *pdata)
{
    if(is_empty_stack(pstack))
    {
        return -1;
    }
    Node_t *pfree = pstack->ptop;
    if(pdata)
    *pdata = pfree->data;
    pstack->ptop = pfree->pnext;
    free(pfree);
    pstack->clen--;
    return 0;
}
int is_empty_stack(Stack_t *pstack)
{
    return pstack->clen == 0;
}
void clear_stack(Stack_t *pstack)
{
    while(!is_empty_stack(pstack))
    {
        pop_stack(pstack,NULL);
    }
}
void show_stack(Stack_t *pstack)
{
    Node_t *ptmp = pstack->ptop;
    while(ptmp)
    {
        printf("%d ",ptmp->data);
        ptmp = ptmp->pnext;
    }
    printf("\n");
}
int get_stack_top(Stack_t *pstack,Data_t *pdata)
{
    if(is_empty_stack(pstack))
    {
        return -1;
    }
    *pdata = pstack->ptop->data;
    return 0;
}
void destroy_stack(Stack_t *pstack)
{
    clear_stack(pstack);
    free(pstack);
}

2.栈的应用

解决回溯问题;
撤销功能、网页撤销功能缓存;
判断回文字符串,判断成对出现的符号有没有丢失;

栈在括号匹配中的应用:

栈在递归中的应用:

栈在表达式中的应用:

中缀表达式转后缀表达式:

注意,先出栈的为右操作数,后出为左操作数,操作符每次出栈时要出两个操作数。

在不同版本Python中安装PyQT5及PyQT5-Tools 阅读详情

相关推荐

UE5 Compute Shader实战:从基础到高级应用全解析

本文全面解析了在UE5中应用Compute Shader的完整流程,从基础概念、环境搭建到核心机制与实战应用。详细介绍了如何通过参数传递、线程派遣与数据读写实现GPU并行计算,并深入探讨了GPU粒子模拟、性能优化及结合光线追踪等高级应用场景,为开发者掌握UE5高性能计算提供系统指导。

yhn45678901的博客 500

朝花夕拾喵の单调队列

#include<stdio.h> #include<algorithm> #include<functional> const int MAXn = 5e6 + 5; int read() { int w = 0, r = 0; char ch = getchar(); while (ch < '0' || ch >'9')w |= ch == '-', ch = getchar(); while (ch >= '0' && c

Azxz0_0的博客 213

RISC-V内核移植实战:从零开始手把手实现RT-Thread上下文切换(附GD32VF103代码解析)

本文详细解析了在RISC-V架构上移植RT-Thread实时操作系统的核心步骤,重点聚焦于上下文切换机制的实现。通过对比ARM Cortex-M与RISC-V在中断处理和寄存器管理上的关键差异,并以GD32VF103开发板为例,手把手指导开发者完成libcpu抽象层适配、线程栈初始化以及三种上下文切换方式的代码编写与调试,为嵌入式开发者从ARM转向RISC-V平台提供了实战指南。

fern8的博客 739

【朝花夕拾】Handler篇

前言 转载请声明,转自【https://www.cnblogs.com/andy-songwei/p/9178735.html】,谢谢! 如果您的app中没有使用过Handler,那您一定是写了个假app;如果您笔试题中没有遇到Handler相关的题目,那您可能做了份假笔试题;如果您面试中没被技术官问到Handler的问题,那您也许碰到了个假面试……因为...

aw1070的博客 160

Cube生成定时器2触发双ADC同步采集并用DMA传输

前言 用cube生成一个用定时器触发ADC1,ADC2同步采集的程序,单片机选择的是STM32L476RGT6,用定时器2进行ADC采集触发,更改定时器2的定时周期便可以更改ADC的采样周期,ADC1和ADC2使用同步规则模式,并用DMA进行数据的传输。 STM32的ADC采样完成总共需要的时间是 ADC完成采样时间=采样周期+12个转换周期 举个例子,假如ADC的时钟是15MHz,采样周期是3个周期,3个采样周期加上12个转换周期,一共是15个周期,因为时钟是15MHz,所以完成一次ADC转换总共需要的时

一行代码的博客 4513

从0开始学GEE python——Google Earth Engine (GEE) 和 geemap 库来获取 Sentinel-2 卫星影像,并将其可视化

这段代码的目的是从 Sentinel-2 卫星影像中获取特定地点的影像,并将其可视化在地图上。通过设置合适的波段和可视化参数,用户可以清晰地查看该地区的卫星影像。

此星光明博客 1167

Java朝花夕拾-非阻塞队列之ConcurrentLinkedQueue

ConcurrentLinkedQueue非阻塞队列 采用先进先出的规则。采用链表实现,由头节点和尾节点组成当插入元素时,不会加锁,因此不会阻塞,当时会有一个死循环,直到插入成功,遍历链表,找到队尾,将元素插入采用cas算法 public boolean offer(E e) { if (e == null) throw ne...

aaabc1112345的博客 134

从AI画稿到3D虚拟时装:Illustrator与Substance 3D的服装设计工作流

本文旨在解决传统服装与纺织品设计师在产品开发流程中,面临的“2D印花图案无法直观预见3D上身效果”、“物理打样成本高昂且周期漫长”的核心痛点。我们将介绍一套纯数字化的3D可视化工作流,核心是利用 Adobe Illustrator 进行矢量印花图案创作,通过 Adobe Substance 3D Sampler 将其转化为逼真的PBR(基于物理渲染)布料材质,并最终在 Adobe Substance 3D Stager 中,将该材质应用于3D服装模型,渲染出照片级的虚拟样衣。本指南将帮助设计师以极低的成本和

Kingsdesigner的博客 1398

Java朝花夕拾-阻塞队列

BlockingQueue 是java.util.current下主要用来控制线程同步的工具,阻塞型队列,有四种实现类:1,ArrayBlockingQueue 大小规定,先进先出,采用数组实现2,LinkedBlockingQueue 大小不确定,先进先出,采用链表实现3,PriorityBlockingQueue 自然排序,或者是构造函数的Compara...

aaabc1112345的博客 195

普冉PY32F002B ADC内部参考电压VREFINT的误差补偿与低功耗优化实践

本文详细介绍了普冉PY32F002B单片机在锂电池供电场景下ADC内部参考电压VREFINT的误差补偿与低功耗优化实践。通过分析GPIO配置、分压电阻匹配、采样时间设置等硬件设计要点,结合实时测量VREFINT电压值和软件补偿算法,有效提升了ADC测量精度至5mV以内,并实现了分压电路功耗控制与采样频率优化,为低成本消费电子项目提供了完整的解决方案。

846

大数据在电力行业的应用案例解析 -【电力技术】(十)电力数字化运营与大数据精准服务体系建设

电力数字化运营,是大数据在电力行业从技术场景走向业务价值的最终落点。它以数据为纽带,将用户、设备、服务、收益、风险全部纳入统一闭环,实现从 “管好电” 向 “运营好能源资产” 升级。在新型电力系统与市场化改革双重驱动下,谁能用好数据、建好闭环、做好运营,谁就能在服务、成本、效益、安全上建立长期优势。

getusushu的博客 69

【朝花夕拾】Android跨进程通信总结篇

前言         原文:https://www.cnblogs.com/andy-songwei/p/10256379.html         只要是面试高级工程师岗位,Android跨进程通信就是最受面试官青睐的知识点之一。Android系统的运行由大量相互独立的进程相互协助来完成的,所以Android进程间通信问题,是做好Android开发高级工程师必须要跨过的一道坎。但是,我们是否...

宋者为王 508

[Dify 实战] 如何在内网环境部署 Dify 应用:彻底离线的企业级方案解析

企业内网环境如何离线部署Dify?本文提供详细教程:Dify作为开源AI平台,支持完全离线部署,无需外网访问。文中介绍两种部署方式:推荐使用Docker一键部署,也可选择源码安装定制化方案。重点讲解内网模型配置(支持Ollama/GPT-OSS等)、知识库存储(MinIO/PostgreSQL)及内网代理设置,并给出常见问题排查方法。该方案适用于金融、政府等对数据安全要求高的场景,确保敏感数据不泄露,实现完全本地化的AI应用闭环。

技术小甜甜:传播可落地技术,帮助个人和企业降低解决真实场景问题的成本 453

朝花夕拾3-使用ELK系统管理日志

使用ELK系统管理日志

Robert19831218的博客 1917

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

朝花夕拾-4-shell

引言shell,我们经常会用到,以其强大的功能,会帮助我们解决很多棘手的问题。最近遇到一个问题,要跑很多case,如果串行的执行,需要很久。能不能让他们并行起来,但又不能所有case都并行运行呢?,因为所有case同时运行,机器会挂掉的。1,方式1比较直接的一种方式是,维护两个文件队列(*.start和*.stop)分别记录所有case的运行状态,然后根据并发数量来获取和分配资源。代码如下:mul

Rill的专栏 3875

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

【C++】朝花夕拾——中缀转后缀

对于简单的四则运算而言,后缀表达式可以通过使用栈(stack)快速算出结果 ==================================我是分割线==================================== 后缀的定义: e.g. 2 + 3 -> 2 3 + 2 + 3 * 4 -> 2 3 4 * + 应用栈来计算后缀表达式: ...

weixin_30872733的博客 174

pscad IEEE标准系统搭建说明

pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。

【朝花夕拾】RT10XX SDK TDM的实现

最近遇到网友在使用RT1020 SDK SAI代码实现TDM模式的时候,发现要么出现时钟问题,要么出现data数据线blocking的问题。TDM的实现主要是调用官方底层API SAI_GetTDMConfig,但是同样的情况,DMA代码工程能够成功发出TDM信号,问题是时钟不准确;终端代码工程TDM的SYNC能发成功,但是数据信号线并无数据。本文就此问题展开讨论分析,并在NXP MIMXRT1020-EVK开发板上,测试TDM, 16kHZ采样率,16bit,2通道,并提供解决方案。

zhoujing优快云的博客 1328

【朝花夕拾】Android性能篇之(七)Android跨进程通信篇

前言 原文:https://www.cnblogs.com/andy-songwei/p/10256379.html 只要是面试高级工程师岗位,Android跨进程通信就是最受面试官青睐的知识点之一。Android系统的运行由大量相互独立的进程相互协助来完成的,所以Android进程间通信问题,是做好Android开发高级...

weixin_34346099的博客 337

朝花夕拾 - 8月离职 & 9月规划

好像,有一个月没有发公众号,没有接触前端工作相关的东西了,今天谈谈 jsliang 7 月底离职、8 月休息,到今天 9月1日,这一个月的感想。简单来说:吹吹水,聊聊天一 8 月做了啥 ...

weixin_41806099的博客 468

Three.js+WebSocket+大模型:为AI聊天角色打造可交互3D形象

在人工智能应用从文本交互走向沉浸式体验的进程中,3D虚拟角色成为连接用户与数字世界的重要载体。其背后涉及大语言模型的内容生成、WebSocket的实时双向通信,以及Three.js的前端渲染三大核心技术。大语言模型负责理解用户意图并产出自然回复,WebSocket保障消息的低延迟推送,Three.js则基于GLTF/GLB模型在浏览器中呈现立体角色,并通过材质与动作响应对话状态。这一技术组合可广泛应用于虚拟陪伴、数字人直播、智能客服、游戏NPC等场景,帮助开发者构建具备“在场感”的交互体验。文章从整体架构出

weixin_34176694的博客 314

【朝花夕拾】Android性能篇之(七)Android跨进程通信篇 ...

前言 原文:https://www.cnblogs.com/andy-songwei/p/10256379.html 只要是面试高级工程师岗位,Android跨进程通信就是最受面试官青睐的知识点之一。Android系统的运行由大量相互独立的进程相互协助来完成的,所以Android进程间通信问题,是做好Android开发高级...

测试0901-1 361

c++ 优先队列 priority_queue 的初学

朝花夕拾,重新学 c++ 的库函数了,优先队列: 基本数据类型 定义 priority_queue 只需要写上头文件 #include<queue> 即可 定义,除了最基本的 priority_queue<int>qu ,还可以定义队列的优先级顺序: priority_queue<int, vector<int>, greater<int>> qu1;// 表示数字小的优先级高 priority_queue<int, vector&lt

weixin_45962741的博客 206

朝花夕拾——finally/final/finalize拨云雾见青天

Java编程中,经常会使用到异常处理,而finally看似的是try/catch后对逻辑处理的完善,其实里面却存在很多隐晦的陷阱;final常见于变量修饰,那么你在内部类中也见过吧;finalize作为GC回收对象前的一道门,什么时候执行,执行效果又是怎样,有时看看又忘了。下面从经典的例子....

「Android之禅」公众号博主,和你分享有价值有思考的技术文章 1581
上一篇: 朝花夕拾 · 数据结构 | 链表篇
下一篇: 朝花夕拾 · 数据结构 | 二叉树篇
剑指offer.
博客等级 码龄3年 15粉丝 38原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值