数据结构——栈和队列

【数据结构|C语言版】栈和队列 各位小伙伴大家好!上次小编给大家讲解了数据结构中的重要基础:算法效率和复杂度分析,接下来我们讲解一下栈和队列!【知识框架】以上就是小编对栈和队列的讲解。如果觉得小编讲的还可以,还请一键三连。互三必回!持续更新中~! 阅读详情

栈和队列是特殊的线性表,其特殊之处是他们的基本操作只是线性表操作的一个子集。下面分别介绍这两种数据结构。


1. 栈(Stack)


栈(Stack)是只能在表尾进行插入或删除的线性表,是后进先出(LIFO)的线性表。

跟线性表相似,他的存储结构也包括顺序和链式两种。

顺序栈的定义及初始化如下:

//顺序栈
#define INIT_SIZE 100
#define INCREMENT 10

typedef struct {
	ElemType *base; //栈底指针
	ElemType *top;  //栈顶指针
	int stacksize;	//目前已分配的空间
}SqStack;

int InitStack(SqStack *s) {
	s.base = (ElemType *)malloc(INIT_SIZE * sizeof(ElemType));
	if(s.base == NULL) return -1;
	s.top = s.base;
	s.stacksize = INIT_SIZE;
	return 1;
}

当栈满时添加内存分配:

int isFull(SqStack *s){
	if(s.top - s.base == s.stacksize)
		s.base = (ElemType *) realloc (s, (s.stacksize+INCREMENT) * sizeof(ElemType));
	if(s.base == NULL) return -1;
	s.stacksize += INCREMENT;
	return 1;
}

插入时s.top+1, 删除时s.top-1。


栈的链式结构及基本操作如下:

/*
  对栈实现初始化(链式结构),插入栈顶元素,删除栈顶元素,遍历栈,清空栈等基本操作
  */
 #include <stdio.h>
 #include <malloc.h>
 #include <stdlib.h>
 
 #define true 1
 #define false 0
 
 
 typedef struct Node
 {
     int data;
     struct Node *pNext;
 }NODE, *PNODE;
 
 typedef struct Stack
 {
     PNODE pTop;
     PNODE pBottom;
 }STACK, *PSTACK;
 
 void init(PSTACK pS);
 void push(PSTACK pS, int val);
 void traverse(PSTACK pS);
 int pop(PSTACK pS , int *val);
 void clear(PSTACK pS);
 int empty(PSTACK pS);
 
 int main(void)
 {
     STACK S ;
     int val;
     int i;
     
     init(&S);
     
     push(&S,1);
     push(&S,2);
     push(&S,3);
     push(&S,4);
     push(&S,5);
     push(&S,6);
 
     traverse(&S);
     
     if(pop(&S ,&val))
     {
         printf("遍历成功,出栈元素为%d\n",val);
     }
     else
     {
         printf("出栈失败!\n");
     }
     traverse(&S);
 
     clear(&S);
     
     traverse(&S);
     
     return 0 ;
 }
 
 //栈的初始化
 void init(PSTACK pS)
 {
     pS -> pTop = (PNODE)malloc(sizeof(NODE));
     
     if(NULL == pS -> pTop)
     {
         printf("动态内存分配失败!");
         exit(-1);
     }
     else
     {
         pS -> pBottom = pS -> pTop;
         pS -> pTop -> pNext = NULL;
     }
     
     return ;
 }
 
 //插入元素到栈顶
 void push(PSTACK pS , int val)
 {
     PNODE pNew = (PNODE)malloc(sizeof(NODE));
     
     pNew -> data = val;
     pNew -> pNext = pS -> pTop;
     pS -> pTop = pNew;
     
     return ;
 }
 
 //遍历栈S
 void traverse(PSTACK pS)
 {
     PNODE p = pS -> pTop;
     
     printf("栈内元素为:");
     while(p != pS -> pBottom)
     {
         printf("%d\t", p -> data);
         p = p -> pNext;
     }
     
     printf("\n");
     return ;
 }
 
 //判断栈是否为空
 int empty(PSTACK pS)
 {
     if(pS -> pTop == pS -> pBottom)
     {
         return true;
     }
     else
         return false;
 }
 
 //删除栈顶元素并将其值赋给*val
 int pop(PSTACK pS , int *val)
 {
     if(empty(pS))
     {
         return false;
     }
     else
     {
         PNODE r = pS -> pTop;
         *val = r -> data;
         pS -> pTop = r -> pNext;
         free(r);
         r = NULL;
     }
 }
 
 //清空栈S
 void clear(PSTACK pS)
 {
     if(empty(pS))
     {
         return;
     }
     else
     {
         PNODE p = pS -> pTop;
         PNODE q = NULL;
         
         while(p != pS -> pBottom)
         {
             q = p -> pNext;
             free(p);
             p = q ;
         }
         
         pS -> pTop = pS -> pBottom;
         
         return;
     }
 }

2 队列


队列(Queue)是在一段插入而在另一端删除的线性表,其数据元素满足先进先出(FIFO)的操作。

队列也包括链式和顺序结构,队列长度确定的情况下用顺序结构来表示。

用顺序结构表示队列时,由于插入和删除操作分别在不同端进行,因而可能出现插入端已位于预分配内存的末端,而实际内存中还有较多空间未使用。此时通过增加内存的方式来继续添加数据的方式会造成内存的浪费,故采用循环队列的方式来操作比较好。

循环队列的定义和基本操作如下:

/*
 循环队列的基本操作,初始化,入队,遍历,出队等操作
 */
 #include <stdio.h>
 #include <malloc.h>
 
 #define true 1
 #define false 0
 
 typedef struct Queue
 {
     int *pBase;     //定义数组pBase
     int front;
     int rear;
 }QUEUE;
 
 void init(QUEUE *pQ);
 int en_queue(QUEUE *pQ , int val);
 void traverse_queue(QUEUE *pQ);
 int out_queue(QUEUE *pQ , int *pVal);
 
 //循环队列的初始化
 void init(QUEUE *pQ)
 {
     pQ -> pBase = (int *)malloc(sizeof(int)*6);   //分配内存,数组长度为6
 
     pQ -> front = 0;                              
     pQ -> rear = 0;
 
     return;
 }
 
 //判断循环队列是否为满
 int full_queue(QUEUE *pQ)
 {
     if((pQ -> rear + 1) % 6 == pQ -> front)     
     {
         return true;
     }
     else
         return false;
 }
 
 //入队操作
 int en_queue(QUEUE *pQ , int val)
 {
     if(full_queue(pQ))
     {
         return false;
     }
     else
     {
         pQ -> pBase[pQ -> rear] = val;
         pQ -> rear = (pQ -> rear + 1) % 6;
 
         return true;
     }
 }
 
 
 //遍历循环队列
 void traverse_queue(QUEUE *pQ)
 {
     int i = pQ -> front;
 
     printf("遍历队列:");
     while(i != pQ -> rear)
     {
         printf("%d\t", pQ -> pBase[i]);
 
         i = (i + 1) % 6 ;
     }
 
     printf("\n");
 
     return;
 }
 
 //判断循环队列是否为空
 int empty_queue(QUEUE *pQ)
 {
     if(pQ -> front == pQ -> rear)
     {
         return true;
     }
     else
         return false;
 }
 
 //循环队列的出队操作
 int out_queue(QUEUE *pQ , int *pVal)
 {
     if(empty_queue(pQ))
     {
         return false;
     }
     else
     {
         *pVal = pQ -> pBase[pQ -> front];
         pQ -> front = (pQ -> front + 1) % 6;
 
         return true;
     }
 }




VL53L1X移植到STM32实战记录,使用软件IIC(附源代码) 序言 VL53L1X是一个很小又很优秀的测距传感器,它相比于上一代VL53L0X有着不小的提升,这次毕业设计打算将这个传感器用起来,就来移植了一下,遇到的坑怎么说还是有一些,故在此分享给大家。 开发环境 IDE:Keil V5 STM32CubeMX ,使用HAL库 具体操作 获取官方库并进行移植 这一步是移植的基础,首先从官方把API库下下来,并添加到IDE中: 适配硬件 这里由于不同的硬件平... 阅读详情

相关推荐

uniapp 使用摄像头 live-pusher (APP)

uniapp 中开发 app 时使用live-pusher踩过的坑

随身笔记 1万+

栈和队列的实现

栈是一种特殊的线性表,其结构的特性和内存中的栈是一样的,。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。压栈:栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。出栈:栈的删除操作叫做出栈。出数据也在栈顶。5先放入,再依次当如1和8,出栈时只能从8开始出栈,后进入的先出。

2301_77529683的博客 1141

linux下wayland协议修改键盘映射

linux下wayland协议,修改键盘映射,实验环境是Ubuntu24,其他wayland协议窗口应该也是可以的。

qq_15027967的博客 1068

【数据结构】栈(Stack)和队列(Queue)

栈和队列都是一种特殊的线性表。栈的特点:后进先出,只能在表尾进行插入和删除。队列的特点:先进先出,只能在表头删除,在表尾插入。它们都可以用顺序存储和链式存储的方式。栈常用顺序存储结构即数组的方式,因为数组的尾插尾删效率高,但可能会存在频繁开辟内存空间和内存空间浪费的问题。而栈的链式存储结构,解决了空间浪费的问题,但每个节点都存放一个指针域,也会存在一定的内存开销,并且在每次申请和释放节点的过程中也存在一定的时间开销。队列常用链式存储结构即链表的方式,

炸掉地球的博客 5539

【学习总结】飞跨电容三电平boost拓扑发波分析与matlab仿真

正常工作时,飞跨电容的电压大约控制在输出电压的一半,降低了开关器件的耐受电压。

晞子的技术札记 1万+

伺服电机三环控制实战:从参数整定到系统优化

本文以实战视角,深入解析伺服电机三环控制(位置环、速度环、电流环)的参数整定与系统优化全流程。文章摒弃复杂理论,通过生动的比喻和分步调试指南,详细阐述了从电流环快速响应、速度环平滑调节到位置环精准定位的调试方法,并提供了常见问题排查与进阶优化技巧,帮助工程师有效提升伺服系统性能与稳定性。

weixin_29201933的博客 246

【数据结构】栈和队列详细分析(全)

前言 栈和队列是两种重要的线性结构。从数据结构角度看,栈和队列也是线性表, 其特殊性在于栈和队列的基本操作是线性表操作的子集,它们是操作受限的线性表,因此,可称为限定性的数据结构。 栈的定义与特点 栈是限定仅在表尾进行插入或删除操作的线性表。 表尾称为栈顶,表头端称为栈底 。不含元素的空表称为空栈。栈的修改是按后进先出的原则进行的。 栈的操作 队列的定义与特点 和栈相反,队列是一种先进先出的线性表。它只允许在表的一端进行插入,而在另一端删除元素,允许插入的一端称为队尾,允许删除的一端则称为队头。 ...

码农研究僧的博客 1万+

RT-DETR改进策略【损失函数篇】| 2024 引进Focaler-IoU损失函数 加强边界框回归 (Focaler-DIoU、Focaler-GIoU、Focaler-CIoU等)

本文记录的是改进RT-DETR的损失函数,将其替换成。现有研究通过利用边界框之间的几何关系来提高回归性能,但忽略了困难样本和简单样本分布对边界框回归的影响。不同检测任务中困难样本和简单样本的分布不同,对于简单样本占主导的检测任务,关注简单样本的边界框回归有助于提高检测性能;对于困难样本比例较高的检测任务,需要关注困难样本的边界框回归。,提高检测器在不同检测任务中的性能。实现的。

Limiiiing的博客 1924

数据结构 —— 栈和队列的概念、结构及实现。

数据结构 —— 栈 和 队列 的概念、结构及实现。

wihkum 290

Python调用CANoe

我们可以创建CANoe应用程序对象,打开配置文件,启动模拟,发送和接收消息,并在完成后关闭CANoe应用程序。这使得我们能够使用Python自动化执行测试任务,并集成CANoe的功能到我们的Python应用程序中。CANoe是一款功能强大的汽车网络仿真和测试工具,它能够模拟和分析汽车网络通信,并提供丰富的测试功能。通过Python编程语言,我们可以方便地调用CANoe的API,实现自动化测试和集成CANoe的功能到我们的Python应用程序中。在CANoe中,我们可以为不同的汽车网络创建配置文件。

AzqLinux的博客 1288

英飞凌 AURIX TC3XX 系列单片机的链接文件

这篇介绍英飞凌 AURIX TC3XX 系列单片机的链接文件,主要是针对使用 SOTA 功能如何修改链接文件,完整地实现 SOTA 功能

大橙子的博客 4385

数据结构与算法 —— 表(栈、队列)

数据结构特性队列: FIFO 结构,适用于按顺序处理的任务。栈: LIFO 结构,适用于需要倒序处理的任务。实现方式两者都可以通过数组或链表来实现。队列需要两个指针(队头和队尾),而栈只需一个指针(栈顶)。应用场景队列通常用于调度、广度优先搜索等需要按顺序处理的任务。栈则常用于递归、表达式求值等需要倒序或回溯处理的任务。两者都是非常重要的基础数据结构,在计算机科学和编程中有广泛的应用。如有错误,欢迎批评指正。

weixin_71421536的博客 1034

【Docker】一招解决超时镜像超时报错:`ERROR: Get https://registry-1.docker.io/v2/`

Docker 镜像拉取超时或失败并不是 Docker 本身的缺陷,而是网络环境和默认配置在特定场景下的限制所导致的结果。通过本文的分析可以看到,问题的核心往往集中在三个方面:网络访问延迟、DNS 解析速度以及客户端默认超时时间。针对这些问题,最直接、有效的做法是使用国内镜像加速器,这不仅能够显著提升拉取速度,还能保证在企业内网或家庭网络中更加稳定

博客 1027

数据结构与算法——栈和队列

栈和队列是两种重要的线性结构,本篇文章详细总结了数据结构与算法中栈和队列的终点知识,并且结合代码片段实现其基本操作,干货满满,每一句话都是重点,希望能给更多的小伙伴在学习数据结构与算法时带来一定帮助...

小田是个程序员的博客欢迎你的到来呀~ 2万+

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

【数据结构】栈和队列

本文系统介绍了栈和队列两种基础数据结构。栈遵循"先进后出"原则,仅允许在固定端进行插入和删除操作;队列遵循"先进先出"原则,在一端插入,另一端删除。文章详细分析了双端队列和循环队列的实现原理,包括角标移动公式、有效长度计算等核心算法。同时比较了链表和数组两种实现方式的复杂度差异,并展示了Java集合框架中Stack类和Queue接口的具体使用方法。通过限制操作方式,任何线性结构都能实现栈或队列的特性,为程序设计提供了灵活的数据组织工具。

2503_92883549的博客 1181

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

[详解栈和队列]数据结构之栈与队列

✅作者简介:大家好,我是Philosophy7?让我们一起共同进步吧!🏆 📃个人主页:Philosophy7的csdn博客 🔥系列专栏: 👑哲学语录: 承认自己的无知,乃是开启智慧的大门 💖如果觉得博主的文章还不错的话,请点赞👍+收藏⭐️+留言📝支持一下博>主哦🤞 文章目录栈和队列1.物理结构和逻辑结构2.什么是栈2.1栈的基本操作3.什么是队列队列的基本操作小结 栈和队列 1.物理结构和逻辑结构 再了解栈和队列之前,我们要先知道什么是逻辑结构和物理结构。 逻辑结构: 按照逻辑结构划分:数据结.

Philosophy7的博客 4195

廖雪峰Python教程[完整版]

廖雪峰的python教程整理的,已经排好版了,而且还是完整的,适合小白

【数据结构】栈和队列详解

栈和队列详解!!!

2403_86779341的博客 1384

【数据结构】 栈和队列

数据结构中栈和队列的学习~

qq_56251766的博客 1180

数据结构—栈和队列

栈是一种只能在一端进行插入或删除操作的线性表。在表中允许进行插入、删除操作的一端称为栈顶。栈顶的当前位置是动态的,由一个称为栈顶指针的位置指示器来指示。表的另一端称为栈底。当栈中没有数据元素时称为空栈。栈的插入操作通常称为进栈或入栈,栈的删除操作通常称为退栈或出栈。栈的主要特点是"先进后出",即后进栈的元素先出栈。每次进栈的元素都放在原当前栈顶元素之前成为新的栈顶元素,每次出栈的元素,都是原当前栈顶元素。栈也成为后进先出表。

2303_80188300的博客 1850

数据结构 栈和队列

数据结构 栈和队列

双吉堡工程专业的一名27届Javaer。 2003
上一篇: 数据结构——线性表
下一篇: Linux中的批量操作和文件统计问题
ancient_wind
博客等级 码龄18年 14粉丝 22原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值