上海交大ACM班C++算法与数据结构——数据结构之栈

2023-11-03

上海交大ACM班C++算法与数据结构——数据结构之栈

大纲

1.栈的定义

  • 后进先出LIFO,first in last out,(先进后出FILO,first in last out)的线性表(有关线性表可查看:上海交大ACM班C++算法与数据结构——数据结构之线性表
  • 基本操作:(由于栈只能在栈顶进行操作,所以基本操作相比普通线性表要少)
    - 建栈
    - 入栈
    - 出栈
    - 读栈(读栈顶元素)
    - 查看栈是否空
  • 虚构类实现
		template <class elemType>
		class stack {
			public: 
				virtual bool isEmpty() const = 0; 
				virtual void push(const elemType &x) = 0; 
				virtual elemType pop() = 0;              
				virtual elemType top() const = 0;
				// 虚析构函数防止内存泄漏
				virtual ~stack() {}
		}; 

2.顺序栈

  • 一个数组(由于在数组头部操作元素很麻烦,可能引起元素大量移动,所以将数组头部作为栈底,尾部作为栈顶)
  • 操作时候要判断一下栈空栈满的情况
  • 类定义
		template <class elemType>
		class seqStack: public stack<elemType>{
			private:
				elemType *elem;
				int top_p;
				int maxSize;
				void doubleSpace();
			public:
				seqStack(int initSize = 10)// 析构函数
				~seqStack() { delete [] elem; }
				// 判断栈是否为空,若top_p的值为-1,返回true,否则返回false。
				bool isEmpty() const { return top_p == -1; }      
				void push(const elemType &x)// 出栈:返回栈顶元素,并把元素数量减1
				elemType pop() { return elem[top_p--]; }
				// top:与pop类似,只是不需要将top_p减1
				elemType top() const { return elem[top_p]; }
		}
  • 构造函数:按照用户估计的栈的规模申请一个动态数组。
		template <class elemType>
		seqStack<elemType>::seqStack(int initSize) {
			elem = new elemType[initSize];
			maxSize = initSize ;
			top_p = -1;  
		}
  • push(x) 入栈:将top_p加1,将x放入top_p指出的位置中。但要注意数组满的情况。
		template <class elemType>
		void seqStack<elemType>::push(const elemType &x) { 
			if (top_p == maxSize - 1)
				doubleSpace();
			elem[++top_p] = x; 
		}
  • 性能分析

    • 除了进栈操作以外,所有运算实现的时间复杂度都是O(1)。
    • 进栈运算在最坏情况下的时间复杂度是O(N)。(需要doubleSpace)
    • 均摊分析法:最坏情况在N次进栈操作中至多出现一次,平均到每次进栈操作上也是O(1)的复杂度。
  • 例题

    给出两个序列 pushed 和 poped 两个序列,其取值从 1 到n (1 ≤ n ≤ 10^5)。已知入栈序列是1 2 3 … n,如果出栈序列有可能是 poped,则输出Yes,否则输出No。每个测试点有多组数据。

    输入描述:

    第一行一个整数q,询问次数。

    接下来q个询问,对于每个询问:

    第一行一个整数n表示序列长度;

    第二行n个整数表示出栈序列。

    输出描述:

    对于每个询问输出单独一行答案。如可能,则输出Yes;反之,则输出No。

    示例 1:
    输入:
    2
    5
    5 4 3 2 1
    4
    2 4 1 3
    输出:
    Yes
    No

		#include <cstdio>
		#include <cstring>
		#include <iostream>
		#include <algorithm>
		#define N 100005 
		using namespace std;

		int a[N], b[N], s[N], top, n;

		int main() {
			int T;
			scanf("%d", &T);
			for (int i = 0; i <100000; i++)
				a[i] = i + 1;
			while (T--) {
				memset(b, 0, sizeof(b));
				memset(s, 0, sizeof(s));
				scanf("%d", &n);
				for (int i = 0; i < n; ++i) scanf("%d", &b[i]);
				int j = 0;
				top = 0;
				for (int i = 0; i < n; ++i) {
					while (j < n && (!top || s[top - 1] != b[i])) 
						s[top++] = a[j++];
					if (s[top - 1] == b[i]) 
						--top;
				}
				if (!top) printf("Yes\n");
				else printf("No\n");
			}
			return 0;
		}

3.链接栈

  • 一个单链表头指针作为栈顶(链接栈不需要头结点:头结点是为了可以对第一个结点和后续结点进行相同操作而不用分类讨论才设置的,栈只在栈顶操作元素,所以不存在这个问题)
  • 类定义
		 template <class elemType>
		class linkStack: public stack<elemType> {
			private:
				struct node {
					elemType  data;
					node *next;
					node(const elemType &x, node *N = NULL) { 
						data = x; 
						next = N;
					}
					node():next(NULL) {}
					~node() {}
				};

				node *top_p;

			public:
				// 构造函数:将top_p设为空指针
				linkStack() { top_p = NULL; }	   
				~linkStack();
				// isEmpty():判top_p是否为空指针
				bool isEmpty() const { return   top_p == NULL; }
				// push(x):在表头执行单链表的插入。
				void push(const elemType &x) { op_p = new node(x, top_p); }
				elemType pop();
				// top():返回top_p指向的结点的值。
				elemType top() const { return top_p->data; }	    
		}; 
  • 析构函数:注意需要释放空间。
		template <class elemType>
		linkStack<elemType>::~linkStack() {
			node *tmp;

			while (top_p != NULL) {
				tmp = top_p; 
				top_p = top_p ->next;
				delete tmp;
			}
		}
  • pop():出栈操作,在表头执行单链表的删除。
		template <class elemType>
		elemType linkStack<elemType>::pop() {
			node *tmp = top_p;
			elemType x = tmp->data;              

			top_p = top_p->next;                   
			delete tmp;                          
			return x;
		} 
  • 性能分析:所有运算的时间复杂度都是O(1)。

4.用栈实现递归函数

		void A(){C();D();}
		void B(){D();}
		void C(){B();}
		void D(){}
		int main()
		{
			A();
			C();
		}
		>函数的调用顺序:ACBDDCBD
  • 快排
    思路流程
		 // 每个node表示要对从left到right这一部分数据进行排序
		struct  node {
			int left;
			int right;
		};

		void quicksort( int a[],  int size) { 
			seqStack <node> st;
			int mid, start, finish;
			node s;

			if (size <= 1) return;

			// 排序整个数组
			s.left = 0; 
			s.right = size - 1;
			st.push(s);
			while (!st.isEmpty())  {
				s = st.pop(); 
				start = s.left;
				finish = s.right; 
				mid = divide(a, start, finish);
				if (mid - start > 1) { 
					s.left = start; 
					s.right = mid - 1; 
					st.push(s); 
				}
				if (finish - mid > 1) { 
					s.left = mid + 1; 
					s.right = finish;
					st.push(s)}
			}
		}
  • 练习题:括号配对检测

    假设一个表达式有英文字母(小写)、运算符+ — * /和左右小(圆)括号构成,以@作为表达式的结束符。请编写一个程序检查表达式中的左右圆括号是否匹配,若匹配,则返回YES;否则返回NO。表达式长度小于255,左圆括号少于20个。

    输入描述:

    一行,输入的表达式。

    输出描述:

    一行,YES或NO

    示例 1:
    输入:
    2*(x+y)/(1-x)@
    输出:
    YES

		 #include <cstdio>
		#include <cstring>
		#include <iostream>
		#include <algorithm>

		using namespace std;

		char s[1010];

		int main() {
			int a = 0;
			scanf("%s", s);
			int len = strlen(s);
			for (int i = 0; i < len; i++) {
				if (s[i] =='(') {
					a++;
				}
				if (s[i] == ')') {
					a--;
					if (a < 0) {
						printf("NO");
						return 0;
					}
				}
			}
			if (a == 0)
				printf("YES");
			else
				printf("NO");
			return 0; 
		}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

上海交大ACM班C++算法与数据结构——数据结构之栈 的相关文章

随机推荐

  • Springboot

    Spring Boot能快速创建出生产级别的Spring应用 使spring开发变得简单 无需编写各种配置 Spring Boot是整合Spring技术栈的一站式框架 Spring Boot是简化Spring技术栈的快速开发脚手架 Spri
  • Docker容器与虚拟化技术:Harbor私有仓库部署与迁移

    目录 一 理论 1 本地私有仓库 2 Harbor 二 实验 1 Docker搭建本地私有仓库 2 docker compose部署及配置 3 harbor部署及配置 4 登录创建项目 5 在其他客户端上传镜像 6 harbor维护 7 移
  • Spark 系列教程(2)运行模式介绍

    Spark 运行模式 Apache Spark 是用于大规模数据处理的统一分析引擎 它提供了 Java Scala Python 和 R 语言的高级 API 以及一个支持通用的执行图计算的优化引擎 Spark Core 是 Spark 的核
  • 【AI思维空间】ChatGPT纵横编程世界,点亮智慧火花

    作者 京东零售 王英杰 概述 该文档记录云交易开发小伙伴儿们在开发过程中的实际应用案例 记录典型案例 以解决开发过程中的实际问题为主 涵盖设计方案 编码 测试 集成 部署等等 目的 贡献最佳实践 分享心得 共同成长 1 怎样构造Prompt
  • chatgpt赋能python:Python多行连一行:简便省事的代码优化方法

    Python多行连一行 简便省事的代码优化方法 在Python编程中 经常会遇到多行代码的情况 这不仅降低了代码的可读性 也增加了调试的难度 为了解决这个问题 Python提供了多行连一行 以反斜杠 结尾 的语法 以便将多行代码转化为单行代
  • 动态规划学习

    动态规划 动态规划简介 什么是动态规划 动态规划和递归区别 动态规划和分治区别 动态规划解决步骤 动态规划类别 1 坐标型动态规划 2 位操作型动态规划 3 背包型动态规划 动态规划简介 什么是动态规划 动态规划是运筹学中用于求解决策过程中
  • python已知两边求第三边_已知两边求第三边公式

    如果是三角形是直角三角形 知道两边 可以用勾股定理求出第三边 如果是三角形是普通三角形 锐角 钝角三角形 那这个条件下只能求出第三边的范围 两边之和大于第三边 两边之差小于第三边 求边公式 只知道两边相等如果一个是底边一个是腰的话 这个是正
  • 数学建模写作与排版

    1 2 数学建模 快速入门 上 1 3 数学建模 快速入门 下 写作部分 首页 论文标题 摘要 关键词 一 问题重述 二 问题分析 三 模型假设 四 符号说明 五 模型的建立与求解 六 模型的分析与检验 七 模型的评价 改进和推广 八 参考
  • NFS环境搭建

    NAT模式下 安装NFS sudo apt install nfs kernel server 重启NFS服务器 sudo etc init d nfs kernel server restart 修改配置文件 etc exports 在里
  • 灰色关联分析法

    与灰色预测模型一样 比赛不能优先使用 灰色关联往往可以与层次分析结合使用 层次分析用在确定权重上面 1 确定比较对象 评价对象 就是数据 并且需要进行规范化处理 就是标准化处理 见下面例题的表格数据 和参考数列 评价标准 一般该列数列都是1
  • windows下能搭建php-fpm吗 phpstudy

    这个Windows和Linux系统是不一样的 因为一般nginx搭配php需要php fpm中间件 但是Windows下需要第三方编译 下载的包里有php cgi exe 但不是php fpm如果想在windows上跑php fpm 据说可
  • 【ES】分布式集群

    ES 分布式集群 单节点集群 故障转移 水平扩容 应对故障 路由计算 本文主要参考尚硅谷的资料 少部分自己原创 有错误之处请指出 单节点集群 node 1001配置如下 集群名称 节点之间要保持一致 cluster name my elas
  • C++ PCL库实现最远点采样算法

    最远点采样 Farthest Point Sampling 简称FPS 是点云处理领域中的一种重要算法 用于对点云数据进行快速降采样 最早的最远点采样算法应该是在计算机图形学领域中提出的 用于在三维模型上进行表面重建 随着点云处理技术的发展
  • HDU--1200:To and Fro (字符串)

    1 题目源地址 http acm hdu edu cn showproblem php pid 1200 2 解题代码 include
  • 服务器远程使用什么协议,云服务器远程是什么协议

    云服务器远程是什么协议 内容精选 换一换 弹性云服务器 Elastic Cloud Server 是一种可随时自动获取 计算能力可弹性伸缩的云服务器 可帮助您打造可靠 安全 灵活 高效的应用环境 确保服务持久稳定运行 提升运维效率 WinS
  • Jira 史诗指南 (2022)

    Jira 就是为了完成工作 而 Epics 是实现该目标的一种有价值的方式 一般来说 Epics 适用于顾名思义 不会在一天内完成但会 的工作 史诗 在本指南中 我们将分解什么是 Epics 它们的用途 以及它们的用途 以及如何创建和使用它
  • Qt 应用程序显示页面的方法

    1 在qt窗口中显示页面 1 pro中添加 QT webkitwidgets 2 添加头文件 include
  • Swift4.0 guard,Array,Dictionary

    guard的使用 guard是Swift新增语法 guard语句必须带有else语句当条件表达式为true时候跳过else语句中的内容 执行语句组内容 条件表达式为false时候执行else语句中的内容 跳转语句一般是return brea
  • Web服务器群集:Nginx网页及安全优化

    目录 一 理论 1 Nginx网页优化 2 Nginx安全优化 3 Nginx日志分割 二 实验 1 网页压缩 2 网页缓存 3 连接超时设置 4 并发设置 5 隐藏版本信息 6 脚本实现每月1号进行日志分割 7 防盗链 三 总结 一 理论
  • 上海交大ACM班C++算法与数据结构——数据结构之栈

    上海交大ACM班C 算法与数据结构 数据结构之栈 1 栈的定义 后进先出LIFO first in last out 先进后出FILO first in last out 的线性表 有关线性表可查看 上海交大ACM班C 算法与数据结构 数据