数据结构与算法--栈

news2024/12/25 9:31:45

文章目录

    • 知识回顾
      • 顺序存储结构的优缺点
      • 链式存储结构的优缺点
    • 数据结构的三个方面
    • 栈的定义与特点
    • 栈的基本运算
    • 栈的存储结构与实现
      • 顺序栈
        • 入栈操作
        • 出栈操作
      • 链栈
        • 入栈操作
        • 入栈操作
    • 栈的应用
      • 数制转换
      • 表达式求值
      • 中缀表达式向后缀表达式的转换
      • 后缀表达式的求值过程
    • 总结

知识回顾

  • 顺序表:使用一组地址连续的存储单元依次存储线性表中的元素。
  • 单链表:使用一组地址任意的存储单元依次存储线性表中的元素。

顺序存储结构的优缺点

优点

  • 比较简单。
  • 随机存取,存取速度快。
  • 每个结点只存储元素自身信息,不需额外空间。

缺点

  • 需占一片连续的存储空间,且需事先估计存储空间的大小。
  • 插入和删除操作时,需移动大量的元素,效率较低。

链式存储结构的优缺点

优点

  • 不需占用连续存储空间,使用链表前不用事先估计存储空间大小。
  • 插入和删除操作时,不需要移动大量元素。

缺点

  • 操作算法较复杂。
  • 不能随机存取。
  • 需要额外空间来表示元素间的关系,空间代价较高。

数据结构的三个方面

  1. 数据的逻辑结构:线性结构、非线性结构。
  2. 数据的存储结构(亦称物理结构):顺序存储、链式存储。
  3. 数据的运算:检索、排序、插入、删除、修改等。

栈的定义与特点

  • 栈(Stack)是限定只能在表的一端进行插入删除操作的线性表

  • 在这里插入图片描述

  • 允许插入和删除运算的一端称为栈顶(top),不允许插入和删除的另一端称为栈底(bottom)。

  • 在栈顶进行的插入操作称为入栈或进栈(push),在栈顶进行的删除操作称为出栈或退栈(pop)

  • 特点:后进先出(LIFO, Last In First Out)。

  • 在这里插入图片描述

栈的基本运算

  • 栈抽象数据类型=逻辑结构+基本运算(运算描述)
  • InitStack(&s):初始化栈。构造一个空栈s。
    
  • DestroyStack(&s):销毁栈。释放栈s占用的存储空间。
    
  • StackEmpty(s):判断栈是否为空:若栈s为空,则返回真;否则返回假。
    
  • Push(&S,e):进栈。将元素e插入到栈s中作为栈顶元素。
    
  • Pop(&s,&e):出栈。从栈s中退出栈顶元素,并将其值赋给e。
    
  • GetTop(s,&e):取栈顶元素。返回当前的栈顶元素,并将其值赋给e。
    
  • 入栈(push):在栈顶进行的插入操作。
  • 出栈(pop):在栈顶进行的删除操作。

栈的存储结构与实现

顺序栈

  • 栈中元素逻辑关系与线性表的相同,栈可以采用与线性表相同的存储结构。
  • 使用数组表示栈。
  • 栈顶通过下标指示。
  • 如何用数组表示栈?
    • 存储栈元素
    • 栈的逻辑结构表示
    • 指示栈的栈顶
      在这里插入图片描述
#define MaxSize 100 // 定义常量MaxSize为100,作为栈的最大容量

// 定义ElemType类型,这里假设ElemType是某种基本数据类型,比如int
typedef int ElemType;

// 定义顺序栈的结构体
typedef struct {
    ElemType data[MaxSize]; // 一个数组,用于存储栈中的元素,大小为MaxSize
    int top;                // 一个整型变量,用于指向栈顶元素的索引
} SqStack; // 用typedef为这个结构体定义一个新的类型名SqStack,代表顺序栈

MaxSize为顺序栈的最大容量;
top为栈顶元素的下标,0 <= top <= MaxSize-1
栈空:top = -1;
栈满:top = MaxSize-1
在这里插入图片描述

入栈操作
  • 操作步骤:
    ①判断栈是否已满,若满则产生上溢出错误,退出算法,否则执行第②步;
    在这里插入图片描述

②栈顶下标增一,指向新的栈顶位置;
在这里插入图片描述

③将新元素置于栈顶。
在这里插入图片描述

bool Push(SqStack &S, ElemType item)
{
  if (S.top == MaxSize - 1)
  {
    cout << "栈满" << endl;
    return false;
  }
  S.top++;
  S.data[S.top] = item;
  return true;
}
出栈操作

操作步骤:
①判断栈是否为空,若空则产生下溢出错误,退出算法,否则执行第②步;
在这里插入图片描述

②栈顶元素出栈;
在这里插入图片描述

③栈顶下标减一,指向新的栈顶位置;
在这里插入图片描述

bool Pop(SqStack &S, ElemType &item)
{
  if (S.top == -1)
  {
    cout << "栈空" << endl;
    return false;
  }
  item = S.data[S.top];
  S.top--;
  return true;
}

链栈

  • 使用链式结构表示栈。
  • 栈顶通过指向单链表第一个元素结点的位置指示。
  • 如何用链式结构表示栈?
    如何存储栈元素
    怎样表示栈的逻辑结构
    怎样指示栈的栈顶
    在这里插入图片描述
typedef struct LNode
{
  ElemType data;      //数据域
  struct LNode *next; //后继结点指针
} LinkStNode;         //链栈结点类型
  • S:单链表头指针,指向头结点。
  • 栈顶:单链表第一个元素结点的位置,即头结点的后一个位置。
  • 在这里插入图片描述
入栈操作
bool Push(LinkStNode *S, ElemType item)
{ //带头结点单链表的表头插入法
  LinkStNode *t = new LinkStNode; //①生成新结点
  if (t == NULL)
  {
    cout << "内存不足";
    return false;
  }
  t->data = item;
  //②在栈顶插入新结点
  t->next = S->next;
  S->next = t; //③
  return true;
}

在这里插入图片描述

入栈操作
bool Pop(LinkStNode *S, ElemType &item)
{ //删除单链表的第一个元素结点
  //①判断栈是否为空
  if (S->next == NULL)
  {
    cout << "栈空";
    return false;
  }
  //②删除栈顶元素
  LinkStNode *t = S->next;
  S->next = t->next;
  item = t->data;
  delete t;
  return true;
}

在这里插入图片描述

栈的应用

数制转换

  • 原理:基于除留余数法。
    • 十进制数N和其他d进制数的转换基于下列原理:
    • N = (N div d)×d + N mod d (div 为整除,mod 为求余)
  • 操作步骤:将数字除以进制数,取商和余数,直至商为零。
    • ① 将N除以d,取其商和余数;
    • ② 判断商是否为零;
    • 若商不为零,则将商赋值给N,并转向① ;
    • 若商为零,则转换结束。
      最先求得的余数是结果的最低位,最后求得的余数是结果的最高位,即运算顺序与结果的各位数字的次序相反,符合栈的特点。
void Convert(int num, int d)
{ //num为待转换数,d为进制
  SqStack S;  ElemType result;  int r; //余数
  char ch[] = "0123456789ABCDEF"; //进制所使用的字符
  InitStack(S);
  while (num != 0)
  { r = num % d;    //取余数r
    Push(S, ch[r]); //余数入栈
    num = num / d;  //利用商进行下一次运算
  }
  while (!StackEmpty(S))
  { Pop(S, result);
    cout << result;
  }
}

表达式求值

  • 算术表达式的定义:任何一个表达式都是由操作数、运算符和界限符组成。

  • 算术表达式的三种形式:前缀、中缀、后缀。

    • 前缀表达式=运算符+操作数1+操作数2
    • 中缀表达式=操作数1+运算符+操作数2
    • 后缀表达式=操作数1+操作数2+运算符
  • 中缀表达式的运算规则和特点。

    • 先计算括弧内后计算括弧外;
    • 在无括号或同层括号内时,先乘除后加减;
    • 同一优先级运算,先左后右。
    • 示例:
      • 16-4×(2+1)
      • 结果:4
      • (110+16)/(16-9×(4+3))
      • 结果:-2
      • 中缀表达式的运算不一定能按运算符出现的先后次序进行,它不仅要依赖运算符优先级,而且还要处理括号。
        因此,中缀表达式不方便计算机程序对表达式进行求值。
  • 后缀表达式的特点与运算规则。

    • 后缀表达式没有括号,也无需考虑优先级,运算符在式中出现的顺序恰为表达式的运算顺序;方便程序进行求值。
    • 对比:
    • 中缀表达式:
    • a - b * ( c / d ) + e
    • 后缀表达式:
    • a b c d / * - e +

中缀表达式向后缀表达式的转换

  • 转换思路:根据运算符的优先级决定运算顺序。
    • 对原表达式中出现的每一个运算符是否即刻进行运算取决于在它后面出现的运算符;
    • 如果它的优先级“高或等于”后面的运算,则它的运算先进行,否则就得等待在它之后出现的所有优先级高于它的“运算”都完成之后再进行。
  • 使用栈存放运算符。
    • ( )
    • × ÷
    • + -

用到的数据结构:
char数组 str1:存放中缀表达式,以 # 结尾;
char数组 str2:存放转换后的后缀表达式;
char型栈 S:存放运算符,包括 * / + - ( #
其中,* / 优先级设为2,
+ - 优先级设为1,
为处理方便,将 ( 优先级设为3,# 优先级设为0

while(str1[i] != ‘\0’)

  • 如果str1[i]是操作数,则将str1[i]存到str2中;
  • 如果str1[i]是‘(’,则str1[i]入栈;
  • 如果str1[i]是‘)’,则将栈S中‘(’之前的运算符依次出栈并存放到str2中,然后将栈S中‘(’出栈;
  • 如果str1[i]是四则运算符,则还须比较str1[i]与栈顶运算符top的优先级,若str1[i] ≤ top (除栈顶- 运算符为“(”外),则依次出栈并存入到str2中,然后将str1[i]进栈;
    str1扫描完毕后,将栈S中剩余运算符依次出栈并存入str2中。

后缀表达式的求值过程

  • 从左向右扫描后缀表达式,操作数入栈,运算符出栈操作数并执行运算。
  • 每个运算符和在它之前出现且紧靠它的两个操作数构成一个最小表达式;
  • 对后缀式从左向右“扫描”,若读入的是一个操作数,就将它入数值栈;
  • 若读入的是一个运算符op,就从数值栈中连续出栈两个元素(两个操作数),假设为x2和x1,计算x1 op x2之值,并将计算结果入数值栈;
  • 对整个后缀表达式读入结束时,栈顶元素就是计算结果。

总结

  • 栈的后进先出特性。
  • 顺序栈和链栈的入栈、出栈操作。
  • 栈在中缀表达式转换为后缀表达式中的应用。

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

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

相关文章

Telnet和SSH配置学习笔记

1. Telnet应用场景 为方便通过命令行管理设备&#xff0c;可以使用Telnet协议对设备进行管理。 Telnet协议与使用Console接口管理设备不同&#xff0c;无需专用线缆直连设备的Console接口&#xff0c;只要IP地址可达、能够和设备的TCP 23端口通信即可。 支持通过Telnet协议进…

Redis基础总结、持久化、主从复制、哨兵模式、内存淘汰策略、缓存

文章目录 Redis 基础Redis 是什么&#xff0c;有哪些特点为什么要使用 Redis 而不仅仅依赖 MySQLRedis 是单线程吗Redis 单线程为什么还这么快 Redis 数据类型和数据结构五种基本数据结构及应用场景其他数据类型Redis 底层数据结构 Redis 持久化数据不丢失的实现AOF 日志RDB 快…

如何理解复信号z的傅里叶变换在频率v<0的时候恒为0,是解析信号

考虑例子2.12.1的说法。 首先我尝试解释第二个说法。需要注意一个事实是 实函数f的傅里叶变换F的实部是偶函数&#xff0c;虚部是奇函数。如图所示&#xff1a; 注意的是这个图中虽然是离散傅里叶变换的性质&#xff0c;但是对于一般的傅里叶变换的性质是适用的。 推导过程如下…

Tecplot安装error找不到指定模块之解决方案

最近有小伙伴反应&#xff0c;在安装Tecplot 2023版本时&#xff0c;参考教程来操作很顺利&#xff0c;但是在开启软件后&#xff0c;有一个error弹窗&#xff0c;内容如下&#xff1a; 随后用中英文翻译&#xff1a;找不到指定模块 同时&#xff0c;软件内部的Tool工具栏打不…

液位传感器- 从零开始认识各种传感器【二十四期】

液位传感器|从零开始认识各种传感器 1、什么是液位传感器 &#xff1f; 液位传感器是一种用于检测和测量液体位置和高度的装置&#xff0c;广泛应用于工业、农业、环保和家庭等领域。液位传感器可以实时监测液体的水平&#xff0c;以实现自动化控制和安全防护。 2、液位传感器…

java之方法引用 —— ::

目录 一、简介 二、引用静态方法 1.格式 2.示例 ​编辑 3.条件解析 三、引用成员方法 1.格式 2.示例 四、引用构造方法 1.格式 2.示例 五、类名引用成员方法 1.格式 2.略微不同的方法引用规则 3.示例 六、引用数组的构造方法 1.格式 2.示例 一、简介 方…

C语言笔记39 •数据结构--栈队列-OJ•

栈&队列-OJ 1.给定一个只包括 (&#xff0c;)&#xff0c;{&#xff0c;}&#xff0c;[&#xff0c;] 的字符串 s &#xff0c;判断字符串是否有效。 有效字符串需满足&#xff1a; (1).左括号必须用相同类型的右括号闭合。 (2).左括号必须以正确的顺序闭合。 (3).每个右括…

MQ消息队列篇:三大MQ产品的必备面试种子题

MQ有什么用&#xff1f; MQ&#xff08;消息队列&#xff09;是一种FIFO&#xff08;先进先出&#xff09;的数据结构&#xff0c;主要用于实现异步通信、削峰平谷和解耦等功能。它通过将生产者生成的消息发送到队列中&#xff0c;然后由消费者进行消费。这样&#xff0c;生产…

【Kubernetes】k8s集群中kubectl的陈述式资源管理

目录 一.k8s集群资源管理方式分类 1.陈述式资源管理方式 2.声明式资源管理方式 二.陈述式资源管理方法 三.kubectl命令 四.项目生命周期 1.创建 kubectl create命令 2.发布 kubectl expose命令 3.更新 kubectl set 4.回滚 kubectl rollout 5.删除 k…

notes for datawhale summer camp chemistry task3

Transformer transformer的诞生 循环神经网络&#xff1a;由于所有的前文信息都蕴含在一个隐向量里面&#xff0c;这会导致随着序列长度的增加&#xff0c;编码在隐藏状态中的序列早期的上下文信息被逐渐遗忘。 卷积神经网络&#xff1a;受限的上下文窗口在建模长文本方面天…

木卫四发布《2024半年度汽车漏洞及威胁情报-简报》

随着智能汽车技术的飞速发展&#xff0c;其安全问题也日益成为行业关注的焦点。木卫四威胁情报中心对2024年上半年国内外智能汽车领域的漏洞情报及安全事件进行了全面研究和分析&#xff0c;发布了《2024半年度汽车漏洞及威胁情报-简报》。本报告中智能汽车威胁情报的来源多样&…

宏集方案 | 传统建筑智能化改造,迈向物联新时代

前言 智能建筑涉及多个系统的集成&#xff0c;如照明、空调、安防等&#xff0c;这些系统的兼容性和协调运作是一大挑战。然而&#xff0c;传统的工业建筑和商业楼宇受早期设计的局限&#xff0c;多个控制系统间互不兼容&#xff0c;并且难以重新部署通信线缆。 针对传统建筑…

Java:查看线程信息

示例用代码 public class Main {static class MyThread extends Thread {Overridepublic void run() {while (true) {System.out.println("hello thread");try {Thread.sleep(1000);} catch (InterruptedException e) {throw new RuntimeException(e);}}}}public st…

【Canvas与艺术】九角大楼

【成图】 【代码】 <!DOCTYPE html> <html lang"utf-8"> <meta http-equiv"Content-Type" content"text/html; charsetutf-8"/> <head><title>九角大楼</title><style type"text/css">.cen…

“光影魔术手”:一款让照片编辑更高效的软件工具

&#x1f680;&#x1f680;&#x1f680; 摄影爱好者和技术控们&#xff0c;想要照片编辑技能更上一层楼吗&#xff1f;“光影魔术手”带你探索照片美化的高级技巧&#xff0c;这款软件不仅是工具&#xff0c;更是你的技术利器&#xff01; &#x1f308;【专业调色功能解析】…

AS400==使用COBOL写个HELLWORLD

登录后输入命令WRKOBJPDM 可以看到在我的lib下拥有的FILES列表 随便选一个&#xff0c;在OPT输入12回车打开这个FILE&#xff0c;最下面一排提示了&#xff0c;F6创建一个新的MEMBER输入这个FILE FILE相当于文件夹&#xff0c;MEMBER相当于一个代码文件test.py。 移动光标输入…

Leetcode—400. 第 N 位数字【中等】

2024每日刷题&#xff08;151&#xff09; Leetcode—400. 第 N 位数字 算法思想 参考自k神 实现代码 class Solution { public:int findNthDigit(int n) {int digitSize 1;int startNum 1;long long count 9;while(digitSize * count < n) {n - count * digitSize;di…

用Python打造精彩动画与视频,5.1 Matplotlib基础及其动画功能

5.1 Matplotlib基础及其动画功能 在本小节中&#xff0c;我们将介绍Matplotlib的基础知识及其动画功能。Matplotlib是Python中最流行的绘图库之一&#xff0c;它可以生成静态、动态和交互式的图表。通过Matplotlib的动画模块&#xff0c;我们可以创建各种动画效果&#xff0c;…

达梦数据库系列—44.SQL调优

目录 SQL优化思路 1、定位慢sql 2、SQL分析方法 2.1 执行计划 2.2 ET 工具 2.3 dbms_sqltune 工具 3、SQL语句优化 3.1 索引 3.2 SQL语句改写 3.3 表设计优化 3.4 表的连接方式 3.5 HINT 4、统计信息 SQL优化思路 1、定位慢sql 待优化的SQL大致可分为两类&#…

PCIe学习笔记(15)

设备就绪状态 (Device Readiness Status&#xff0c;DRS)消息 &#xff08;Device Readiness Status (DRS) 是PCIe规范中引入的一种机制&#xff0c;旨在改进设备初始化和就绪状态的检测与报告。 在以往的PCIe版本中&#xff0c;系统通常依赖于固定的超时机制来判断设备是否已…