栈和队列(栈的详解)

news2024/11/28 10:33:15

目录

  • 栈的实现
  • 栈的结构
  • 栈的初始化
  • 栈的销毁
  • 入栈
  • 出栈
  • 获取栈顶元素
  • 栈的判空
  • 获取栈的数据个数
  • test.c(测试)
  • 总结

栈也是线性表(在逻辑上是顺序存储)的一种,栈只允许其在固定的一端进行插入和删除,栈中的元素遵循后进先出(先进后出)
出入数据可以比喻成羽毛球和电梯
栈顶:可以进行插入和删除数据,入数据和出数据都在栈顶
栈底:不允许插入和删除数据

栈的实现

栈可以用数组或单链表,双向链表实现
双向链表要多维护一个指针
单链表和数组实现栈都比较好,但是数组的缓存利用率比较高

缓存利用率(命中率)是什么?
如果第一个数据在缓存中,缓存命中,直接访问
不在缓存中,叫不命中,要把数据从内存中加载到缓存中,再访问
简单来说是缓存命中的多少

数组在内存中是连续存储的,所以提取数组的缓存利用率比较高
1.命中第一个数据,后面的数据就会连续命中
2.第一个数据不命中,把它加载到缓存中,后面的一系列数据就都会加载到缓存中
比如你们去春游,老师叫来一个大巴车把A同学带来了,司机不只把A同学带来,还把后面的所有同学都带来了

链表
链表是由一个一个指针链接在一起的,拉到缓存中一次也只能来一个数据,效率比较低,缓存命中率不高
还有一个原因就是拉一个数据,可能把后面无关的数据也拉进来,会造成缓存污染,把之前有用的数据给挤出去,链表物理上不是连续存储的

所以我们使用数组来实现栈
在这里插入图片描述

栈的结构

//静态栈不太实现,都是实现的动态栈
//用数组为基础实现动态栈
typedef int STDataType;
typedef struct Stack
{
    STDataType* a;//指向数组的指针
	int top;//标识栈顶
	int capacity;//栈的大小
}Stack;

栈的初始化

//栈的初始化
void StackInit(Stack* pst)
{
	assert(pst);

	pst->a = NULL;
	pst->top = 0;
	//指向栈顶的下一个数据,可以表示元素的多少(size)

	//s->top = -1;
	//指向栈顶数据,可以表示元素的下标
	pst->capacity = 0;
}

top有两种情况

  • top可以指向栈顶,可以这样理解,top是指向数组下标
  • 先top++,再插入数据
    在这里插入图片描述
  • top还可以指向栈顶的下一个数据,top可以理解为size,数据的多少
  • 先插入数据,再top++
    在这里插入图片描述
    易错点:top指向栈顶元素,又top初始化为0,为0是指向栈顶的下一个元素
    应该top初始化为-1

栈的销毁

//栈的销毁
void StackDestroy(Stack* pst)
{
	assert(pst);
    //pst指向栈的结构体为空就找不到数组了
	free(pst->a);
	pst->a = NULL;
	pst->top = pst->capacity = 0;
}

入栈

//入栈
void StackPush(Stack* pst, STDataType x)
{
	assert(pst);

	//扩容
	if (pst->capacity == pst->top)
	{
		int newcapacity = pst->capacity == 0 ? 4 : pst->capacity * 2;
		//->的优先级大于*
		STDataType* tmp = (STDataType*)realloc(pst->a,(sizeof(STDataType))
		* newcapacity);
		//为数组realloc一个连续的空间
		if (tmp == NULL)
		{
			perror("StackPush:realloc");
			return;
		}
		//开辟成功一个空间
		pst->capacity = newcapacity;
		//把新空间给它
		pst->a = tmp;
		//新数组给它
	}
	pst->a[pst->top] = x;
	//插入x
	pst->top++;
	//top增加1
}

判满(判断空间是否满了):
1.top指向栈顶的下一个数据(size),top == capacity
2.top指向栈顶(下标),top+1 == capacity

出栈

//出栈
void StackPop(Stack* pst)
{
	assert(pst);
	assert(pst->top > 0);
	//top指向0的时候是没有元素的

	pst->top--;
	//元素少一个
}

在这里插入图片描述

获取栈顶元素

//获取栈顶元素
STDataType STTop(Stack* pst)
{
	assert(pst);
	assert(pst->top > 0);
	//取的最后一个元素是0下标的元素,取0时下标为-1是越界访问的

	return pst->a[pst->top - 1];
	//返回最后一个数据
}

栈的判空

//栈的判空
bool STEmpty(Stack* pst)
{
	assert(pst);

	return pst->top == 0;
	//为真时top为0,返回true,数组中没有元素
	//为假时top为非0,返回false,数组中还有元素
}

获取栈的数据个数

//获取栈的数据个数
int STSize(Stack* pst)
{
	assert(pst);

	return pst->top;
	//top(代表数据个数)
}

test.c(测试)

 #define _CRT_SECURE_NO_WARNINGS

#include"Stack.h"

//int main()
//{
//	Stack sl;
//	StackInit(&sl);
//	StackPush(&sl,1);
//	StackPush(&sl, 2);
//	StackPush(&sl, 3);
//	StackPush(&sl, 4);
//	StackPop(&sl);
//	StackPop(&sl);
//	StackPop(&sl);
//	StackPop(&sl);
//	printf("%d", STTop(&sl));
//	StackDestroy(&sl);
//
//	return 0;
//}

int main()
{
	Stack sl;
	//入栈: 1,2,3,4 出栈: 4,3,2,1 / 1,2,3,4 有多种可能
	// 队列的入栈是1,2,3,4 出栈一定是:4,3,2,1
	//创建一个栈的变量
	StackInit(&sl);

	StackPush(&sl,1);
	//printf("%d", STTop(&sl));

	StackPush(&sl, 2);
	printf("%d ", STTop(&sl));
	StackPop(&sl);

	StackPush(&sl, 3);
	//printf("%d", STTop(&sl));

	StackPush(&sl, 4);
	//printf("%d", STTop(&sl));


	while (!STEmpty(&sl))//判断栈是不是空
	{
	   //有数据返回false,!(取反)真,获取栈顶数据,弹出栈顶数据
	   //没数据返回true,!(取反)假,top == 0,退出循环,空栈
		printf("%d ", STTop(&sl));
		StackPop(&sl);
	}
	//2 4 3 1

	StackDestroy(&sl);

	return 0;
}

总结

栈做题关键是找最近的匹配(东西),比如leetcode中括号的匹配,
{ [ ( ) ] }
最后祝大家题题AC

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

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

相关文章

Linux-笔记 开发板Uboot命令使用

将之前自学的知识整理了一下笔记,以便回忆 信息查询命令 1、help/?:查看所支持命令 > ? md md - memory displayUsage: md [.b, .w, .l] address [# of objects]2、bdinfo:查询板子信息 > bdinfo arch_number 0x00000000 boot_p…

多商户Docker Supervisor进程管理器部署

Dockerfile 根目录下没有Dockerfile的可以复制下面的命令 # 使用基础镜像 FROM leekay0218/crmeb-mer## 复制代码 ## 在本地调试注释掉,使用映射把文件映射进去 #ADD ./ /var/www# 设置工作目录 WORKDIR /var/www# 设置时区为上海 ENV TZAsia/Shanghai RUN ln -sn…

对数据进行标准化和归一化

数据的形式:保存在CSV中,第一列为姓名,第二列之后为特征。 标准化 输入文件的路径,设置保存转化后的文件路径 import pandas as pd from sklearn.preprocessing import StandardScaler# 读取CSV文件 data pd.read_csv(rC:\User…

开发时如何快速分析代码和生成测试方法(Baidu Comate插件帮我一键分析)

目录 前言 Baidu Comate智能编码助手简介 安装教程 使用RabbitMQ一个绑定队列方法进行演示 进行测试现有功能 使用感觉 测试结果 前言 因为在开发代码的时候,发现有很多都是废话也不是很想写注释 的,毕竟程序员最讨厌的两件事情,一…

Hikyuu高性能量化研究框架助力探索

Hikyuu Quant Framework 是一款基于C/Python的开源量化交易分析与研究工具,主要用于A股市场的交易策略分析与回测,目前不支持期货等,需要自行改造。 Hikyuu的目标 Hikyuu的最初目的是为了快速对A股全市场股票进行策略回测和验证&#xff0c…

windows窗口消息队列与消息过程处理函数

在Windows窗口应用程序中,消息队列和窗口过程函数是实现消息驱动机制的核心组件。 消息队列(Message Queue): 消息队列是用于存储窗口消息的缓冲区。当用户与应用程序交互时,系统会将生成的消息插入到消息队列中&…

C++11:常用语法汇总

目录 🍁统一的列表初始化 { }initializer_list 🍁decltype 推导表达式类型🍁可变参数模板解析可变参数包方法一方法二 🍁lambda 表达式捕捉列表的使用运用场景举例lambda表达式 与 函数对象 🍁统一的列表初始化 { } 在…

电商购物系统首页的商品分类

如上图对商品的一个分类实际上和省市区的分类十分类似 , 都是通过自关联的方法来实现 , 但是这里不同的是 , 涉及到外键来获取数据 首先让我们来看一下最后通过后端返回数据的形式是什么样子的 """{1:{channels:[{id:1 , name:手机 , url:},{}{}],sub_cats:[{…

苍穹外卖面试总结

项目介绍 我完成了一个外卖项目,名叫苍穹外卖,是跟着黑马程序员的课程来自己动手写的。 项目基本实现了外卖客户端、商家端的后端完整业务。 商家端分为员工管理、文件上传、菜品管理、分类管理、套餐管理、店铺营业状态、订单下单派送等的管理、数据…

考研数学|强化阶段怎么刷《660》《880》《1000》?

强化阶段想要刷好题,首先要选一本适合自己的题集! 一般在强化阶段,大家用多个最多的题集就是660题,880题还有1000题 660题的特点是只训练客观题,虽然题目的质量很高,但是训练面还是比较窄 880题是综合训…

【SpringBoot】 什么是springboot(二)?springboot操作mybatisPlus、swagger、thymeleaf模板

文章目录 SpringBoot第三章1、整合mybatsPlus1-234-67-10问题2、整合pageHelper分页3、MP代码生成器1、编写yml文件2、导入依赖3、创建mp代码生成器4、生成代码5、编写配置类扫描mapper类6、编写控制器类4、swagger1、什么是swagger2、作用3、发展历程4、一个简单的swagger项目…

ADC模-数转换原理与实现

1. 今日摸鱼计划 今天来学习一下ADC的原理,然后把ADC给实现 ADC芯片:ADC128S102 视频: 18A_基于SPI接口的ADC芯片功能和接口时序介绍_哔哩哔哩_bilibili 18B_使用线性序列机思路分析SPI接口的ADC芯片接口时序_哔哩哔哩_bilibili 18C_基于线性序列机的S…

MFC的句柄概念以及句柄类型

在MFC(Microsoft Foundation Class)桌面应用程序中,窗口是通过句柄(Handle)来进行管理和操作的。 句柄是一个标识符,用于唯一标识和引用窗口、控件、设备上下文等对象。在MFC桌面应用程序中,常…

mac -- Navicat premium for mac 12的安装破解过程

下载准备好dmg文件,接下来开始安装破解。 镜像在官网下载,复制打开链接可以直接下载,可以直接下载中文版,不需要汉化:(下载包不能用,留言我发给你) 英文64位: http://dow…

【0003day】VOSviewer分析

这个软件也可以用知网,也可以用web of science。 首先,需要创建数据。这个数据如何创建,需要参考对应的教程。(本文以web of science为平台来做分析。) 首先,创建对应的数据库。 一直下一步 让后选择完…

Linux重定向及缓冲区理解

重定向: 在上一期虚拟文件系统中讲到了每个进程在打开后,都会默认打开3个文件,如下: stdin 标准输入(键盘) 文件描述符:0 stdout 标准输出(显示器)文件描述符&a…

Boss让你设计架构图,你懵逼了,解救你的参考图来啦。

架构图是指用于描述系统或软件的结构和组成部分之间关系的图形表示。 它是一种高层次的图示,用于展示系统的组件、模块、接口和数据流等,以及它们之间的相互作用和依赖关系。架构图通常被用于可视化系统的整体设计和组织结构,帮助人们理解系…

分享10类正规的网上赚钱平台,让你摆脱单一收入

在这个互联网飞速发展的时代,你是否还在为单一的收入来源而焦虑?别担心,今天带你解锁10种网上赚钱的新姿势,让你的收入不再单一,甚至可能翻倍! 1. 文库类:知识的变现 你知道吗?你的…

利用IP地址查询解决被“薅羊毛”的方法

在互联网时代,随着各种网络诈骗手段的不断更新和演变,“薅羊毛”成为了一种常见的网络犯罪行为。其中,利用查询IP地址进行欺诈活动已经成为一种普遍的手段。当个人或组织的IP地址被不法分子查询后,可能会面临虚假注册、盗取个人信…

三. TensorRT基础入门-剖析ONNX架构并理解ProtoBuf

目录 前言0. 简述1. 执行一下我们的python程序2. ONNX是什么?3. onnx中的各类Proto3.1 理解onnx中的ValueInfoProto3.2 理解onnx中的TensorProto3.3 理解onnx中的NodeProto3.4 理解onnx中的AttributeProto3.5 理解onnx中的GraphProto3.6 理解onnx中的ModelProto 4. …