栈是限制插入和删除只能在一个位置上进行的表,该位置是表的末端,叫做栈顶。对栈的基本操作有push(进栈)和pop(出栈),对空栈进行push和pop,一般被认为栈ADT的一个错误。当push时空间用尽是一个实现限制,而不是ADT错误。栈有时又叫做LIFO(后进先出)表。

基本概念

允许插入和删除的一端称为栈顶(top),另一端称为栈底(bottom),不含任何数据元素的栈称为空栈。栈又称为后进先出的线性表.

栈的顺序存储结构

栈的数序结构可以使用数组来实现,栈底是:下标为0的一端

栈的链式存储结构

栈的实现
栈的实现,一般分为两种形式,链式结构和数组。两者均简化了ArrayList和LinkedList中的逻辑。

栈的数组实现

抽象出栈的必备接口

public interface Stack<T> {boolean isEmpty();void push(T data);T pop();int size();
}

栈的数组实现形式

public class ArrayStack<T> implements Stack<T>, Iterable {private T[] mArray;private int mStackSize;private static final int DEFAULT_CAPACITY = 10;public ArrayStack(int capacity) {if (capacity < DEFAULT_CAPACITY) {ensureCapacity(DEFAULT_CAPACITY);} else {ensureCapacity(capacity);}}public boolean isEmpty() {return mStackSize == 0;}public int size() {return mStackSize;}public void push(T t) {if (mStackSize == mArray.length) {ensureCapacity(mStackSize * 2 + 1);}mArray[mStackSize++] = t;}public T pop() {if (isEmpty()) {throw new EmptyStackException();}T t = mArray[--mStackSize];mArray[mStackSize] = null;//调整数组的大小,防止不必要的内存开销if (mStackSize > 0 && mStackSize < mArray.length / 4) {ensureCapacity(mArray.length / 2);}return t;}private void ensureCapacity(int newCapacity) {T[] newArray = (T[]) new Object[newCapacity];for (int i = 0; i < mArray.length; i++) {newArray[i] = mArray[i];}mArray = newArray;}@Overridepublic Iterator iterator() {return null;}private class ArrayStackIterator implements Iterator<T> {@Overridepublic boolean hasNext() {return mStackSize > 0;}@Overridepublic T next() {returnmArray[--mStackSize];}}
}

对象游离

Java的垃圾收集策略是回收所有无法被访问对象的内存,如果我们pop()弹出对象后,不调用如下代码,就会造成游离,因为数组中仍然持有这个对象的引用,保存一个不需要的对象的引用,叫做游离。

mArray[mStackSize] = null;

动态调整数组大小
pop()中,删除栈顶元素后,如果栈的大小小于数组的1/4,就将数组的大小减半,这样栈永远不会溢出,使用率也不会小于1/4。

栈的链表实现
采用链式存储结构的栈,由于我们操作的是栈顶一端,因此这里采用单链表(不带头结点)作为基础,直接实现栈的添加,获取,删除等主要操作即可。

链栈的出入栈操作
链栈的入栈操作:

链栈的出栈操作:

private int mSize;
private Node<T> endNote;
private int modCount;public LinkedStack() {init();
}private void init() {endNote = new Node<T>(null, null);modCount++;
}@Override
public boolean isEmpty() {return mSize == 0;
}@Override
public void push(T data) {Node<T> newNote = new Node<T>(data, null);endNote.mNext = newNote;mSize++;modCount++;
}@Override
public T pop() {if (endNote.mNext == null) {throw new NoSuchElementException();}T t = endNote.mNext.mData;endNote.mNext = endNote.mNext.mNext;mSize--;modCount++;return t;
}@Override
public int size() {return mSize;
}@Override
public Iterator iterator() {return new LinkedStackIterator();
}private static class Node<T> {private Node<T> mNext;private T mData;public Node(T data, Node<T> next) {mData = data;mNext = next;}
}private class LinkedStackIterator implements Iterator<T> {private Node<T> currentNode = endNote.mNext;private int expectedModCount = modCount;@Overridepublic boolean hasNext() {return currentNode != null;}@Overridepublic T next() {if (modCount != expectedModCount) {throw new ConcurrentModificationException();}if (!hasNext()) {throw new NoSuchElementException();}T t = currentNode.mData;currentNode = currentNode.mNext;return t;})
}

时间复杂度对比

顺序栈复杂度


可知栈的主要操作都可以在常数时间内完成,这主要是因为栈只对一端进行操作,而且操作的只是栈顶元素。

栈的经典实用

逆波兰表达式法
标准四则运算表达式—中缀表达式
这里写图片描述
我们在小学学习的四则运算表达式就是中缀表达式 ,但是计算机是不认识中缀表达式的,它采用的是后缀表达式

计算机采用—后缀表达式
这里写图片描述

计算规则:

它的规则是,从头开始遍历,遇到数字进行压栈,遇到运算符号,将栈顶开始的两个元素进行运算符操作后,弹栈,结果进栈,931遇到“—”时,进行3-1=2,将2进栈,然后3进栈,遇到“*”,3*2=6进栈,遇到“+”,进行9+6=15进栈,然后10和2进栈,遇到“/”,进行10/2后结果进栈,最后是15+5=20,就完成了后缀表达式的计算操作。

中缀表达式转后缀表达式


数字输出,运算符进栈,括号匹配出栈,是当栈顶是运算符时,又压进来一个运算符,如果压进来的运算符优先级比栈顶的高,则这个压进来的运算符出栈。

如果我们见到任何其他的符号(+,*,(),那么我们从栈中弹出栈元素直到发现优先级更低的元素为止。有一个例外:除非是在处理一个)的时候,否则我们决不从栈中移走(。对于这种操作,+的优先级最低,而(的优先级最高。当从栈弹出元素的工作完成后,我们再将操作符压入栈中。

转载地址 : http://blog.csdn.net/u012124438/article/details/77815937

Java数据结构与算法解析(二)——栈相关推荐

  1. Java数据结构与算法(二)

    Java数据结构与算法(二) 第六章 递归 1 递归应用场景 2 递归的概念 3 递归调用机制 4 递归能解决什么样的问题 5 递归需要遵守的重要规则 6 递归-迷宫问题 6.1 迷宫问题 6.2 代 ...

  2. Java数据结构和算法(二):数组

    上篇博客我们简单介绍了数据结构和算法的概念,对此模糊很正常,后面会慢慢通过具体的实例来介绍.本篇博客我们介绍数据结构的鼻祖--数组,可以说数组几乎能表示一切的数据结构,在每一门编程语言中,数组都是重要 ...

  3. Java数据结构和算法(二)——数组

    上篇博客我们简单介绍了数据结构和算法的概念,对此模糊很正常,后面会慢慢通过具体的实例来介绍.本篇博客我们介绍数据结构的鼻祖--数组,可以说数组几乎能表示一切的数据结构,在每一门编程语言中,数组都是重要 ...

  4. Java数据结构与算法解析(一)——表

    本节我们讨论常见常用的数据结构--表. 如果要通俗简单的说什么是表,那我们可以这样说:按顺序排好的元素集合就是表. 表的概述 抽象数据类型是带有一组操作的一些对象的结合 1.定义: 线性表是一个线性结 ...

  5. java算法概述,Java数据结构与算法基础(一)概述与线性结构

    Java数据结构与算法基础(二)递归算法 Java数据结构与算法基础(一)概述与线性结构 学习目的:为了能更顺畅的读很多底层API代码和拓宽解决问题的思路 一.数据结构概述 1.数据结构是什么?数据与 ...

  6. java树的基本知识_Java数据结构和算法(二)树的基本操作

    Java数据结构和算法(二)树的基本操作 一.树的遍历 二叉树遍历分为:前序遍历.中序遍历.后序遍历.即父结点的访问顺序 1.1 前序遍历 基本思想:先访问根结点,再先序遍历左子树,最后再先序遍历右子 ...

  7. Java数据结构和算法(六)——前缀、中缀、后缀表达式

    前面我们介绍了三种数据结构,第一种数组主要用作数据存储,但是后面的两种栈和队列我们说主要作为程序功能实现的辅助工具,其中在介绍栈时我们知道栈可以用来做单词逆序,匹配关键字符等等,那它还有别的什么功能吗 ...

  8. Java数据结构和算法(第二版)

    Java数据结构和算法(第二版) 下载地址 https://pan.baidu.com/s/112D5houIgu0eMs_i5o0Ujw 扫码下面二维码关注公众号回复 100066获取分享码 本书目 ...

  9. 数据结构 - Java -韩顺平 图解Java数据结构和算法

    数据结构 Lesson 1 数据结构的知识总结 1. 几个经典的算法面试题 2. 线性结构与非线性结构 2.1 稀疏数组 sparsearray 2.2 队列 2.2.1 顺序队列: 2.2.2 环形 ...

最新文章

  1. Docker(swarm mode)在一段时间不用后无法启动
  2. Invalid ADAPTORNAME specified. Type 'imaqhwinfo' for a list of available ADAPTORNAMEs. Image acquisi
  3. 开发软件真是一件有意思的事情
  4. 美团面试动态规划——整数拆分
  5. 错误 No package ‘vulkan‘ found 解决办法
  6. HarmonyOS之常用组件TabList与Tab的功能和使用
  7. 论文浅尝 | 基于对抗学习的弱监督知识图谱对齐
  8. Intel 64/x86_64/IA-32/x86处理器 - 锁原子操作(1) - 处理器保证的原子操作
  9. windows下使用conda命令在anaconda环境中安装caffe
  10. ioctl 详细说明
  11. jQuery addClass
  12. Docker error : no space left on device docker 空间不足
  13. 分享一个奇葩SM2258XT板子(100-H00112581-590)没有CE跳线,只有CE飞线,顺便量产开卡
  14. 驱动精灵修复服务器,驱动精灵系统漏洞需要修复吗
  15. 第二届中国计量大学ACM程序设计竞赛个人赛(同步赛)A -Little Gyro and Sort【签到题?】
  16. Linux环境下配置虚拟ip,方法2:单网卡绑定多IP
  17. 关于 Glide 加载图片圆角问题
  18. html5 frog jump,frog-jump
  19. 信用百度公司商标信息爬取
  20. Mxnet (20): 循环神经网络(RNN)下

热门文章

  1. linux服务占用的真实内存,为什么TOP看不出真实的内存占用情况?
  2. php 5.4.39 安装,Lamp 安装(CentOS6.6, php-5.4.39, httpd-2.4.12, mysql-5.6.24)
  3. java 字符字节数组_Java字符串与字符、字节数组知识点总结
  4. Unity+SenseAR教程:用手势发射爱心【源码】
  5. 故障转移集群仲裁盘_MongoDB负载均衡、故障转移及海量数据应对方案
  6. 在Reporting Services (RDL)中自动生成大量列
  7. 使用Elasticsearch和C#理解和实现CRUD APP的初学者教程——第1部分
  8. QQ for Linux 复活,微信 for Linux 还远吗?
  9. centos普通用户修改文件权限_Linux CentOS更改文件的权限与用户及用户组管理命令...
  10. python颜色填充代码_求懂WORD的大佬怎么一次性填充颜色或者使用python识别