线性结构-栈

news2024/7/6 18:19:06

栈是Stack一个后进先出Last In First Out,LIFO的线性表,他要求只在表尾对数据执行删除和插入等操作。
栈就是一个线性表,可以是数组、也可以是链表。但它的操作有别于一般的线性表。栈的元素必须先进后出,也就是先进入栈的元素必须后出栈。而不能像一般的链表或数组那样从任意位置读取元素。
栈的操作只能在线性表的表尾进行,这个标为被称为栈的栈顶top,相应的表头被称为栈的栈底bottom


栈的数据必须从栈顶进入,也必须从栈顶取出,先入栈的数据在后入栈的数据下面。
栈中不含有任何数据时的状态叫作空栈,此时栈顶top等于栈底bottom。

栈的定义

前面说过,作为一个线性结构,栈既可以用数组实现,也可以用链表实现。
在大多数情况下,我们用数组来实现栈。

public class MyStack {
	int[] stack; // 用数组实现一个栈
	int top; // 栈顶索引,实际上就是栈顶位置的数组下标
	int capacity; // 栈的容量
	public MyStack(int capacity) {
		stack = new int[capacity]; // 动态初始化栈,长度为capacity
		top = 0; // 栈顶索引为0,说明此时是空栈
		this.capacity = capacity; // 初始化栈的容量
	}
    //更多操作
}

MyStack类中并没有定义栈底位置bottom的值。这是因为我们是使用数组来实现栈的,所以bottom的值恒为0。
如果采用链表的形式实现栈,则需要定义bottom的值,它应当是指向栈底节点的指针变量(引用变量)。

MyStack是我们定义的栈类,包含3个成员变量:

  • stackint[]类型的数组,说明栈将存储整型。
  • top:栈顶在数组stack中的下标,一般规定top始终指向栈顶元素的上一个空间。真正的栈顶元素是stack[top-1]
  • capacity:记录栈当前的容量,随着栈中元素不断增加,可对栈进行扩容,变量capacity的值也应随之调整。

在调用构造函数public MyStack(int capacity)初始化一个栈后。top等于bottom等于0,即栈顶等于栈底,此时栈中没有数据(空栈)

栈的基本操作

入栈

入栈就是向栈中存入数据。入栈要在栈顶进行,每当向栈顶压入一个数据,栈顶指针top都要+1,直到栈满。

public void push(int elem) {
    // 入栈操作
    if (top == capacity) {
        // 达到栈容量上限,需要扩容
        increaseCapacity();
    }
    stack[top] = elem; // 将元素elem存放在stack[top]
    top++; // top指向栈顶元素的上一个空间,此时栈顶元素为stack[top-1]
}

在数据入栈前判断栈是否已满if (top == capacity)
因为规定了top始终指向栈顶元素的上一个空间,下标top是从0开始计算的,所以**stack[top-1]**就是栈顶元素,并且**top**值等于该栈中元素的个数。当top等于capacity时,栈中元素的个数等于capacity,top已经指向stack数组的外面,所以不能再向栈中压入元素,需要调用increaseCapacity()函数对栈进行扩容。

public void increaseCapacity() {
    // 增加栈的容量
    // 初始化一个新栈,容量是原stack容量的2倍
    int[] stackTmp = new int[stack.length * 2];
    System.arraycopy(stack, 0, stackTmp, 0, stack.length);
    stack = stackTmp;
}

将参数存入栈顶,即执行stack[top] = elem;操作。
然后移动top,指向栈顶元素的上一个位置top++;

出栈

函数pop()的作用是将栈顶元素取出并返回,同时调整栈顶指针top的值-1

public int pop() {
    // 出栈操作
    if (top == 0) {
        // 栈顶等于栈底,说明栈中没有数据
        System.out.println("There are no elements in stack");
        return -111;
    }
    return stack[--top];
}

与所有数据结构一样,在执行增删操作之前,要先判断是否符合条件。
从栈顶取出元素前,需要判断栈内是否有元素。当top==0时,栈内没有元素,pop的操作将是非法的,所以需要返回一个无效值ERROR_ELEM_VALUE,在介绍“线性结构-数组”中,有一道“删除重复元素”的题目,当时将重复元素赋值为-111,也是同样的道理。一旦将某个整数赋值给常量**ERROR_ELEM_VALUE**,则该整数就不能作为栈中的有效元素了

来两道题

二/十进制转换


利用栈结构将二进制数转换为十进制数


利用栈的FILO特点,方便位权运算

首先将二进制数从高位到低位顺序入栈。然后从栈顶依次取出每一个元素。当取出第i个元素时,结果增加 2 i − 1 2^{i-1} 2i1。最终的和即为该二进制数对应的十进制数。

public class BiToDecTest {
	public static String BiToDec(String binary) {
		MyStack stack = new MyStack(10);
		int i;
		for (i = 0; i < binary.length(); i++) {
			if (binary.charAt(i) == '0') {
				stack.push(0); // 将二进制0入栈
			} else {
				stack.push(1);// 将二进制1入栈
			}
		}
		i = 0;
		int e;
		long sum = 0;
		while ((e = stack.pop()) != stack.ERROR_ELEM_VALUE) {
			sum = sum + (int) (e * Math.pow(2, i));
			i++;
		}
		return String.valueOf(sum);
	}

	public static void main(String args[]) {
		System.out.println("The result of converting 11001 to decimal number is");
		System.out.println(BiToDecTest.BiToDec("11001"));
	}
}

public static String BiToDec(String binary)String.valueOf(sum)的作用是将binary指定的二进制串转换成对应的十进制串并返回。参数**binary****String**类型,为了与之对应,函数的返回值也是**String**类型,并通过**String.valueOf()**函数将十进制转换成对应的字符串

括号匹配问题


已知表达式中只允许有两种括号:圆括号()和方括号[]。它可以任意地嵌套使用,例如[()][()()][()([])]都是合法的表达式。括号必须成对出现,[(])([)][())等不成对出现的情况是非法的。编写一个程序,判断一个括号表达式是否合法。


一道栈的经典问题

  1. 合法的情况下,第一个入栈的字符应该是左括号。
  2. 我们可以在检测到下一个字符为右括号时,弹出栈内的左括号,查看是否匹配。
  3. 如果不匹配或已经空栈,则表明括号表达式不合法。

我们介绍一段没上面那么好理解的代码:

循环遍历字符串上的字符,每个字符进行如下判断:
首先是判断是否栈空,如果栈不为空,则将栈顶c与临时字符expression.charAt(i)匹配,成功则继续遍历;不成功则再将刚刚出栈的元素塞回,并将临时字符入栈。
如果栈为空,则将临时字符expression.charAt(i)直接入栈。
如果表达式合法,所有元素都被弹出,最后结果是空栈。
因此最后一步即为判断是否为空栈,栈空则表示合法。不为空则非法。

public static boolean MatchBracket(String expression) {
    // 判断括号表达式expression是否合法
    MyStack stack = new MyStack(10); // 初始化栈
    char c;
    for (int i = 0; i < expression.length(); i++) {
        if ((c = stack.pop()) != stack.ERROR_ELEM_VALUE) {
            // 从栈中弹出了有效元素,说明栈不为空
            if (!match(c, expression.charAt(i))) {
                // 如果栈顶元素c跟expression的第i个括号
                // 不相匹配,则将c重新入栈,同时将
                // expression的第i个括号入栈
                stack.push(c);
                stack.push(expression.charAt(i));
            }
        } else {
            // 如果是空栈,说明输入的是第1个括号,因此保存在栈中
            stack.push(expression.charAt(i));
        }
    }
    if (stack.pop() != stack.ERROR_ELEM_VALUE) {
        // 栈不为空,说明表达式expression不合法,返回false
        return false;
    } else {
        return true; // 栈为空,说明表达式expression合法,返回true
    }
}

在检索完括号表达式之后,如果栈已空,说明左右括号完全匹配,即括号表达式合法。
如果栈未空,则表明输入的括号不完全匹配,也就是括号表达式非法。
对于匹配括号的函数,我们不能简单地作==的判断,因为'('注定不等于')'
如果是C++,我们可以使用map容器,右括号为索引,所括号为实值。因为我们是检测到右括号之后才去匹配左括号,所以要将右括号作为索引。
如果是Java,也有类似的容器。但在这里,我们使用更粗暴的方法。

private static boolean match(char a, char b) {
    if ((a == '(' && b == ')') ||
            (a == '[' && b == ']')) {
        return true;
    }
    return false;
}

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

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

相关文章

金三银四好像消失了,IT行业何时复苏

疫情时候不敢离职&#xff0c;以为熬过来疫情了&#xff0c;行情会好一些&#xff0c;可是疫情结束了&#xff0c;反而行情更差了&#xff0c; 这是要哪样 我心中不由一万个 草泥&#x1f434; 路过 我心中不惊有了很多疑惑和感叹 接着上一篇 一个28岁程序员入行自述和感受 自…

3年外包测试走进字节,真的泪目了.....

一提及外包测试&#xff0c;大部分人的第一印象就是&#xff1a;工作强度大&#xff0c;技术含量低&#xff0c;没有归属感&#xff01;外包工作三年总体感受就是这份工作缺乏归属感&#xff0c;心里总有一种落差&#xff0c;进步空间不大&#xff0c;接触不到核心技术&#xf…

零基础如何学习项目管理?

零基础如何学习项目管理&#xff1f;我们可以从项目管理的思维、能力、工具、书籍阅读四个方面入手—— 1.项目管理的思维 &#xff08;1&#xff09;系统思考 项目管理需要从一个系统的角度来看待问题&#xff0c;将复杂的项目分解为小的部分进行管理&#xff0c;从而达到更…

Power BI 数据模型设计及搭建——星型模型雪花模型

前言 之前的笔记提到了《Power BI 数据模型的核心概念》&#xff0c;本文继续深入讨论数据模型的设计架构&#xff0c;同时介绍两种常用的数据模型&#xff1a;星型模型和雪花模型 BI 的数据模型和数仓模型有什么不同&#xff1f; 数据仓库和Power BI中使用的数据架构模型有一…

seaborn load_dataset报错的解决方案

大家好,我是爱编程的喵喵。双985硕士毕业,现担任全栈工程师一职,热衷于将数据思维应用到工作与生活中。从事机器学习以及相关的前后端开发工作。曾在阿里云、科大讯飞、CCF等比赛获得多次Top名次。现为CSDN博客专家、人工智能领域优质创作者。喜欢通过博客创作的方式对所学的…

6000+字讲透ElasticSearch 索引设计

ElasticSearch 索引设计 在MySQL中数据库设计非常重要&#xff0c;同样在ES中数据库设计也是非常重要的 概述 我们创建索引就像创建表结构一样&#xff0c;必须非常慎重的&#xff0c;索引如果创建不好后面会出现各种各样的问题 索引设计的重要性 索引创建后&#xff0c;索引的…

Mac使用svn全教程(安装+命令操作项目)

Mac使用svn&#xff0c;包括安装以及命令检出项目提交项目&#xff0c;下面直接进入正题&#xff1a; 1.安装svn 首先Mac需要安装brew #安装brew /bin/zsh -c "$(curl -fsSL https://gitee.com/cunkai/HomebrewCN/raw/master/Homebrew.sh)"图1: 图2: 图3: 如…

java数组排序,升序和降序

文章目录 前言基本数据类型排序升序降序排列 基本数据类型包装类升序降序 对象排序升序降序 前言 对于数组的排序一直很疑惑&#xff0c;尤其是如何对数组进行降序排列&#xff0c;例如要对int[]类型的数组降序排列&#xff0c;这里来进行说明 基本数据类型排序 升序 int[]…

缓存失效的三大祸害:穿透、击穿、雪崩及应对策略详解

1、概述 缓存穿透、缓存击穿和缓存雪崩都是常见的缓存问题&#xff0c;下面分别介绍它们的定义和解决方法&#xff1a; 1&#xff09;缓存穿透 缓存穿透指的是恶意用户或攻击者通过请求不存在于缓存和后端存储中的数据来使得所有请求都落到后端存储上&#xff0c;导致系统瘫痪…

【数据库复习】第五章 数据库编程1

存储过程和触发器 PL/SQL &#xff1a; SQL的扩展 增加了过程化语句功能 基本结构是块 块之间可以互相嵌套 每个块完成一个逻辑操作 1.定义部分 DECLARE ------变量、常量、游标、异常等 定义的变量、常量等只能在该基本块中使用 当基本块执行结束时&#…

OpenCL编程指南-3.1OpenCL平台与设备

OpenCL平台 在2.1中讨论过&#xff0c;OpenCL应用的第一步是查询OpenCL平台集合&#xff0c;选择其中一个或多个平台在应用中使用。与平台关联有一个简档 (profile)&#xff0c;描述所支持的特定OpenCL版本的功能。简档可以是完全简档&#xff0c;涵盖定义为核心规范的所有功能…

超好用!免费使用的Sketch在线版真香!

在设计领域中&#xff0c;Sketch是一款非常受欢迎的矢量绘图设计软件&#xff0c;但它只支持Mac系统&#xff0c;这对于Windows用户来说是一个很大的限制。虽然有人称之为Sketch在线版&#xff0c;但实际上并不存在这样的工具。不过&#xff0c;现在有一款全新的在线协同设计工…

SpringBoot整合Mybaties增删改查

文章目录 1、填写pom.xml2、填写application.properties3、User实体4、Springboot主类5、UserMapper6、UserServise层7、UserServiseImpl8、Controller类测试 使用 Java 开发或者学习过程中&#xff0c;最避免不了的是连接和操作数据库&#xff0c;此次&#xff0c;学习如何在S…

Java之单例模式

目录 一.上节内容 1.什么是线程安全 2.线程不安全的原因 3.JMM(Java内存模型) 4.synchronized锁 5.锁对象 6.volatile关键字 7.wait()和notify() 8.Java中线程安全的类 二.单例模式 1.什么是单例 2.怎么设计一个单例 1.口头约定 2.使用编程语言的特性 三.饿汉模式…

文心一言没有体验上,看看讯飞星火认知大模型

目录 前言 正文 1.简单对话环节 1.1什么是讯飞星火认知大模型 1.2你都可以干一些什么 1.3你的训练数据库还在持续更新么 1.4今天是哪一天 1.5宇宙中有哪些目前认为可能存在生命的星球 2.辅助学习对话 2.1我想完成一篇关于CT检测技术的论文综述&#xff0c;你有什么好的…

Elasticsearch - 聚合获取原始数据并分页排序模糊查询

文章目录 概述第一步 &#xff1a; 聚合获取原始数据并分页知识点&#xff1a;bucket_sort实现分页知识点&#xff1a;获取 total -----> cardinality 去重 小结第二步 分页并支持模糊查询方式一 query 方式方式二&#xff1a; 脚本cardinality 的 script 概述 ES版本&…

4.100ASK_V853-PRO开发板支持4寸MIPI屏

0.前言 ​ 由于之前我们已经适配过RGB屏&#xff0c;如果我们去适配了4寸MIPI屏&#xff0c;那么RGB屏就不能使用了。对于4寸屏购买链接为&#xff1a; 百问网4寸MIPI屏 LCD_调试指南:https://tina.100ask.net/SdkModule/Linux_LCD_DevelopmentGuide-01/ Display_开发指南:h…

pmp学习对职场的影响有多大?

不知不觉&#xff0c;2021的进度条已经走过了一半。行业政策的变化&#xff0c;岗位的能力对比&#xff0c;都让职场竞争变得更加激烈&#xff0c;成为一名优秀且具有竞争力的项目经理好像变得越来越难了。 为什么这样说呢&#xff1f;因为各行各业在对PM要求各项专业技能的同…

ChatGPT人工智能聊天机器人的优势与应用

当今社会&#xff0c;聊天机器人(Chatbot)已经成为一种新的交互方式。而ChatGPT则是一种基于深度学习技术的聊天机器人&#xff0c;它可以模拟人类对话的过程&#xff0c;可以为人们提供快速、便捷的解决方案。以下是ChatGPT的简介和优势&#xff1a; 基本信息&#xff1a;Chat…

将区块链技术融入电梯管理系统

电梯管理系统 电梯是人们日常生活和工作中必不可少的交通工具&#xff0c;为了保障电梯的安全性和运营效率&#xff0c;需要实时监测电梯状态及事件/故障。这里可以查考网络上提供的方案&#xff0c;在电梯内部安装了各种各样的传感器&#xff0c;通过网关将收集到的数据上传到…