【数据结构】三、栈和队列: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;		//指针先加1S.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;	//指针再减1return 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;			//令栈顶位置为0stack.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;		//初始化栈顶指针的位置为-1return true;
}//判断栈空
bool StackEmpty(SqStack stack){if (stack.top == -1)return true;elsereturn false; 
}//判断栈满
bool StackFull(SqStack stack){if (stack.top == MaxSize-1)   //top的位置值等于MaxSize-1时栈满,因为是从0开始的return true; elsereturn 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++;		//栈顶自增1stack.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--;	//栈顶自减1return 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;			//令栈顶位置为0stack.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

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

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何把为知笔记导入到Notion笔记里面

&#x1f4a1; 大家好&#xff0c;我是可夫小子&#xff0c;《小白玩转ChatGPT》专栏作者&#xff0c;关注AIGC、读书和自媒体。 为知笔记并不开放&#xff0c;笔记文件只能以pdf或者图片的方向导出来&#xff0c;无法与其他笔记文件相互导入导出&#xff0c;然而&#xff0c;稍…

【QT学习】13.使用TCP实现文件传输

一。传输文件流程 二。实现 结果&#xff1a; 1. server server类属性 Ui::Widget *ui;QTcpServer* pTcpServer;QTcpSocket* pTcpSocket;//文件与文件信息QFile file;QString m_fileName;qint64 m_fileSize; //整个文件大小qint64 fileSize; //当前已经发送的文件大小bool …

巅峰之战·成长之美丨 纷享销客中南战区伙伴同行者大会圆满成功

近日&#xff0c;为期2天的纷享销客中南战区伙伴同行者大会在北京成功举行&#xff0c;从全国各地奔赴而来的渠道伙伴共襄盛举。大会以”巅峰之战成长之美“为主题&#xff0c;共同探讨”双向奔赴 、健康经营、赢盈共进“的发展之道。 一、数智赋能&#xff0c;任重道远 纷享销…

第三方软件测试机构的优势

软件测试机构在软件开发和验收过程中扮演着至关重要的角色&#xff0c;其优势主要体现在以下几个方面&#xff1a; 专业性&#xff1a;软件测试机构通常拥有专业的测试团队&#xff0c;这些团队成员具备丰富的测试经验和深厚的专业知识&#xff0c;能够准确识别软件中的潜在问…

新唐的nuc980/nuc972的开发1-环境和源码同步

开发环境安装 1.1更新源 服务器端&#xff1a;可以参考&#xff1a;Linux替换清华源_更改清华源-CSDN博客 下面是桌面端的方法&#xff1a; 打开系统的软件中心&#xff0c;选择自己想要使用的源 更新缓存 1.2安装必须的库 apt-get install patch apt-get install libc6-dev …

微信机器人openai免注册信用卡生成api

简介 chatgpt-on-wechat (cow) 项目是使用 ChatGPT 搭建的智能聊天机器人&#xff0c;在GPT3.5/4.0 API 及 itchat框架的基础上实现&#xff0c;支持微信公众号、企业微信、钉钉、飞书部署&#xff0c;能生成文本、语音和图片&#xff0c;访问操作系统和互联网。 最新版本支持…

【Qt之·控件·样式表】

系列文章目录 文章目录 前言一、Qt样式表的基础知识1.1 Qt样式表的定义和语法规则1.2 Qt样式表中的选择器和属性1.2.1 盒子模型1.2.2 border 1.3 Qt样式表中的伪类和伪元素 二、编写基本的Qt样式表2.1 在Qt应用程序中引入样式表文件的方式2.2 设置基本的背景色、字体样式等 三、…

大数据中的项目数据采集

Datax介绍 官网&#xff1a; DataX/introduction.md at master alibaba/DataX GitHub DataX 是阿里云 DataWorks数据集成 的开源版本&#xff0c;在阿里巴巴集团内被广泛使用的离线数据同步工具/平台。 DataX 实现了包括 MySQL、Oracle、OceanBase、SqlServer、Postgre、HDFS…

源码篇--Nacos服务--中章(8):Nacos服务端感知客户端实例变更-3

文章目录 前言一、客户端实例变更&#xff1a;二、实例变更感知&#xff1a;2.1 实例注册信息通知&#xff1a;2.1.1 接收DistroDataRequest 请求&#xff1a;2.1.2 onReceive 处理请求&#xff1a;2.1.3 processData 处理请求&#xff1a;2.1.4 handlerClientSyncData 处理数据…

数据库分库分表

数据库分库分表 分库分表到底是什么 分库分表其实是分库,分表,分库分表的总称 分库 将数据按照一定规则存储到不同的数据库中,每个数据库存储一部分数据 分库主要解决的是并发量过大的问题&#xff0c;并发量一旦上升&#xff0c;那么数据库就可能成为系统的瓶颈&#xff…

Vulnhub-DIGITALWORLD.LOCAL: VENGEANCE渗透

文章目录 前言1、靶机ip配置2、渗透目标3、渗透概括 开始实战一、信息获取二、smb下载线索三、制作字典四、爆破压缩包密码五、线索分析六、提权&#xff01;&#xff01;&#xff01; Vulnhub靶机&#xff1a;DIGITALWORLD.LOCAL: VENGEANCE ( digitalworld.local: VENGEANCE …

简单谈谈URL过滤在网络安全中的作用

用户花在网络上的时间越来越多&#xff0c;浏览他们最喜欢的网站&#xff0c;点击电子邮件链接&#xff0c;或利用各种基于网络的 SaaS 应用程序供个人和企业使用。虽然这种不受约束的网络活动对提高企业生产力非常有用&#xff0c;但也会使组织面临一系列安全和业务风险&#…