28 线性表 · 栈

news2024/12/27 13:28:47

目录

一、概念与结构

(一)概念

1、栈

2、压栈

3、出栈

4、底层实现       

二、栈的实现

三、栈的算法题


一、概念与结构

(一)概念

1、栈

        一种特殊的线性表,只允许在固定的一端进行插入和删除操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出的原则。

2、压栈

        栈的插入操作叫做进栈/压栈/入栈,入数据在顶端

3、出栈

        栈的删除操作叫做出栈,出数据也在顶端

4、底层实现       

        底层使用数组、单链表、双向链表来实现都是没问题的。

        从内存角度出发,双向链表的节点比单链表节点多一个指正,在32位机器中就多出了4字节内存,在64位机器中就多出了8字节内存。在优化的角度来看,可以先排除掉双向链表。

        从增容的效率出发,数组每次是空间×2地去增容,相比单链表的尾插每增加一个节点就要动态申请一个节点大小的内存的频率,数组的增容频率要小很多,会减少系统的开销。

        从数据读取角度来看,数组的读取频率也比单链表的读取频率要低,因为从主存中读取数据时是取一块连续的空间到缓存中读取,而单链表的地址不一定是连续的,可能要多次从主存中进行读取,所以综合上面增容效率的论述,在优化的角度来看,可以排除单链表。

        综上所述,栈的底层为数组会更优

                

二、栈的实现

        栈的常用名:Stack。

栈的编写:

① 头文件:定义栈的结构体,声明要提供的操作(起到目录作用)。

② cpp文件:编写具体实现各种操作(起到内容作用)。

③ 测试文件:测试是否可以正常运行。

Stack.h

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

using namespace std;
typedef int STDatapype;
//定义栈结构
typedef struct Stack
{
	STDatapype* arr;//栈底层为数组
	int capecity;//栈底层数组的总元素个数
	int top;//栈顶,相当于顺序表中的有效元素个数size
}ST;

//一、初始化栈、销毁栈、增容栈的数组、判断栈是否为空、取栈顶元素、获取栈中有效元素个数
//(一)初始化栈
void STInit(ST& st);
//(二)销毁栈
void STDestroy(ST& st);
//(三)增容栈的数组
void STCapacity(ST& st);
//(四)判断栈是否为空
bool STEmpty(ST& st);
//(五)取栈顶元素
STDatapype STGetTop(ST& st);
//(六)获取栈中有效元素个数
int STGetSize(ST& st);

//二、栈顶插入
void STPush(ST& st, STDatapype num);

//三、栈顶删除
void STPop(ST& st);

Stack.cpp

#define _CRT_SECURE_NO_WARNINGS 1
#include"Stack.h"

//一、初始化栈、销毁栈、增容栈的数组、判断栈是否为空、取栈顶元素、获取栈中有效元素个数
//(一)初始化栈
void STInit(ST& st)
{
	st.arr = nullptr;
	st.capecity = st.top = 0;
}
//(二)销毁栈
void STDestroy(ST& st)
{
	if (st.arr)
	{
		free(st.arr);
		st.arr = nullptr;
	}
	st.capecity = st.top = 0;
}
//(三)增容栈的数组
void STCapacity(ST& st)
{
	if (st.capecity == st.top)
	{
		st.capecity = st.capecity == 0 ? 4 : st.capecity * 2;
		STDatapype* new_st = (STDatapype*)realloc(st.arr, sizeof(STDatapype) * (st.capecity));
		if (new_st == nullptr)
		{
			perror("STCapecity reallco fail");
			exit(1);
		}
		st.arr = new_st;
	}
}
//(四)判断栈是否为空
bool STEmpty(ST& st)
{
	return st.top == 0;
}
//(五)取栈顶元素(只能取到栈顶元素)
STDatapype STGetTop(ST& st)
{
	assert(!STEmpty(st));
	return st.arr[st.top - 1];

}
//(六)获取栈中有效元素个数
int STGetSize(ST& st)
{
	return st.top;
}

//二、栈顶插入
void STPush(ST& st, STDatapype num)
{
	STCapacity(st);
	/*st.arr[st.top] = num;
	st.top++;*/
	st.arr[st.top++] = num;
}

//三、栈顶删除
void STPop(ST& st)
{
	//assert(st.arr);
	assert(!STEmpty(st));
	st.top--;
	if (st.top <= 0)
		st.arr = nullptr;
}

test.cpp

#define _CRT_SECURE_NO_WARNINGS 1
#include"Stack.h"

void test()
{
	ST st;
	STInit(st);

	for (int i = 1; i < 6; i++)
	{
		STPush(st, i);
	}

	/*for (int i = 1; i < 11; i++)
	{
		STPop(st);
		STPrint(st);
	}
	STPrint(st);*/

	while (!STEmpty(st))
	{
		STDatapype num = STGetTop(st);
		cout << num << " ";
		STPop(st);
	}
	cout << endl;
 }

int main()
{
	test();
	return 0;
}

        注意:

                ① 栈没有遍历打印的操作,因为栈不能通过下标进行随机访问其中的数据,只能通过下标拿到栈顶元素。

                ② 空栈的时候,栈底等于栈顶。

三、栈的算法题

        题目链接如下:

                https://leetcode.cn/problems/valid-parentheses/description/

        解题思路:

                使用栈的结构与方法,先遍历字符串数组,若字符串数组中为左括号(无论大中小括号),把该元素压入自定义的栈中;若字符串数组中为右括号(无论大中小括号)则取出栈顶元素进行判断,看看是否为一对,若为一对就把栈顶元素出栈,不是则return false;到最后要销毁栈

        注意点:

                ① 循环结束后要检查栈是否为空,若为空则是括号对应的情况,return true;否则 return false。

                ② 在取出栈顶元素时,要判断栈顶元素是否为空,若为空则 return false,因为要考虑只存在右括号的情况。

        答案代码如下:

typedef char STDataType;
//定义栈结构
typedef struct Stack
{
	STDataType* arr;//栈底层为数组
	int capacity;//栈底层数组的总元素个数
	int top;//栈顶,相当于顺序表中的有效元素个数size
}ST;
//初始化栈
void STInit(ST* ps)
{
	assert(ps);
	ps->arr = NULL;
	ps->capacity = ps->top = 0;
}
//销毁栈
void STDestroy(ST* ps)
{
	assert(ps);
	if (ps->arr)
		free(ps->arr);
	ps->arr = NULL;
	ps->top = ps->capacity = 0;
}
//插入
void STPush(ST* ps, STDataType x)
{
	assert(ps);
	
	//1.判断空间是否足够
	if (ps->capacity == ps->top)
	{
		int newCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
		STDataType* tmp = (STDataType*)realloc(ps->arr, newCapacity * sizeof(STDataType));
		if (tmp == NULL)
		{
			perror("realloc fail!");
			exit(1);
		}
		ps->arr = tmp;
		ps->capacity = newCapacity;
	}
	//空间足够
	ps->arr[ps->top++] = x;
}
//判断是否为空
bool StackEmpty(ST* ps)
{
	assert(ps);
	return ps->top == 0;
}
//删除尾元素
void STPop(ST* ps)
{
	assert(ps);
	assert(!StackEmpty(ps));

	--ps->top;
}
//取栈顶元素
STDataType STGetTop(ST* ps)
{
	assert(ps);
	assert(!StackEmpty(ps));

	return ps->arr[ps->top - 1];
}
//获取栈中有效元素个数
int STSize(ST* ps)
{
	assert(ps);
	return ps->top;
}
 
bool isValid(char* s) {
    //创建栈结构并初始化
    ST st;
    STInit(&st);

    //遍历s,若为左括号就入栈;若为右括号就与栈顶元素进行比较
    char* ps = s;
    while(*ps)
    {
        if(*ps == '(' || *ps == '[' || *ps == '{')
        {
            STPush(&st, *ps);
        }
        else
        {
            if(StackEmpty(&st))//栈不为空才能取栈顶元素,若为空直接返回false
                return false;
            char top_ele = STGetTop(&st);
            if((*ps == ')' && top_ele == '(')
            || (*ps == ']' && top_ele == '[')
            || (*ps == '}' && top_ele == '{'))
            {
                STPop(&st);
            }
            else
            {
                STDestroy(&st);
                return false;
            }
        }
        ps++;
    }
    //销毁栈
    bool re = StackEmpty(&st);
    STDestroy(&st);
    return re;
}

        以上内容仅供分享,若有错误,请多指正。 

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

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

相关文章

idea连接数据库大避雷!!!

再跟着黑马学习的时候&#xff0c;用黑马的资料安装的数据库&#xff0c;命令行能正常启动&#xff0c;SQLyog也能正常连接&#xff0c;就是tmd idea连接不了。不论是原始的jdbc,还是其它方式都不行&#xff0c;一直报错&#xff1a; 然后就各种搜&#xff0c;有的说数据库驱动…

【JavaEE初阶】多线程(4)

欢迎关注个人主页&#xff1a;逸狼 创造不易&#xff0c;可以点点赞吗~ 如有错误&#xff0c;欢迎指出~ 目录 线程安全的 第四个原因 代码举例: 分析原因 解决方法 方法1 方法2 wait(等待)和notify(通知) wait和sleep区别 线程安全的 第四个原因 内存可见性,引起的线程安全问…

AI辅助癌症诊断取得了进展

每周跟踪AI热点新闻动向和震撼发展 想要探索生成式人工智能的前沿进展吗&#xff1f;订阅我们的简报&#xff0c;深入解析最新的技术突破、实际应用案例和未来的趋势。与全球数同行一同&#xff0c;从行业内部的深度分析和实用指南中受益。不要错过这个机会&#xff0c;成为AI领…

服务发现和代理实例的自动更新

1.服务发现的两种方式 StartFindService 方法 这是一个在后台启动的连续 “FindService” 活动&#xff0c;当服务实例的可用性发生变化时&#xff0c;会通过回调通知调用者。 它返回一个FindServiceHandle&#xff0c;可通过调用StopFindService来停止正在进行的监视服务实例…

pwn题目搭建过程中glibc出现问题的解决方案

前言&#xff1a; 在做pwn的堆题时&#xff0c;会遇到不同版本的glibc。为了更好地与远程环境对应&#xff0c;我们可以通过patchelf和glibc-all-in-one来更换程序动态加载时的glibc。简单介绍一下&#xff0c;glibc-all-in-one用来下载需要的glibc包&#xff0c;然后用petche…

【Git】初识Git

本篇文章的环境是在 Ubuntu/Linux 环境下编写的 文章目录 版本控制器Git 基本操作安装 Git创建 Git 本地仓库配置 Git认识工作区、暂存区、版本库添加文件修改文件版本回退撤销修改删除文件 版本控制器 在日常工作和学习中&#xff0c;老板/老师要求我们修改文档&#xff0c;…

Live800:客户服务新纪元,从响应到主动关怀的转型之路

在当今这个快速变化的商业环境中&#xff0c;客户服务已不再是简单的售后响应或问题解决的环节&#xff0c;而是企业赢得市场、构建品牌忠诚度、实现可持续增长的核心驱动力。随着技术的飞速发展和消费者需求的日益多样化&#xff0c;客户服务正步入一个新的纪元——从传统的被…

电脑上如何多开微信软件(多个微信同时使用)

想登录几个就下面这种文件里&#xff0c;复制几行即可&#xff1a; 创建的是以 .bat 文件结尾的txt文件&#xff08;先创建一个txt文本文档&#xff0c;等写好了命令保存后&#xff0c;再把文件的后缀名改为: .bat &#xff09;再保存即可。然后&#xff0c;右键以管理员运行&a…

电子废物检测回收系统源码分享

电子废物检测回收检测系统源码分享 [一条龙教学YOLOV8标注好的数据集一键训练_70全套改进创新点发刊_Web前端展示] 1.研究背景与意义 项目参考AAAI Association for the Advancement of Artificial Intelligence 项目来源AACV Association for the Advancement of Computer…

mysql 8.0 日期维度表生成(可运行)

mysql 8.0 日期维度表生成&#xff08;可运行&#xff09; 文章目录 mysql 8.0 日期维度表生成&#xff08;可运行&#xff09;日期维度表左右日期维度表生成技术点 日期维度表左右 在数据仓库&#xff08;Data Warehouse&#xff09;中&#xff0c;日期维度表&#xff08;Dat…

离谱碾压!奇安信中标:高出第二名近70分!

2024年08月09日&#xff0c;广东省政务服务和数据管理局&#xff0c;近日发布了网络安全第三方服务&#xff08;2024年&#xff09;项目之关基检查及重要政务应用安全检查服务招标公告&#xff01; 预算金额&#xff1a;2,896,200.00元&#xff0c;其中安全检查服务包&#xf…

Pytorch+Anaconda+Pycharm+Python

0 python知识 0.1 os库常见用法 os 库提供了许多用于操作操作系统功能的函数。常见用法包括&#xff1a; 文件和目录操作&#xff1a; os.listdir(path)&#xff1a;列出指定路径下的所有文件和目录。os.mkdir(path)&#xff1a;创建新目录。os.remove(path)&#xff1a;删除…

清理C盘缓存,删除电脑缓存指令是什么

在处理计算机系统的C盘缓存清理任务时&#xff0c;需要谨慎操作以确保系统的稳定性和数据的安全性。通常&#xff0c;Windows操作系统中并没有直接的“一键清理C盘缓存”的单一命令&#xff0c;因为缓存文件分散存储于多个位置&#xff0c;并且有些缓存对于系统性能至关重要&am…

【MySQL】EXPLAIN(执行计划)关键字是什么?

简介&#xff1a; explain是一个强大的 SQL 命令&#xff0c;用于分析和优化查询性能。通过查看数据库执行计划&#xff0c;我们可以理解查询是如何被处理的&#xff0c;包括表的访问顺序、使用的索引、连接类型等。这对于找到潜在的性能瓶颈非常重要。 目录 一、基本含义 二…

四、链表————相关概念详解

链表 前言一、链表是什么&#xff1f;二、链表的类型2.1 单向链表2.2 环形链表2.3 双向链表 三、链表中常用操作 (以单向列表为例)3.1 初始化链表3.2 判断链表是否为空3.3 获取链表长度3.4 插入节点3.4.1 链表头部添加节点3.4.2 链表尾部添加节点3.4.3 指定位置添加节点 3.5 删…

大数据处理技术:分布式文件系统HDFS

目录 1 实验名称&#xff1a; 2 实验目的 3 实验内容 4 实验原理 5 实验过程或源代码 5.1 HDFS的基本操作 5.2 HDFS-JAVA接口之读取文件 5.3 HDFS-JAVA接口之上传文件 5.4 HDFS-JAVA接口之删除文件 6 实验结果 6.1 HDFS的基本操作 6.2 HDFS-JAVA接口之读取文件 6.…

精通推荐算法30:行为序列建模之SIM— 基于检索建模长周期行为序列

1 行为序列建模总体架构 2 SIM提出的背景 MIMN第一次真正实现了长周期行为序列的建模&#xff0c;并取得了非常不错的业务效果。但受困于离线建模&#xff0c;它没办法实现用户行为序列和候选物品的交叉。同时采用一个固定大小的记忆网络来压缩超长序列&#xff0c;存在网络容…

redis-shake v4全量增量同步redis数据

1 概述 RedisShake是一个用于处理和迁移 Redis 数据的工具&#xff0c;github地址是https://github.com/tair-opensource/RedisShake。它提供以下特性&#xff1a; 1&#xff09;Redis 兼容性&#xff1a; RedisShake 兼容从 2.8 到 7.2 的 Redis 版本&#xff0c;并支持各种部…

Spring Event 业务解耦神器(泛型喔!)

一.前言 又与我一直负责Cocos Creator的开发,我发现在TS领域,是可以自定义事件(有兴趣的大宝可以坐飞机直达:[CocosCreator]自定义事件(订阅/发布)管理器),这样做有什么好处呢?回答:解耦! 于是乎,我就觉得前端能干的事,后端也一样能干!当然,如果后端是TS或JS写的,比如nodeJS,…

Cyber Weekly #24

赛博新闻 1、OpenAI发布最强模型o1 本周四&#xff08;9月12日&#xff09;&#xff0c;OpenAI宣布推出OpenAIo1系列模型&#xff0c;标志着AI推理能力的新高度。o1系列包括性能强大的o1以及经济高效的o1-mini&#xff0c;适用于不同复杂度的推理任务。新模型在科学、编码、数…