栈和队列修炼指南(基本操作+OJ练习)

news2024/11/25 13:48:13

栈和队列修炼指南

1. 栈

1. 1 概念及结构

  • 栈:是一种特殊的线性表,其只允许在固定的一端进行插入和删除元素的操作。进行数据插入和删除操作的一端称为栈顶,另一端为栈底

  • 栈中的数据元素遵守后进先出原则(LIFO)原则

  • 压栈:栈的插入操作称为进栈/压栈/入栈,其位置在栈顶

  • 出栈:栈的删除操作称为出栈,其位置也在栈顶

1.2 分类(数组栈和链式栈)

数组栈(推荐方式,因为在数组尾插代价更小)

链式栈:相较数组栈无优势,且一般将链表尾作为栈底,链表头作为栈顶(单链表情况下)

1.3 数组栈

1.3.1 结构的定义

typedef int STElemType;
typedef struct Stack
{
	STElemType *data;	//动态栈
	int top;
	int capacity;
}ST;

1.3.2 初始化

void StackInit(ST *pt)
{
	pt->data = (SElemType *)malloc(N*sizeof(SElemTyp  e));
   	if (!pt->data)
   	{
   		perror("malloc");
   		exit(1);
	}
    
	pt->capacity = N;	//N表示初始的最大容量
	pt->top = 0;	//此时top指向的是栈顶元素的下一个位置,也可以定义为pt->top=-1,这样,top就是指向栈顶元素
} 

1.3.3 销毁

void StackDestroy(ST *pt)
{
	free(pt->data);
	pt->top=pt->capacity=0;
} 

1.3.4 判断栈是否为空

bool StackEmpty(ST *pt)
{
	return pt->top==0; 	//若为真即栈为空,则返回1,否则返回0
} 

1.3.5入栈

void StackPush(ST *pt,SElemType x)
{
	if(pt->top==pt->capacity)			//如果容量已满
	{
		pt->capacity *= 2;		//将容量扩为原来的两倍
		ST* temp = realloc(pt->data, pt->capacity*sizeof(SElemType));
		if(!temp)
		{
			perror("malloc");
			exit(1);
		}
        
        pt->data = temp;
	}
    
    //入栈
	pt->data[pt->top]=x;
	pt->top++;
}

1.3.6 出栈

void StackPop(ST *pt) 
{
	assert(!stackEmpty(pt));	//栈不能为空
    
    //出栈
	pt->top--;
}

1.3.7 返回栈顶元素

SElemType StackTop(ST *pt)
{
	assert(!stackEmpty(pt));	//栈不能为空
    
	return pt->data[pt->top-1]; 
} 

1.3.8 返回栈的元素个数

int StackSize(ST *pt)
{
	return pt->top;
} 

1.3.9 将栈的元素全部取出

void StackPrint(ST *pt)
{
	assert(!stackEmpty(pt));	//栈不能为空
    
	while(!StackEmpty(pt))
	{
		printf("%d ",StackTop(pt));	//遵循先入后出原则,从上往下取
		pt->top--;
	}
} 

1.4 练习

学习完栈的基本概念和相关操作后,你可以利用栈的特性做下面的OJ题:

有效括号序列👉题目解析

逆波兰表达式求值👉题目解析

删除字符串中的所有相邻重复项👉题目解析

包含min函数的栈👉题目解析


2. 队列

2.1 概念及结构

  • 队列:只允许在一端进行入数据操作,在另一端进行删除数据操作的特殊线性表
  • 遵循先进先出的原则FIFO
  • 入队列:进行插入操作的一段叫做队尾
  • 出队列:进行删除操作的一段叫做队头
    在这里插入图片描述

2.2. 分类(数组队列和链队列)

数组队列:由于出队列出的是队头元素,因此数组队列出数据的效率低下,不推荐使用

链队列:入和出数据的效率都很高,是队列常用的表示法

2.3 链队列

2.3.1 结构的定义

typedef int QDataType;	//存储的数据类型

typedef struct QueueNode	//链队列的节点
{
	struct QueueNode *next;
	QDataType data;
}QueueNode;

typedef struct Queue	//定义存放指向队头,队尾指针的结构体
{
	QueueNode *head;	//指向队头
	QueueNode *tail;	//指向队尾
}Queue;

2.3.2 初始化

void QueueInit(Queue *pq)
{
	assert(pq);
	pq->head = NULL;
	pq->tail = NULL;
}

2.3.3 销毁

void QueueDestroy(Queue *pq)
{
	QueueNode *cur = pq->head;	//定义临时变量
	while (cur)
	{  
		pq->head = pq->head->next;	//链表下滑
		free(cur);		//释放空间
		cur = pq->head;	//更新临时变量
	} 
	pq->tail = NULL;	//空间释放完毕后head已经为空,但tail成为了野指针,所以要置空
}

2.3.4 判断队列是否为空

bool QueueEmpty(Queue *pq) 
{
	assert(pq);
    
	return pq->head == NULL;
}

2.3.4 入队

void QueuePush(Queue *pq,QDataType x)
{
	assert(pq);
    
	QueueNode *newnode=(QueueNode *)malloc(sizeof(QueueNode));		//创建新节点
    if (NULL == newNode)
    {
        perror("malloc");
        exit(1);
	}
	newnode->data=x;
	newnode->next=NULL;
    
	if(QueueEmpty(pq))	//如果队列为空
	{
		pq->head=newnode;	//使队头、队尾指针同时指向新节点
		pq->tail=newnode;
	}
	else
	{
		pq->tail->next=newnode;	//使队尾指针的指向下一个节点的指针指向新节点
		pq->tail=newnode;	//更新队尾指针
	}
}

2.3.5 出队

void QueuePop(Queue *pq) 
{
	assert(pq);
	assert(!QueueEmpty(pq));	//队列不能为空
    
	QueueNode *cur=pq->head;	//定义临时变量保存队头指针
	pq->head=pq->head->next;	//使队头指针指向下一个节点
	free(cur);		//释放原来的队头
    
	if(pq->head==NULL)
		pq->tail=NULL;	//如果节点已经全部出队,则要将队尾指针置空,防止形成野指针
}

2.3.6 返回队头/队尾数据域

//返回队头元素
QDataType QueueFront(Queue *pq)	 
{
	assert(pq);
	assert(!QueueEmpty(pq));
    
	return pq->head->data;
}

//返回队尾元素 
QDataType QueueBack(Queue *pq)
{
    assert(pq);
    assert(!QueueEmpty(pq));

    return pq->tail->data;
}

2.3.7 返回队列元素个数

int QueueSize(Queue *pq)
{
	QueueNode *cur=pq->head;
	int size=0;
    
	while(cur)
	{
		size++;
		cur=cur->next;
	}
    
	return size;
}
//也可以在队列结构体中增加size变量,每入队一个size就加一

2.4 练习

队列常常被用来对一些复杂数据结构的广度优先遍历,但由于目前还未学习,故不作深入讨论

除了这种最基本的只能从队尾插入数据,从队头删除数据的队列外,其实还有循环队列、双端队列、单调队列等许多复杂但功能强大的队列结构,如果小伙伴们感兴趣,也可以看看:

👉循环队列

👉双端队列 & 单调队列

如果小伙伴们愿意挑战,也可以做一做滑动窗口的最大值👉题目解析


3. 栈和队列的相互表示

这里拿两道OJ题来进行说明:

用两个栈表示队列👉题目解析

用两个队列表示栈👉题目解析

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

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

相关文章

【Git】—— git的配置

目录 (一)忽略特殊⽂件 (二)给命令配置别名 (一)忽略特殊⽂件 在⽇常开发中,我们有些⽂件不想或者不应该提交到远端,⽐如保存了数据库密码的配置⽂件,那怎么让Git知道呢…

为什么金鸣识别不做成离线版?

来百度APP畅享高清图片 在众多的用户咨询中,金鸣识别客服常常会被用户问及为何不做成离线版的问题,下面我就在这里跟大伙说说其中的原因吧。 离线版的OCR准确率相对于网络版可能会较低,主要有以下几个原因: 1. 数据量和模型更新…

WLRYJ-300型微流控芯片真空热压机

WLRYJ-300型微流控芯片真空热压机 关键词:微流控芯片,热压封合,LNP合成芯片 WLRYJ-300型微流控芯片真空热压机是一款应用于PMMA、PC、PP、COP、COC、BOPET、CBC、树脂(部分)、聚乙烯(部分)等硬质…

干货丨学完网络安全专业,我掌握了哪些技能?

andy Ng在我校完成网络防御与司法大专(Diploma in Network Defense and Forensic Countermeasures)之后,顺利升入我校的网络安全本科课程,目前她就职于一家金融机构并担任安全操作中心的分析专员。在进入我校就读之前,Sandy在建筑行业领域工作…

tsup打包如何更改outFileName

首先简单介绍一下,什么是tsup tsup是一个打包工具,类似的有rollup tsup的官网:https://tsup.egoist.dev/ tsup的优点:打包速度快,配置少,与ts兼容良好 安装 npm i tsup -D # Or Yarn yarn add tsup --…

决策规划仿真平台搭建

决策规划仿真平台搭建 自动驾驶决策规划算法第二章第一节 决策规划仿真平台搭建 这部分的主要难点在于多个软件的连通与适配,环境的搭建总是折磨人的,主要是 4 个软件,各软件版本如下 Visual Studio2017PreScan8.5.0CarSim2019.0MATLAB2019b…

【黑马头条之xxl-Job分布式任务调度】

本笔记内容为黑马头条项目的分布式任务调度热点文章部分 目录 一、今日内容 1、需求分析 2、实现思路 3、定时计算 4、定时任务框架-xxljob 二、分布式任务调度 1、什么是分布式任务调度 2、xxl-Job简介 3、XXL-Job-环境搭建 4、配置部署调度中心-docker安装 5、xx…

美团外卖红包入口在哪里找到如何免费领取美团外卖红包天天神券?

美团外卖红包免费领取入口在哪里找到? 关注「草柴」微信公众号,回复「美团外卖」就可以找到美团外卖红包免费领取入口,获得美团外卖节红包优惠券; 美团外卖节红包优惠券怎么使用享受优惠? 1、通过(上面&a…

2021年12月 C/C++(一级)真题解析#中国电子学会#全国青少年软件编程等级考试

第1题&#xff1a;输出整数部分 输入一个双精度浮点数f&#xff0c; 输出其整数部分。 时间限制&#xff1a;1000 内存限制&#xff1a;65536 输入 一个双精度浮点数f(0 < f < 100000000)。 输出 一个整数&#xff0c;表示浮点数的整数部分。 样例输入 3.8889 样例输出 3…

Vue.js2+Cesium1.103.0 八、动态光墙效果

Vue.js2Cesium1.103.0 八、动态光墙效果 Demo <template><divid"cesium-container"style"width: 100%; height: 100%;"/> </template><script> /* eslint-disable no-undef */ import /utils/dynamicWallMaterialProperty.js exp…

浅谈AI人工智能ChatGpt提升竞彩足球分析准确率最高的分析软件

随着科技的不断进步&#xff0c;人工智能正在扮演着越来越重要的角色。在体育领域&#xff0c;特别是足球竞猜中&#xff0c;AI人工智能ChatGpt正以其卓越的分析能力引起了广泛的关注。作为一款以大数据分析为基础的分析软件&#xff0c;AI人工智能ChatGpt不仅可以提供准确的数…

树莓派命令行运行调用音频文件的函数,不报错,没有声音解决办法

树莓派接上音频首先需要切换音频不是HDMI&#xff0c;然后可以双击运行wav文件可以播放&#xff0c;但是&#xff1a; 命令行直接运行wav文件报错&#xff1a; Playing WAVE twzc.wav : Signed 16 bit Little Endian, Rate 16000 Hz, Mono命令行运行main方法也是无法播放&am…

Linux学习————redis服务

目录 一、redis主从服务 一、redis主从服务概念 二、redis主从服务作用 三、缺点 四、主从复制流程 五、搭建主从服务 配置基础环境 下载epel源&#xff0c;下载redis​编辑 二、哨兵模式 一、概念 二、作用 三、缺点 四、结构 五、搭建 修改哨兵配置文件 启动服务…

骨传导耳机对耳朵有损害吗?最不伤耳的骨传导耳机

骨传导耳机对耳朵有损害吗&#xff1f; 骨传导是除了空气传导之外另一种很重要的听觉方式&#xff0c;它是通过骨骼进行传递声音的&#xff0c;利用骨头振动的原理&#xff0c;声音直接绕过耳膜等神经单元&#xff0c;声音直接传送到内部耳神经。 骨传导耳机的原理就是通过人体…

React 全栈体系(一)

第一章 React入门 一、React简介 1. 是什么&#xff1f; 是一个将数据渲染为HTML视图的开源JavaScript库。 2. 谁开发的&#xff1f; 由Facebook开源 3. 为什么要学&#xff1f; 原生JavaScript操作DOM繁琐&#xff0c;效率低&#xff08;DOM-API 操作 UI&#xff09; 使…

nvidia驱动更新导致驱动版本不匹配

关于nvidia驱动自动更新&#xff1a; 和这篇描述类似&#xff1a;https://blog.csdn.net/weixin_43568307/article/details/128187469 记得记录原先版本 sudo dpkg-reconfigure unattended-upgrades 关闭一下自动更新。 当前主机做好快照备份&#xff0c;重新安装之前的驱…

代码随想录算法训练营第53天|动态规划part11|123. 买卖股票的最佳时机 III、188.买卖股票的最佳时机IV

代码随想录算法训练营第53天&#xff5c;动态规划part11&#xff5c;123. 买卖股票的最佳时机 III、 188.买卖股票的最佳时机IV 123. 买卖股票的最佳时机 III 123. 买卖股票的最佳时机 III 思路&#xff1a; 相比买股票的最佳时机II&#xff0c;限制了买股票的次数&#xf…

高端百度地图开发1:自定义水滴头像(自定义标注覆盖物、Overlay覆盖类)

自定义水滴头像&自定义标注覆盖物 一、引入百度地图JSAPI库二、构建map容器1. CSS样式表2.HTML容器 三、核心代码1.百度地图API功能2.定义构造函数并继承Overlay3.初始化自定义覆盖物4.绘制覆盖物5.添加覆盖物 自定义标注覆盖物&#xff08;Custom Overlay&#xff09;是百…

面部表情识别4:C++实现表情识别(含源码,可实时检测)

面部表情识别4&#xff1a;C实现表情识别(含源码&#xff0c;可实时检测) 目录 面部表情识别4&#xff1a;C实现表情识别(含源码&#xff0c;可实时检测) 1.面部表情识别方法 2.人脸检测方法 3.面部表情识别模型(Python) &#xff08;1&#xff09; 面部表情识别模型的训练…

Astro 搭建博客系列:添加 giscus 评论系统

Astro 支持动态插入 script&#xff0c;所以为集成 giscus 提供了便利。我们需要探究两个问题&#xff1a; 选用什么作为 页面 -> discussion 的映射&#xff1f;如何做到动态切换主题&#xff1f; 我们的文章详情链接是 http://127.0.0.1:3000/posts/[post-title] 的形式&…