栈的实现与OJ括号匹配

news2024/11/29 0:44:59

今日备忘录: "不破不立. "

本文索引

  • 1. 前言
  • 2. 顺序表与链表的区别
  • 3. 什么是栈
  • 4. 栈的实现
  • 5. OJ括号匹配
  • 6. 总结

1. 前言

人总是在坍塌中重建, 有些东西必须摧毁, 才能迎来新生, 不管是那些消耗你的人, 还是令你感到焦虑的事情, 还是一份你觉得毫无意义并且又不喜欢的工作, 又或者是那个内心敏感的自己, 总之你害怕什么, 就要去面对什么, 你想要什么, 就要去靠近什么, 在声色名利中守住本性, 在世俗目光中信步前行, 大浪淘沙, 去伪存真, 破而后立, 否极泰来.

本文旨在探讨数据结构中栈的实现以及顺序表与链表区别总结.
更多精彩, 期待关注 主页: 酷酷学!!!

2. 顺序表与链表的区别

在实现栈之前, 我们先总结一下顺序表和链表
在这里插入图片描述
以上是顺序表与链表比较全面的区别总结, 在插入数据时链表没有容量的概念指的是链表的空间是使用多少开辟多少, 不会进行扩容操作, 也不会造成容量的浪费.

那么什么是缓存利用率,简单讲解一下

在这里插入图片描述
以上是存储器的结构层次,由于CPU的访问速度非常的快, 它不会直接访问内存, 因为内存的读写速度太慢了, 而是将数据先逐层转移到寄存器或者高速缓存中,在进行读写, 一般寄存器存放字节大小为8的数据, 然后CPU再进行访问, 但是如何将数据转移到缓存当中的呢, 为什么说顺序表缓存利用率高而链表低呢?

在这里插入图片描述

在将内存中的数据运送到缓存中的时候, 不是一个一个传输的,而是将连带后面的一块空间直接一起运送到缓存中, 如同一辆大巴车一样, 不是一个一个运送, 而是包括后面的一块空间一起运输, 然后CPU在从缓存中进行读写, 那么, 如果继续往后读写, 在缓存中, 我们称之为缓存命中, 直接访问, 如果不在缓存中, 我们称之为不命中, 要把数据从内存加载到缓存中, 在进行访问, 如此看来所以 顺序表的缓存利用率肯定高于链表

更多资讯, 可以点击参考 与程序员相关的CPU缓存知识

3. 什么是栈

: 一种特殊的线性表, 其只允许在固定的一端进行插入和删除元素操作. 在进行数据插入和删除操作的一端称之为栈顶, 另一端称之为栈底. 栈中的元素遵守后进先出LIFO(Last In First Out)原则.

压栈 : 栈的插入操作叫做压栈或入栈, 入数据在栈顶
出栈 : 栈的删除操作叫做出栈. 出数据也在栈顶.

在这里插入图片描述
在这里插入图片描述

4. 栈的实现

栈的实现一般可以使用数组或者链表进行实现, 相对而言数组的结构实现更优一些, 因为在数组上尾插数据的代价比较小, 而且数组的缓存利用率比较高.

在这里插入图片描述
在这里插入图片描述
第一步:

创建三个文件
在这里插入图片描述
在头文件中进行结构定义和函数声明

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#include<stdbool.h>

typedef int STDatatype;
typedef struct Stack
{
	STDatatype* a;
	int top;
	int capacity;
}ST;

//初始化
void InitStack(ST* pst);
//销毁
void Destory(ST* pst);

//压栈
void Push(ST* pst,STDatatype x);
//出栈
void Pop(ST* pst);
//取栈顶元素
STDatatype STTop(ST* pst);

//判空
bool Empty(ST* pst);
//获取元素个数
int Size(ST* pst);

第二步:
实现栈的方法

  • 初始化
void InitStack(ST* pst)
{
	assert(pst);
	pst->a = NULL;
	pst->capacity = pst->top = 0;
}

注意
top的值根据自己的情况定义, 若top=0,表示指向栈顶数据下一个位置, top=-1,表示指向栈顶数据.
在这里插入图片描述

首先断言,这里肯定不能给我传一个NULL, 然后进行常规操作

  • 销毁
void Destory(ST* pst)
{
	assert(pst);
	free(pst->a);
	pst->a = NULL;
	pst->top = pst->capacity = 0;
}

动态顺序表, 空间需要手动释放

  • 压栈
void Push(ST* 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);
		if (tmp == NULL)
		{
			perror("malloc fail");
			return;
		}
		pst->a = tmp;
		pst->capacity = Newcapacity;
	}
	pst->a[pst->top] = x;
	pst->top++;
}

因为我们初始化的时候没有开辟空间, 所以如果栈为空的时候, 我们先开辟四个空间, 当栈满时, 我们在成倍扩容, 然后先用临时变量存储首地址, 防止申请失败原地址丢失, 然后更改空间容量大小, 最后在进行写入数据.

  • 销毁
void Pop(ST* pst)
{
	assert(pst);
	assert(pst->top > 0);
	pst->top--;
}

首先栈不能为NULL, 并且需要有数据, 然后直接top-- 就行.

  • 获取栈顶元素
STDatatype STTop(ST* pst)
{
	assert(pst);
	assert(pst->top > 0);
	return pst->a[pst->top-1];
}

直接返回top的前一个位置

  • 判断栈是否为空
bool Empty(ST* pst)
{
	assert(pst);
	return pst->top == 0;
}

如果top为0则栈为空

  • 获取数据个数
int Size(ST* pst)
{
	assert(pst);
	return pst->top;
}

top表示下标, 也就是元素个数

5. OJ括号匹配

题目链接: 有效的括号

题目描述:

在这里插入图片描述
题目分析:

首先题目有三个要求

  1. 左括号必须用相同类型的右括号进行闭合.
  2. 左括号必须以正确的顺序闭合
  3. 每个左括号都有一个对应相同类型的左括号

如果我们直接用左括号个数与右括号进行比较的话, 那么顺序问题我们无法解决, 而栈这种后进先出的结构恰好可以解决这种问题, 当遇到左括号时进行压栈, 遇到右括号时将左括号出栈, 进行比较, 正好解决了顺序问题, 但是C语言没有栈这种结构, 所以我们需要自己写栈这种结构.
于是我们很容易写出下面的代码.

bool isValid(char* s) {
	ST stack;
	InitStack(&stack);
	while (*s)
	{
		//左括号压栈
		if (*s == '(' || *s == '{' || *s == '[')
		{
			Push(&stack, *s);
			s++;
		}
		//右括号与栈顶左括号进行匹配
		else
		{

			char tmp = STTop(&stack);
			Pop(&stack);
			//如果不匹配
			if ((tmp == '(' && *s != ')')
				|| (tmp == '[' && *s != ']')
				|| (tmp == "{" && *s != '}'))
			{
				return false;
				Destory(&stack);
			}
		}
	}
	return true;
	Destory(&stack);
}

但是这样写真的对吗, 答案是错的, 因为如果只有左括号的情况, 和只有右括号的情况, 我们还需要加以判断. 修正代码
字符串只有右括号, 先判断栈是否为空, 若为空返回false,并且释放栈

字符串只有左括号, 循环结束, 看看栈中元素还有没有, 如果还有则返回false,并且销毁栈

bool isValid(char* s) {
    ST stack;
    InitStack(&stack);
    while (*s) {
        // 左括号压栈
        if (*s == '(' || *s == '{' || *s == '[') {
            Push(&stack, *s);
        }
        // 右括号与栈顶左括号进行匹配
        else {
            if (Empty(&stack)) {
                Destory(&stack);
                return false;
            }
            char tmp = STTop(&stack);
            Pop(&stack);
            // 如果不匹配
            if ((tmp == '(' && *s != ')') || (tmp == '[' && *s != ']') ||
                (tmp == '{' && *s != '}')) {
                Destory(&stack);
                return false;
            }
        }
        ++s;
    }
    bool ret = Empty(&stack);
    Destory(&stack);
    return ret;
}

全部代码如下:

typedef char STDatatype;
typedef struct Stack {
    STDatatype* a;
    int top;
    int capacity;
} ST;

// 初始化
void InitStack(ST* pst);
// 销毁
void Destory(ST* pst);

// 压栈
void Push(ST* pst, STDatatype x);
// 出栈
void Pop(ST* pst);
// 取栈顶元素
STDatatype STTop(ST* pst);

// 判空
bool Empty(ST* pst);
// 获取元素个数
int Size(ST* pst);

void InitStack(ST* pst) {
    assert(pst);
    pst->a = NULL;
    pst->capacity = pst->top = 0;
}

void Destory(ST* pst) {
    assert(pst);
    free(pst->a);
    pst->a = NULL;
    pst->top = pst->capacity = 0;
}

void Push(ST* 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);
        if (tmp == NULL) {
            perror("malloc fail");
            return;
        }
        pst->a = tmp;
        pst->capacity = Newcapacity;
    }
    pst->a[pst->top] = x;
    pst->top++;
}

void Pop(ST* pst) {
    assert(pst);
    assert(pst->top > 0);
    pst->top--;
}

STDatatype STTop(ST* pst) {
    assert(pst);
    assert(pst->top > 0);
    return pst->a[pst->top - 1];
}

bool Empty(ST* pst) {
    assert(pst);
    return pst->top == 0;
}

int Size(ST* pst) {
    assert(pst);
    return pst->top;
}

bool isValid(char* s) {
    ST stack;
    InitStack(&stack);
    while (*s) {
        // 左括号压栈
        if (*s == '(' || *s == '{' || *s == '[') {
            Push(&stack, *s);
        }
        // 右括号与栈顶左括号进行匹配
        else {
            if (Empty(&stack)) {
                Destory(&stack);
                return false;
            }
            char tmp = STTop(&stack);
            Pop(&stack);
            // 如果不匹配
            if ((tmp == '(' && *s != ')') || (tmp == '[' && *s != ']') ||
                (tmp == '{' && *s != '}')) {
                Destory(&stack);
                return false;
            }
        }
        ++s;
    }
    bool ret = Empty(&stack);
    Destory(&stack);
    return ret;
}

6. 总结

栈是一种线性数据结构,具有后进先出(LIFO)的特点,即最后进入栈的元素最先被访问或删除。栈通常有两种基本操作:压栈(push)和弹栈(pop),分别用于将元素压入栈顶和从栈顶弹出元素。

栈的应用非常广泛,常见的应用包括表达式求值、函数调用、浏览器的前进后退功能等。在计算机科学中,栈也被用于实现递归算法、解决括号匹配等问题。

栈的实现方式有多种,包括基于数组和基于链表的实现。基于数组的实现通常需要指定栈的最大容量,而基于链表的实现则可以动态调整大小。

总的来说,栈是一种非常重要且常用的数据结构,掌握栈的基本操作和应用场景对于理解算法和数据结构有着重要的意义。

如果此文有帮助 感谢点赞关注!!!

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

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

相关文章

python(环境安装)搭建、pycharm安装、背景改为白色详细文章

安装python环境 1、下载python安装包 Welcome to Python.org&#xff08;官网链接&#xff09; 2、点击下载、windows、python3.12.3 安装python 执行安装程序、安装选项 选择下面两项 翻译 Use admin privieges when installing py.exe是使用administrator超级管理员用户安…

疾病防范:拯救微笑,关于儿童抑郁的注意事项

引言&#xff1a; 儿童抑郁是一种常见但常被忽视的心理健康问题&#xff0c;对孩子的身心健康和成长都会造成严重影响。本文将探讨儿童抑郁的注意事项&#xff0c;以帮助家长和教育者更好地识别、理解和应对儿童抑郁问题。 1. 深入了解抑郁症&#xff1a; 抑郁症并非一种偶发的…

技术探索:揭秘美颜API与直播美颜SDK的算法与优化策略

今天&#xff0c;小编将深入探讨美颜API与直播美颜SDK背后的算法原理和优化方法。 一、美颜算法概述 美颜算法的核心在于对人脸的识别和特征分析&#xff0c;通过对人脸各个部位的处理&#xff0c;达到美颜等效果。 二、美颜API的算法原理 美颜API通常是以云服务的形式提供&…

参加了深圳线下组织的商业沙龙,收获颇丰

能参加本次商业沙龙也本是一连串的事情导致的&#xff0c;听我慢慢道来&#xff1a; 大概在4.13之前无意收到忘了谁发的短信了&#xff0c;说有个啥AI的报告会&#xff0c;然后我就报名了&#xff1a; 会上大佬还是挺多的&#xff0c;来了好多各界的老板和政府的领导&#xff…

MySQL—子查询

目录 ▐ 子查询概述 ▐ 准备工作 ▐ 标量子查询 ▐ 列子查询 ▐ 表子查询 ▐ 多信息嵌套 ▐ 子查询概述 • 子查询也称嵌套查询&#xff0c;即在一个查询语句中又出现了查询语句 • 子查询可以出现在from 后面 或where后面 • 出现在 from 后称表子查询&#xff0c;结…

CSS 之 帧动画(Keyframe Animation)

一、简介 ​ CSS 制作 Web 动画有两种方式&#xff1a; 帧动画&#xff08;Keyframe Animation&#xff09;和过渡动画&#xff08;Transition Animation&#xff09;。在不同的业务场景中&#xff0c;我们应该选择不同的动画方式&#xff0c;通常来说&#xff1a;对于交互元素…

数据库管理-第187期 23ai:怎么用SQL创建图(20240510)

数据库管理187期 2024-05-10 数据库管理-第187期 23ai:怎么用SQL创建图&#xff08;20240510&#xff09;1 安装PGX1.1 数据库配置对应用户1.2 使用RPM包安装Graph Server1.3 安装Oracle Graph Client1.4 访问PGX页面 2 SQL Property Graph2.1 创建SQL属性图2.2 关于点和边图元…

k8s 使用Docker和Containerd对比分析

目录 k8s 使用Docker和Containerd对比分析 互动1&#xff1a;docker build构建的镜像和containerd镜像通用吗&#xff1f; 互动2&#xff1a;k8s1.24之前版本和1.24及1.24之后版本区别&#xff1f; k8s 使用Docker和Containerd对比分析 如果你使用Docker作为K8S容器运行时的…

NASA数据集——非洲加蓬上空的回波能量波形、高程数据和地理标记图像V001版本

数据英文名称 AfriSAR LVIS L1B Geolocated Return Energy Waveforms V001 AfriSAR LVIS L2 Geolocated Surface Elevation Product V001 AfriSAR LVIS L1A Geotagged Images V001 简介 该数据集包含非洲加蓬上空的回波能量波形数据。测量数据由美国国家航空航天局的陆地、…

《一“企”谈》∣企企通走进『鹏辉能源』,探索百亿储能上市企业如何实现供应链数字化转型

随着运营模式的升级和市场竞争的加剧&#xff0c;采购数字化已成为企业提升竞争力的关键。通过整合人工智能、大数据、云计算和物联网等先进技术&#xff0c;采购流程正逐步实现智能化、协同化和绿色化&#xff0c;大幅提升采购效率和决策质量。 广州鹏辉能源科技股份有限公司&…

STM: SpatioTemporal and Motion Encoding for Action Recognition 论文阅读

STM: SpatioTemporal and Motion Encoding for Action Recognition 论文阅读 Abstract1. Introduction2. Related Works3. Approach3.1. Channel-wise SpatioTemporal Module3.2. Channel-wise Motion Module3.3. STM Network 4. Experiments5. Conclusion 文章信息&#xff1a…

vin查询接口如何对接

vin查询接口是VIN车辆识别代码查询接口的简称&#xff0c;也叫vin查询车辆信息接口、车架号查询接口&#xff0c;指的是输入车辆VIN识别码&#xff08;车架号&#xff09;&#xff0c;返回车辆相关信息&#xff0c;如车辆品牌、车型、油耗、车身形式、排量等。那么vin查询接口如…

数据治理平台有哪些核心功能?十款热门数据治理平台盘点

数据治理是管理企业数据资产全过程中的决策、监督和执行控制&#xff0c;旨在引导和影响组织内所有其他数据管理活动&#xff0c;核心目标是确保数据按照既定的管理制度和行业最佳实践得到妥善管理。不论企业是否设有正式的数据治理职位&#xff0c;那些确立了正式数据治理流程…

高德地图:标点-连线-自定义图标-文字提示的使用

目录 下面是使用高德地图进行标点连线的使用&#xff1a; 1.定义一个装载地图的容器&#xff0c;并定义进行标点和连线的数据 2.在组件的mounted钩子函数中初始化地图&#xff0c;给地图添加点击事件监听器。 3.使用高德地图的Polyline类来绘制连接线。 这是上面代码的效果…

人工智能生成图像的兴起:区分事实与虚构

人工智能生成图像的兴起&#xff1a;区分事实与虚构 概述 在人工智能 (AI) 已融入我们日常生活的时代&#xff0c;人工智能生成图像的快速发展引发了人们对数字内容真实性的担忧。最近&#xff0c;人工智能生成的图像甚至欺骗了最敏锐的眼睛&#xff0c;这引发了人们对批判性…

Shell生成支持x264的ffmpeg安卓全平台so

安卓 FFmpeg系列 第一章 Ubuntu生成ffmpeg安卓全平台so 第二章 Windows生成ffmpeg安卓全平台so 第三章 生成支持x264的ffmpeg安卓全平台so&#xff08;本章&#xff09; 文章目录 安卓 FFmpeg系列前言一、实现步骤1、下载x264源码2、交叉编译生成.a3、加入x264配置4、编译ffmp…

数字水印 | Python 基于离散小波变换 DWT 的图像水印嵌入(下)

&#x1f34d;原文&#xff1a; 基于 dwt (离散小波变换) 实现彩色图像水印嵌入部分_2.0 &#x1f34d;写在前面&#xff1a; 本文在原文的基础上进行了代码补全。 正文 修改了尺寸变换导致的图像失真问题&#xff0c;同时简化了部分代码。 效果确实很好&#x1f609; 1 通道…

15W 3KVAC隔离 宽电压输入 AC/DC 电源模块——TP15AL系列

TP15AL系列产品是一款小体积裸板式电源,该系列电源输出功率为15W,具有低漏电流小于0.35mA,隔离耐压高达3KV等特点。产品安全可靠&#xff0c;EMC性能好&#xff0c;该系列产品广泛应用于智能家居、充电桩、安防、物联、工控等行业中&#xff0c;如应用于电磁兼容比较恶劣的环境…

Kerberos修改协议为TCP

部署前 修改模板/home/cloud-setup/deploy-forklift/mids/forklift-basic/kde/v1.0/impl/plays/roles/krb5-client/templates/krb5.conf.j2 添加如下参数 udp_preference_limit 1 部署后 界面修改 添加如下参数&#xff0c;并勾选下发配置按钮&#xff0c;重启刷新服务

Linux-04

账号管理 添加账号 useradd 选项 用户名 useradd -m dai删除帐号 userdel 选项 用户名 userdel -r dai修改帐号 usermod 选项 用户名usermod -d /home/user dai &#xff08;修改位置&#xff09;切换帐号 su username su dai退出账号 exit $表示普通用户 #表示超级用户&#…