数据结构(三)——栈

三、栈、队列和数组

3.1 栈

3.1.1 栈的基本概念

线性表是具有相同数据类型的n(n≥0)个数据元素的有限 序列,其中n为表长,当n = 0时线 性表是一个空表。若用L命名线性表,则其一般表示为 L = (a1, a2, … , ai , ai+1, … , an)

栈(Stack)是只允许在一端进行插入或删除操作的线性表
逻辑结构:与普通线性表相同 数据的运算:插入、删除操作有区别

重要术语:栈顶、栈底、空栈
栈顶:允许插入 和删除的一端 (最后进的即最上面的为栈顶元素)
栈底:不允许插 入和删除的一端(最先进的即最下面的为栈底元素)
空栈:不含任何元素的栈

特点:后进先出(后进栈的元素先出栈)  记为LIFO (Last In First Out)

栈的基本操作

  • InitStack(&S):初始化栈。构造一个空栈 S,分配内存空间。
  • DestroyStack(&S):销毁栈。销毁并释放栈 S 所占用的内存空间。
  • Push(&S,x):进栈,若栈S未满,则将x加入使之成为新栈顶。
  • Pop(&S,&x):出栈,若栈S非空,则弹出栈顶元素,并用x返回。
  • GetTop(S, &x):读栈顶元素。若栈 S 非空,则用 x 返回栈顶元素

其他常用操作

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

栈的常考题型
进栈顺序为: a à b à c à d à e  有哪些合法的出栈顺序?

3.1.2 栈的顺序存储实现

顺序栈的定义:

#define MaxSize 10         //定义栈中元素的最大个数
typedef struct{    ElemType data[MaxSize];       //静态数组存放栈中元素    int top;                      //栈顶指针 用于指向此时栈中的栈顶元素 一般用来记录数组的下标
}SqStack;void testStack(){    SqStack S;       //声明一个顺序栈(分配空间)
}

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

初始化操作

#define MaxSize 10                 //定义栈中元素的最大个数
typedef struct{   ElemType data[MaxSize];        //静态数组存放栈中元素int top;                       //栈顶指针
}SqStack;// 初始化栈
void InitStack(SqStack &S){ S.top = -1;                   //初始化栈顶指针
}void testStack(){SqStack S;                    //声明一个顺序栈(分配空间)InitStack(S);//...后续操作...
}// 判断栈是否为空
bool StackEmpty(SqStack S){    if(S.top == -1)                //栈空return true;    else                           //不空return false;
}

进栈操作

#define MaxSize 10                    //定义栈中元素的最大个数
typedef struct{ElemType data[MaxSize];           //静态数组存放栈中元素int top;                          //栈顶指针
}SqStack;    // 新元素进栈
bool Push(SqStack &S, ElemType x){    // 判断栈是否已满   满了报错  if(S.top == MaxSize - 1)        return false;    S.top = S.top+1;                  //指针先加1S.data[S.top]=x;                  //新元素入栈 把x存到top指针所在的位置return true;
}S.top = S.top+1;                  //指针先加1S.data[S.top]=x;                  //新元素入栈 把x存到top指针所在的位置上面两句代码等价于S.data[++S.top]=x;                //++top表示,先让top的值加1 再来使用top

 出栈操作

#define MaxSize 10                    //定义栈中元素的最大个数
typedef struct{ElemType data[MaxSize];           //静态数组存放栈中元素int top;                          //栈顶指针
}SqStack;    // 出栈
bool Pop(SqStack &x, ElemType &x){    // 判断栈是否为空    if(S.top == -1)                   //栈空报错return false;    x = S.data[S.top--];    return true;
}x = S.data[S.top--];    等价于x=S.data[S.top];                     //栈顶元素先出栈S.top=S.top-1;                       //指针再减1top指针减1 数据还残留在内存中,指示逻辑上被删除了

栈顶指针:S.top,初始化时设置S.top=-1;栈顶元素:S.data[S.top]
进栈操作:栈不满时,栈顶指针先加1,再送值到栈顶
出栈操作:栈非空时,先取栈顶元素,再将栈顶指针减1
栈空条件:S.top==-1,栈满条件:S.top==MaxSize-1;栈长:S.top+1

读取栈顶元素

// 读栈顶元素 
bool GetTop(SqStack S, ElemType &x){        if(S.top == -1)               //栈空 报错   return false;        x = S.data[S.top];            //x记录栈顶元素 和出栈操作基本一样,唯一区别是这里top不需要-- return true; 
}

 仅为读取栈顶元素,并没有出栈操作,因此原栈顶元素依然保留在栈中
共享栈(利用栈底位置相对不变的特性,让两个顺序栈共享一个一维数组空间):
将两个栈的栈底分别设置在共享空间的两端,两个栈顶向共享空间的中间延伸

#define MaxSize 10                //定义栈中元素的最大个数
typedef struct{       ElemType data[MaxSize];       //静态数组存放栈中元素  int top0;                     //0号栈栈顶指针  int top1;                     //1号栈栈顶指针
}ShStack;// 初始化栈
void InitSqStack(ShStack &S){    S.top0 = -1;                  //初始化栈顶指针S.top1 = MaxSize;   
}/*仅当两个栈顶指针相邻(top1-top0=1)时,判断为栈满
0号栈进栈时top0先加1再赋值
1号栈进栈时top1先减1再赋值
出栈时则相反*/

栈满的条件:top0 + 1 == top1

共享栈是为了更有效地利用存储空间,两个栈的空间相互调剂,只有在整个存储空间被占满时才发生上溢,其存取数据的时间复杂度为O(1),所以对存取效率没有什么影响

3.1.3 栈的链式存储实现

采用链式存储的栈称为链栈,链栈的优点是便于多个栈共享存储空间和提高其效率,且不存在栈满上溢的情况,通常采用单链表实现,并规定所有操作都是在单链表的表头进行的


链栈的定义 和单链表的定义几乎没差别

typedef struct Linknode{        ElemType data;        //数据域    Linknode *next;       //指针域
}*LiStack;void testStack(){   LiStack L;            //声明一个链栈
}

采用链式存储,便于结点的插入与删除。链栈的操作与链表类似,入栈和出栈的操作都在链的表头进行。需要注意的是,对于带头结点和不带头结点的链栈,具体的实现会有所不同。

链栈的初始化

typedef struct Linknode{       ElemType data;      Linknode *next;
}*LiStack;// 初始化栈
bool InitStack(LiStack &L){    L = (Linknode *)malloc(sizeof(Linknode));   if(L == NULL)             return false;   L->next = NULL;    return true;
}// 判断栈是否为空
bool isEmpty(LiStack &L){    if(L->next == NULL)      return true;   else           return false;
}

入栈出栈

// 新元素入栈
bool pushStack(LiStack &L,ElemType e){  Linknode *s = (Linknode *)malloc(sizeof(Linknode));  if(s == NULL)               //内存分配失败 return false;   s->data = e;                //用结点s保存数据元素es->next = L->next;          //头插法      L->next = s;                //把s结点连到L后return true;
}// 出栈
bool popStack(LiStack &L, int &e){     if(L->next == NULL)         // 栈空不能出栈  return false;    Linknode *s = L->next;  x = s->data;       L->next = s->next;free(s);       return true;
}

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

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

相关文章

Java基础—2

1.面向对象 1.1 与面向过程区分 了解 Java是一种面向对象的编程语言,与面向过程的编程方式有明显的区别。 思维方式:面向对象编程(OOP)是基于对象的概念,强调将问题分解为对象,通过对象之间的交互来解决…

【GPT-SOVITS-02】GPT模块解析

说明:该系列文章从本人知乎账号迁入,主要原因是知乎图片附件过于模糊。 知乎专栏地址: 语音生成专栏 系列文章地址: 【GPT-SOVITS-01】源码梳理 【GPT-SOVITS-02】GPT模块解析 【GPT-SOVITS-03】SOVITS 模块-生成模型解析 【G…

Ansible管理主机的清单------------inventory

目录 一、 Ansible组成 二、inventory 主机清单 (1)主机变量使用 (2)inventory 中的变量含义 (3)组变量使用 (4)组嵌套使用 三、ansible命令 一、 Ansible组成 INVENTORY:Ansible管理主机的清单 /etc/ansible/hosts 需要管理的服务清单,(将你需要管理的主机 …

机器学习-绪论

机器学习致力于研究如何通过计算的手段、利用经验来改善系统自身的性能。在计算机系统中,“经验”通常以“数据”的形式存在,因此,机器学习所研究的主要内容,是关于在计算机上从数据中产生“模型”的算法,即“学习算法…

排序算法:快速排序(递归)

文章目录 一、创始人托尼霍尔的快速排序二、挖坑法三、前后指针法 所属专栏:C初阶 引言:这里所说的快速排序有三种,第一种是霍尔大佬自创的,还有一种叫做挖坑法,另外一种叫前后指针法 一、创始人托尼霍尔的快速排序 1.这里我们先…

VUE3 异步组件

概念 在大型项目中&#xff0c;我们可能需要拆分应用为更小的块&#xff0c;并仅在需要时再从服务器加载相关组件。Vue 提供了 defineAsyncComponent 方法来实现此功能&#xff1a; 使用 父组件 <template><div><asyncSon></asyncSon></div> <…

敏感信息泄露到接管云服务器

通过信息收集发现子域为xx.xx.com网站&#xff0c;打开先找功能点&#xff0c;测试登录&#xff0c;是微信扫描登录&#xff0c;自己太菜&#xff0c;测试一圈没测出来什么 指纹识别发现是js开发&#xff0c;如果登录或者找回密码不是扫码登录的话&#xff0c;八成是前端验证&a…

性能测试-Jmeter常用元件基础使用

一、Jmeter元件 #线程组 添加HTTP请求 #配置元件 配置元件内的元件都是用于进行初始化的东西 #监听器 监听器主要是用来获取我们使用取样器发送请求后的响应数据相关信息 #定时器 定时器主要用来控制我们多久后执行该取样器&#xff08;发送请求&#xff09; #前置处理器 前置处…

为什么手机和电视ip地址不一样

在数字化时代&#xff0c;我们每天都会与各种电子设备打交道&#xff0c;其中最常见的就是手机和电视。当我们连接到互联网时&#xff0c;这些设备都会被分配一个独特的IP地址&#xff0c;用于在网络上进行标识和通信。然而&#xff0c;您可能已经注意到&#xff0c;即使手机和…

1.MongoDB的特点与应用场景

什么是 MongoDB &#xff1f; MongoDB 是基于 C 开发的 NOSQL 开源文档数据库 &#xff0c;是最像关系型数据库的 nosql&#xff0c;功能也是最丰富的 nosql&#xff0c;它具有所以的可伸缩性&#xff0c;灵活性&#xff0c;高性能&#xff0c;高扩展性的优势。 大致有如下特…

【Stable Diffusion】入门-04:不同模型分类+代表作品+常用下载网站+使用技巧

目录 1 模型简介2 模型文件构成和加载位置2.1 存储位置2.2 加载模型 3 模型下载渠道3.1 HuggingFace3.2 Civitai 4 模型分类4.1 二次元模型4.2 写实模型4.3 2.5D模型 1 模型简介 拿图片给模型训练的这个过程&#xff0c;通常被叫做“喂图”。模型学习的内容不仅包括对具体事物…

云平台基本介绍 —— 什么是云原生及云服务器的购买和使用

云原生概述 在了解什么是云原生之前&#xff0c;我们先了解一下什么是云计算 什么是云计算 云计算是一种通过互联网提供计算资源和服务的模式。它允许用户通过网络访问虚拟化的计算资源&#xff0c;包括计算能力、存储空间和应用程序&#xff0c;而无需拥有实际的物理设备。…

uniapp h5 部署

uniapp 配置 服务器文件路径 打包文件结构 //nginx 配置 server {listen 8300;server_name bfqcwebsiteapp;charset utf-8;#允许跨域请求的域&#xff0c;* 代表所有add_header Access-Control-Allow-Origin *;#允许带上cookie请求add_header Access-Control-Allow-C…

WRF模型运行教程(ububtu系统)-- IV-1.模型相关文件参数说明【namelist.wps文件、namelist.input文件】

一、namelist.wps文件 文件位置&#xff1a;Build_WRF/WPS WPS模块有主要的三大程序geogrid.exe、ungrib.exe、metgrid.exe&#xff0c;namelist.wps文件是输入到这三大程序的配置文件。 namelist.wps文件一共包括四个部分&#xff1a;share, geogrid, ungrib和metgrid。 每个主…

2、鸿蒙学习-申请调试证书和调试Profile文件

申请发布证书 发布证书由AGC颁发的、为HarmonyOS应用配置签名信息的数字证书&#xff0c;可保障软件代码完整性和发布者身份真实性。证书格式为.cer&#xff0c;包含公钥、证书指纹等信息。 说明 请确保您的开发者帐号已实名认证。每个帐号最多申请1个发布证书。 1、登录AppGa…

PyQt5使用

安装Pyqt5信号与槽使用可视化界面编辑UI (Pyside2)ui生成之后的使用(两种方法)1 ui转化为py文件 进行import2 动态调用UI文件 安装Pyqt5 pip install pyqt5-tools这时候我们使用纯代码实现一个简单的界面 from PyQt5.QtWidgets import QApplication, QMainWindow, QPushButto…

面试笔记——Redis(缓存击穿、缓存雪崩)

缓存击穿 缓存击穿&#xff08;Cache Breakdown&#xff09;&#xff1a; 当某个缓存键的缓存失效时&#xff08;如&#xff0c;过期时间&#xff09;&#xff0c;同时有大量的请求到达&#xff0c;并且这些请求都需要获取相同的数据&#xff0c;这些请求会同时绕过缓存系统&a…

豆瓣电影信息爬取与可视化分析

目录 一、项目背景 二、代码 三、总结 一、项目背景 &#xff08;1&#xff09;利用requests库采集豆瓣网分类排行榜 (“https://movie.douban.com/chart”)中各分类类别前100部电影的相关信息并存储为csv文件。 &#xff08;2&#xff09;利用获取的13个分类类别共1300部电…

Leetcode 1. 两数之和

心路历程&#xff1a; 很简单的题&#xff0c;双层暴力就可以&#xff0c;用双指针的话快一点。暴力时间复杂度O( n 2 n^2 n2)&#xff0c;双指针时间复杂度O(nlogn) O(n) O(n) O(nlogn)。 注意的点&#xff1a; 1、题目需要返回原数组的索引&#xff0c;所以排序后还需要…

x6.js 从流程图组件库中拖拽组件到画布dnd使用

上一篇已经了解到了x6.js常用功能以及使用方法。但我们使用流程图的时候还少不了一个非常重要的功能那就是拖拽组件库里的组件进来。如下图&#xff1a; 首先是布局这块&#xff0c;拖拽组件库的视图中布局无需我们去写&#xff0c;我们只需把界面搭建好。 添加组件库 1.搭建布…