【数据结构】三、栈和队列:2.顺序栈共享栈(顺序栈的初始化,判空,进栈,出栈,读取栈顶,顺序栈实例)

文章目录

    • 1.顺序栈
      • 1.1初始化
      • 1.2判空
      • 1.3进栈
      • 1.4出栈
      • 1.5读取栈顶
      • 1.6销毁栈
      • ❗1.7顺序栈c++实例
    • 2.共享栈
      • 2.1初始化
      • 2.2判满

1.顺序栈

顺序存储实现的栈

顺序栈的缺点:栈的大小不可变。

#define MaxSize 10			//定义栈中元素的最大个数
typedef struct{
    ElemType data[MaxSize];	//静态数组存放栈中元素
    int top;				//栈顶指针
} SqStack;				//Sq即sequence:顺序的意思

有的顺序栈结构还有栈的大小stackSize

typedef struct{
	ElemType* base;	//栈底指针:base指针不动、top往上移
	ElemType* top;	//栈顶指针
	int stackSize;	//当前已分配的存储空间大小,即顺序栈的大小
} SqStack;			//顺序栈的结构体定义

顺序存储:给各个数据元素分配连续的存储空间,大小为 MaxSize * sizeof(ElemType)。

1.1初始化

InitStack(&S):初始化栈。构造一个空栈S,分配内存空间。

#define MaxSize 10			//定义栈中元素的最大个数
typedef struct {
    ElemType data[MaxSize];	//静态数组存放栈中元素
    int top;				//栈顶指针
} SqStack;

//初始化
void InitStack(SqStack &S) {
	S.top = -1;				//初始化栈顶指针
}

void main() {
    SqStack S; 				//声明一个顺序栈(分配空间)
    InitStack(S);
    //后续操作...
}

初始化有两种方式:

栈顶指针top指向栈顶元素,一般存储的是数组的下标。(一般初始化时top=-1)

  1. 初始化时top=-1,那么元素从0开始。top当前指向的位置就是栈顶。

    如果有abcde,5个元素,那么满栈top=4。

    • 入栈:S.data[++S.top]=x;
    • 出栈:x=S.data[S.top-];
    • 获得栈顶元素:x=S.data[S.top];
  2. 初始化时top=0。top当前指向的位置是栈顶上面的一个没有元素的空位置。

    • 入栈:S.data[S.top++]=x;
    • 出栈:x=S.data[–S.top];
    • 获得栈顶元素:x=S.data[S.top-1];

1.2判空

StackEmpty(S):断一个栈S是否为。若S为空,则返回true,否则返回false。

时间复杂度:O(1)

//判断栈空
bool StackEmpty(SqStack S) {
    if(S.top == -1)	//栈空
        return true;
    else			//不空
        return false;
}

1.3进栈

Push(&S,x):插入,进栈。若栈S未满,则将x加入使之成为新栈顶

时间复杂度:O(1)

//新元素入栈
bool Push(SqStack &S, ElemType x) {
    if (S.top == MaxSize-1)	//栈满,报错
        return false;
    
    S.top = S.top+1;		//指针先加1
    S.data[S.top] = x;		//新元素入栈
    
    return true;
}

上述代码中,指针+1,然后新元素入栈的两段代码可以等价于:

S.data[++S.top] = x;

注意是++S.top先加再用,而不是S.top++先用再加。

1.4出栈

Pop(&S,&x):删除,出栈。若栈S非空,则弹出栈顶元素,并用x返回。

时间复杂度:O(1)

//出栈操作
bool Pop(SqStack &S, ElemType &x) {
    if(S.top == -1)		//栈空,报错
        return false;
    
    x = S.data[S.top];	//栈顶元素先出栈
    S.top = S.top-1;	//指针再减1
    
    return true;
}

注意:这里top-1,数据其实还残留在内存中,只是逻辑上被删除了。

上述代码中也可以等价于:

x = S.data[S.top--];

注意是S.top--先用再减,而不是--S.top先减再用。

1.5读取栈顶

GetTop(S,&x):读取栈顶元素。若栈S非空,则用x返回线顶元素。

时间复杂度:O(1)

//读栈顶元素
bool GetTop(SqStack S, ElemType &x) {
	if(S.top == -1)		//栈空,报错
        return false;
    x = S.data[S.top];	//×记录栈顶元素
    return true;
}

读取栈顶元素和出栈操作十分相似,唯一不同是不需要出栈之后top指针-1。

1.6销毁栈

顺序栈是在声明栈时直接分配内存,并没有使用malloc函数,所以不需要手动free,函数运行结束后系统自动回收空间。

但是如果使用了动态分配那么就需要手动释放空间:

//销毁栈、释放栈的内存
void DestroyStack(SqStack& stack){
	if(stack.base) {			//若栈底指针分配有地址,则释放
		delete stack.base;	//释放栈底指针的地址
		stack.top = -1;			//令栈顶位置为0
		stack.base = NULL;	//将栈底指针指向空
		cout << "栈已释放内存!" << endl; 
	}
}

❗1.7顺序栈c++实例

C++是一门面向对象的高级语言,在我们编写代码中,常常离不开对对象的创建和清理对象资源。而兼容过来的mallocfree并不能很好的满足我们的需求,从而C++将mallocfree封装起来并起了新的名字newdelete,这两个关键字的作用不仅比mallocfree的功能强大,用起来也非常的方便。

new和delete都是运算符,不是库函数,不需要单独添加头文件。

格式:

new

  • 类型指针 指针变量名 = new 类型
  • 类型指针 指针变量名 = new 类型(初始值)
  • 类型指针 指针变量名 = new 类型[元素个数]

delete

  • delete 指针变量名
  • delete[] 指针变量名
#include<iostream>
#include<Windows.h>
using namespace std;

#define MaxSize 10				//栈最大可以存放的元素个数
typedef int ElemType;		//顺序栈存储的数据类型、用int代替ElemType

//创建顺序栈

typedef struct
{
	ElemType* base;  //栈底指针
	int top;		 //栈顶的位置 如 0、1、2、3、4....MaxSize
} SqStack;			 //顺序栈的结构体定义



bool InitStack(SqStack& stack);	//初始化栈
bool StackEmpty(SqStack stack);//判断是否为空
bool StackFull(SqStack stack);	//判断是否已满
int GetStackSize(SqStack& stack);//获取顺序栈中元素个数

bool Push(SqStack& stack, ElemType value);//入栈
bool Pop(SqStack& stack, ElemType& value);//出栈
bool GetTop(SqStack& stack, ElemType& value);//获取栈顶的元素
void DestroyStack(SqStack& stack);//销毁栈、释放栈的内存



//--------------------------------------------------
void CreatStack(SqStack stack){
    int number, value = 0;
    cout << "请输入需要插入的元素个数:";
	cin >> number;
	while (number > 0){
		cin >> value;
		Push(stack, value);	//放入栈
		number--;
        value++;
	}
}

int main()
{
	SqStack	stack;		//创建顺序栈
	InitStack(stack);	//初始化顺序栈
//例如插入    
	int value = 5;      //插入5个元素
    while (value > 0){
		Push(stack, value);	//放入栈
		value--;
	}

	
	//获取栈顶的元素
	GetTop(stack, value);
	cout << "当前栈顶的元素是:" << value << endl;

	//获取栈的元素个数
	cout << "当前栈的元素个数是:" << GetStackSize(stack) << endl;

	//出栈
	cout << "出栈顺序:" << endl;
	while (!StackEmpty(stack)){
		Pop(stack, value);
		cout << value << " "; 
	}
	cout << endl;
    
	//释放栈的内存
	DestroyStack(stack);
	system("pause");
	return 0;
}


//-----------------------------------------------------------------------
//初始化顺序栈
bool InitStack(SqStack& stack){

	//注意:这里使用new进行空间分配,所以在后面摧毁栈的时候需要delete释放空间

	//动态分配一个ElemType类型MaxSize长度的空间,将地址给顺序栈Stack的栈底指针
	stack.base = new ElemType[MaxSize];
	//判断顺序栈的栈底指针(stack.base)是否为空,若无地址,则分配失败
	if(!stack.base){
		return false; 
	}
	stack.top = -1;		//初始化栈顶指针的位置为-1
	return true;
}

//判断栈空
bool StackEmpty(SqStack stack){
	if (stack.top == -1)
		return true;
	else
		return false; 
}

//判断栈满
bool StackFull(SqStack stack){
	if (stack.top == MaxSize-1)   //top的位置值等于MaxSize-1时栈满,因为是从0开始的
		return true; 
	else
		return false; 
}

//顺序栈中元素个数
int GetStackSize(SqStack& stack){
	return stack.top+1;  //栈顶位置即top的数值,就是栈中元素的个数
}

/**
 * @brief 顺序栈入栈:
 * 开辟一个新的空间,栈顶+1,然后将数据存入stack.base[stack.top]所在的位置.
 * 
 * @param stack 
 * @param value 
 * @return true 
 * @return false 
 */
bool Push(SqStack& stack, ElemType value){
	if (StackFull(stack)){
		cout<<"栈满"<<endl;
		return false;  
	}
	//若栈未满,执行入栈操作
	stack.top++;		//栈顶自增1
	stack.base[stack.top] = value;    //以栈顶位置作为下标存储数据
	return true;
}

/**
 * @brief 顺序栈出栈:
 * 读取栈顶stack.base[stack.top]的元素,然后使栈顶-1.
 * 
 * @param stack 
 * @param value 
 * @return true 
 * @return false 
 */
bool Pop(SqStack& stack, ElemType &value){
	if (StackEmpty(stack)){
		cout<<"栈为空"<<endl;
		return false;
	}
	value = stack.base[stack.top];	//以栈顶位置作为下标的值赋值给value返回
	stack.top--;	//栈顶自减1
	return true;
}

//读取栈顶元素
bool GetTop(SqStack& stack, ElemType &value){
	if (StackEmpty(stack)){
		cout<<"栈为空"<<endl;
		return false; 
	}
	value = stack.base[stack.top];
	return true; 
}

//销毁栈、释放栈的内存
void DestroyStack(SqStack& stack){
	if(stack.base) {			//若栈底指针分配有地址,则释放
		delete stack.base;	//释放栈底指针的地址
		stack.top = -1;			//令栈顶位置为0
		stack.base = NULL;	//将栈底指针指向空
		cout<<"栈已释放内存!"<<endl; 
	}
}


当前栈顶的元素是:1
当前栈的元素个数是:5
出栈顺序:
1 2 3 4 5
栈已释放内存!

2.共享栈

因为顺序栈的缺点是栈的大小不可变,所以引出共享栈,两个栈共享一片空间。这片存储空间不单独属于任何一个栈,某个栈需要的多一点,它就可能得到更多的存储空间。两个栈的栈底在这片存储空间的两端,当元素入栈时,两个栈的栈顶指针相向而行。

在这里插入图片描述

2.1初始化

#define MaxSize 10			//定义栈中元素的最大个数
typedef struct {
    ElemType data [MaxSize];//静态数组存放栈中元素
    int top0;				//0号栈线顶指针
    int top1;				//1号栈线顶指针
} ShStack;


//初始化栈
void InitStack(ShStack &S) {
    S.top0 = -1;				//初始化栈顶指针
    S.top1 = MaxSize;
}

2.2判满

top0从-1开始,top1从MAX开始。那么放入元素后,top0逐渐增大,top1减小。当他们下一个指针的位置在一起时,说明这个栈已经放满元素。

top0+1 == top1

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

图像哈希:全局+局部提取特征

文章信息 作者&#xff1a;梁小平&#xff0c;唐振军期刊&#xff1a;ACM Trans. Multimedia Comput. Commun. Appl&#xff08;三区&#xff09;题目&#xff1a;Robust Hashing via Global and Local Invariant Features for Image Copy Detection 目的、实验步骤及结论 目…

CPPTest实例分析(C++ Test)

1 概述 CppTest是一个可移植、功能强大但简单的单元测试框架&#xff0c;用于处理C中的自动化测试。重点在于可用性和可扩展性。支持多种输出格式&#xff0c;并且可以轻松添加新的输出格式。 CppTest下载地址&#xff1a;下载地址1  下载地址2 下面结合实例分析下CppTest如…

进程概念(进程第1篇)【Linux复习篇】

目录 1、冯诺依曼体系结构怎么画&#xff1f;中央处理器是什么&#xff1f;存储器是什么&#xff1f;每个部分有什么作用&#xff1f; 2、什么是操作系统&#xff1f; 3、什么叫进程&#xff1f;操作系统如何管理进程的&#xff1f; 4、怎么查看进程&#xff1f; 5、C语言…

springcloud Ribbon的详解

1、Ribbon是什么 Ribbon是Netflix发布的开源项目&#xff0c;Spring Cloud Ribbon是基于Netflix Ribbon实现的一套客户端负载均衡的框架。 2、Ribbon能干什么 LB负载均衡(Load Balance)是什么&#xff1f;简单的说就是将用户的请求平摊的分配到多个服务上&#xff0c;从而达…

AI视频改字个性化祝福豪车装X系统uniapp前端开源源码下载

装X系统源码简介 创意无限&#xff01;AI视频改字祝福&#xff0c;豪车装X系统源码开源&#xff0c;打造个性化祝福视频不再难&#xff01; 想要为你的朋友或家人送上一份特别的祝福&#xff0c;让他们感受到你的真诚与关怀吗&#xff1f;现在&#xff0c; 通过开源的AI视频…

从0到1—POC编写基础篇(二)

接着上一篇 POC常用基础模块 urllib 模块 Python urllib 库用于操作网页 URL&#xff0c;并对网页的内容进行抓取处理。 urllib 包 包含以下几个模块&#xff1a; ●urllib.request - 打开和读取 URL。 ●urllib.error - 包含 urllib.request 抛出的异常。 ●urllib.parse - …

新技术前沿-2024-大型语言模型LLM的本地化部署

参考快速入门LLM 参考究竟什么是神经网络 1 深度学习 1.1 神经网络和深度学习 神经网络是一种模拟人脑神经元工作方式的机器学习算法,也是深度学习算法的基本构成块。神经网络由多个相互连接的节点(也称为神经元或人工神经元)组成,这些节点被组织成层次结构。通过训练,…

【网络安全】在网络中如何对报文和发送实体进行鉴别?

目录 1、报文鉴别 &#xff08;1&#xff09;使用数字签名进行鉴别 &#xff08;2&#xff09;密码散列函数 &#xff08;3&#xff09;报文鉴别码 2、实体鉴别 鉴别(authentication) 是网络安全中一个很重要的问题。 一是要鉴别发信者&#xff0c;即验证通信的对方的确是…

小扎宣布开放 Meta Horizo​​n OS

日前&#xff0c;Meta以“混合现实的新时代”为题的博文宣布向第三方制造商开放Meta Horizon OS&#xff0c;包括华硕、联想和微软Xbox等等&#xff1a; Meta正在朝着为元宇宙建立一个更开放的计算平台的愿景迈出下一步。Meta正在向第三方硬件制造商开放赋能Meta Quest设备的操…

使用 IPAM 解决方案简化分布式网络管理

随着组织在数字领域的全球扩张&#xff0c;分布式网络是不可避免的&#xff0c;这意味着&#xff0c;随着 IT 基础设施的发展&#xff0c;组织需要适应&#xff0c;这包括在不断增长的系统需求、应用程序堆栈、各种协议和安全防御中监控、现代化和简化流程和资源。在有效管理现…

AJAX——案例

1.商品分类 需求&#xff1a;尽可能同时展示所有商品分类到页面上 步骤&#xff1a; 获取所有的一级分类数据遍历id&#xff0c;创建获取二级分类请求合并所有二级分类Promise对象等待同时成功后&#xff0c;渲染页面 index.html代码 <!DOCTYPE html> <html lang&qu…

Pycharm代码规范与代码格式化插件安装

给大家分享两个PyCharm编辑器的插件&#xff0c;分别是pylint与autopep8&#xff0c;主要用来提高我们在使用python进行自动化测试编写以及性能测试脚本编写过程中的代码质量、可读性与美观性。 pylint&#xff1a; ● 代码检查工具&#xff1a;它可以帮助检查代码中的错误、…

pnpm 安装后 node_modules 是什么结构?为什么 webpack 不识别 pnpm 安装的包?

本篇研究&#xff1a;使用 pnpm 安装依赖时&#xff0c;node_modules 下是什么结构 回顾 npm3 之前&#xff1a;依赖树 缺点&#xff1a; frequently packages were creating too deep dependency trees, which caused long directory paths issue on Windowspackages were c…

明日方舟游戏助手:一键完成日常任务 | 开源日报 No.233

MaaAssistantArknights/MaaAssistantArknights Stars: 11.6k License: AGPL-3.0 MaaAssistantArknights 是一款《明日方舟》游戏的小助手&#xff0c;基于图像识别技术&#xff0c;支持一键完成全部日常任务。 刷理智、掉落识别及上传企鹅物流智能基建换班、自动计算干员效率…

《ElementPlus 与 ElementUI 差异集合》el-select 差异点,如:高、宽、body插入等

宽度 Element UI 父元素不限制宽度时&#xff0c;默认有个宽度 207px&#xff1b; 父元素有固定宽度时&#xff0c;以父元素宽度为准&#xff1b; Element Plus 父元素不限制宽度时&#xff0c;默认100%&#xff1b; 父元素有固定宽度时&#xff0c;以父元素宽度为准&#x…

哪些因素影响了PCB电路板切割精度?

PCB电路板切割是电子制造过程中一个至关重要的环节&#xff0c;其精度对后续工序的质量和效率具有决定性影响。因此&#xff0c;了解影响PCB电路板切割精度的原因&#xff0c;对于提高电子产品的质量和生产效率具有重要意义。 1. PCB分板机稳定性 PCB分板机的性能直接影响到切…

李沐62_序列到序列学习seq2seq——自学笔记

"英&#xff0d;法”数据集来训练这个机器翻译模型。 !pip install --upgrade d2l0.17.5 #d2l需要更新import collections import math import torch from torch import nn from d2l import torch as d2l循环神经网络编码器。 我们使用了嵌入层&#xff08;embedding l…

广东理工学院携手泰迪智能科技成功部署人工智能实验室

广东理工学院是经国家教育部批准设立的全日制普通本科院校&#xff0c;入选全国应用型人才培养工程培养基地、国家级众创空间试点单位、广东省高校电子商务人才孵化基地。开设34个本科专业&#xff0c;涵盖工学、经济学、管理学、文学、艺术学、教育学等6大学科门类&#xff0c…

【docker】拉取人大金仓KingbaseES数据库镜像速度很慢问题

作为一种新兴的虚拟化方式&#xff0c;Docker 跟传统的虚拟化方式相比具有众多的优势。 对于学习新技术、快速搭建实验环境等是很不错的选择。优势大致总结如下&#xff1a; 1.镜像拉取速度对比 速度前后对比&#xff0c;提升10倍不止&#xff0c;很快将镜像文件下载至本地。 …

Java常见面试题总结

文章目录 1. 什么是线程和进程?2. 请简要描述线程与进程的关系,区别及优缺点&#xff1f;3. 什么是堆和方法区&#xff1f;4. 并发与并行的区别5. 同步和异步的区别6.为什么要使用多线程? 优点&#xff1f;&#xff08;重要&#xff09;7. 使用多线程可能带来什么问题?8. 如…