我理解的数据结构(二)—— 栈(Stack)
我理解的数据结构(二)—— 栈(Stack)
一、栈基础
- 栈是一种线性结构
- 相比较数组,栈对应的操作是数组的子集
- 只能从一端添加元素,也只能从同一端取出元素,这一端称为栈顶
- 栈是一种后进先出的数据结构,LIFO(Last In First Out)
二、栈的应用
- Undo操作(撤销)
- 程序调用所使用的系统栈

三、栈的实现
其实,实现一个栈结构非常简单,我们只需要复用上一节我们自己封装的数组就可以快速的实现一个栈的创建。
以数组的最后一个元素当成栈顶元素。
1. 首先,我们先创建一个栈的借口,里面声明我们需要实现的方法:
```
public interface Stack<E> {
boolean isEmpty();
int getSize();
// 移除栈顶元素
E pop();
// 查看栈顶元素
E peek();
// 压入栈
void push(E ele);
}
```
注:这里我们有一个peek方法,就是查看栈顶元素,所以我们需要给我们自己封装的数组类添加一个查看最后一个元素的方法:
```
// 获取最后一个元素
public E getLast() {
return get(size - 1);
}
```
2. 封装我们自己的栈
```
public class ArrayStack<E> implements Stack<E> {
private ArrayNew<E> array;
public ArrayStack(int capacity) {
array = new ArrayNew<>(capacity);
}
public ArrayStack() {
array = new ArrayNew<>();
}
public int getCapacity() {
return array.getCapacity();
}
@Override
public int getSize() {
return array.getSize();
}
@Override
public boolean isEmpty() {
return array.isEmpty();
}
@Override
public void push(E ele) {
array.addLast(ele);
}
@Override
public E pop() {
return array.removeLast();
}
@Override
public E peek() {
return array.getLast();
}
@Override
public String toString() {
StringBuilder res = new StringBuilder();
res.append("Stack: [");
for (int i = 0; i < getSize(); i++) {
res.append(array.get(i));
if (getSize() - 1 != i) {
res.append(", ");
}
}
res.append("] top");
return res.toString();
}
}
<p><strong>注:</strong>其中的<code>ArrayNew</code>即是我们在上一节自己封装的数组类,不知道的同学可以去查看:<br><a href="https://segmentfault.com/a/1190000016064569">我理解的数据结构(一)—— 不要小看了数组</a></p>
<blockquote>因为我在<code>ArrayNew</code>中已经实现了动态数组,所以不用考虑栈长度的问题,这样我们就自己封装了一个栈(注释在<code>Stack</code>接口中和<code>ArrayNew</code>类中足够详细)。</blockquote>
<h3>四、用栈去解决《有效的括号》</h3>
<blockquote>这是一道<code>leetcode</code>上,编号为20的题目,具体题目描述如下:</blockquote>
给定一个只包括 '(',')','{','}','[',']' 的字符串,判断字符串是否有效。
有效字符串需满足:
1.左括号必须用相同类型的右括号闭合。
2.左括号必须以正确的顺序闭合。
注意空字符串可被认为是有效字符串。
<p><strong>解题思路</strong></p>
<ol>
<li>首先,我们可以把左括号直接压入栈,不论是小括号、中括号还是大括号。</li>
<li>
<p>如果拿到的是右括号,则需要做匹配判断。</p>
<ul>
<li>拿出栈顶元素,如果与之右括号匹配,则<code>pop</code>出栈顶元素。</li>
<li>拿出栈顶元素,如果与之右括号不匹配,则返回<code>false</code>。</li>
</ul>
</li>
<li>
<p>如果字符串比较完成,没有返回<code>false</code>,则判断栈是否为空。</p>
<ul>
<li>为空,返回<code>true</code>,括号匹配成功</li>
<li>不为空,返回<code>false</code>
</li>
</ul>
</li>
</ol>
<h4>解题代码如下:</h4>
public boolean isValid(String s) {
ArrayStack<Character> stack = new ArrayStack<>();
for (int i = 0; i < s.length(); i++) {
char c = s.charAt(i);
// 左括号直接压入栈
if (c == '(' || c == '[' || c == '{') {
stack.push(c);
} else {
if (stack.isEmpty()) {
return false;
}
char topChar = stack.pop();
if (c == ')' && topChar != '(') {
return false;
}
if (c == ']' && topChar != '[') {
return false;
}
if (c == '}' && topChar != '{') {
return false;
}
}
}
return stack.isEmpty();
}
<h3>五、栈的复杂度分析</h3>
<table>
<thead><tr>
<th align="center">方法</th>
<th align="center">复杂度</th>
</tr></thead>
<tbody>
<tr>
<td align="center">push</td>
<td align="center">O(1) 均摊</td>
</tr>
<tr>
<td align="center">pop</td>
<td align="center">O(1) 均摊</td>
</tr>
<tr>
<td align="center">peek</td>
<td align="center">O(1)</td>
</tr>
<tr>
<td align="center">getSize</td>
<td align="center">O(1)</td>
</tr>
<tr>
<td align="center">isEmpty</td>
<td align="center">O(1)</td>
</tr>
</tbody>
</table>
<blockquote>因为栈的时间复杂度都是<code>O(1)</code>,所以栈的性能是很高的。</blockquote>
原文地址:https://segmentfault.com/a/1190000016067831
我理解的数据结构(二)—— 栈(Stack)的更多相关文章
- 数据结构之栈(Stack)
什么是栈(Stack) 栈是一种遵循特定操作顺序的线性数据结构,遵循的顺序是先进后出(FILO:First In Last Out)或者后进先出(LIFO:Last In First Out). 比如 ...
- Python与数据结构[1] -> 栈/Stack[0] -> 链表栈与数组栈的 Python 实现
栈 / Stack 目录 链表栈 数组栈 栈是一种基本的线性数据结构(先入后出FILO),在 C 语言中有链表和数组两种实现方式,下面用 Python 对这两种栈进行实现. 1 链表栈 链表栈是以单链 ...
- [ACM训练] 算法初级 之 数据结构 之 栈stack+队列queue (基础+进阶+POJ 1338+2442+1442)
再次面对像栈和队列这样的相当基础的数据结构的学习,应该从多个方面,多维度去学习. 首先,这两个数据结构都是比较常用的,在标准库中都有对应的结构能够直接使用,所以第一个阶段应该是先学习直接来使用,下一个 ...
- 算法与数据结构(二) 栈与队列的线性和链式表示(Swift版)
数据结构中的栈与队列还是经常使用的,栈与队列其实就是线性表的一种应用.因为线性队列分为顺序存储和链式存储,所以栈可以分为链栈和顺序栈,队列也可分为顺序队列和链队列.本篇博客其实就是<数据结构之线 ...
- 数据结构11: 栈(Stack)的概念和应用及C语言实现
栈,线性表的一种特殊的存储结构.与学习过的线性表的不同之处在于栈只能从表的固定一端对数据进行插入和删除操作,另一端是封死的. 图1 栈结构示意图 由于栈只有一边开口存取数据,称开口的那一端为“栈顶”, ...
- Python与数据结构[1] -> 栈/Stack[1] -> 中缀表达式与后缀表达式的转换和计算
中缀表达式与后缀表达式的转换和计算 目录 中缀表达式转换为后缀表达式 后缀表达式的计算 1 中缀表达式转换为后缀表达式 中缀表达式转换为后缀表达式的实现方式为: 依次获取中缀表达式的元素, 若元素为操 ...
- 线性数据结构之栈——Stack
Linear data structures linear structures can be thought of as having two ends, whose items are order ...
- 【Java数据结构学习笔记之二】Java数据结构与算法之栈(Stack)实现
本篇是java数据结构与算法的第2篇,从本篇开始我们将来了解栈的设计与实现,以下是本篇的相关知识点: 栈的抽象数据类型 顺序栈的设计与实现 链式栈的设计与实现 栈的应用 栈的抽象数据类型 栈是 ...
- Java 集合深入理解(13):Stack 栈
点击查看 Java 集合框架深入理解 系列, - ( ゜- ゜)つロ 乾杯~ 今天心情不错,再来一篇 Stack ! 数据结构中的 栈 数据结构中,栈是一种线性数据结构,遵从 LIFO(后进先出)的操 ...
随机推荐
- Linux Framebuffer驱动剖析之中的一个—软件需求
嵌入式企鹅圈将以本文作为2015年的终结篇,以回应第一篇<Linux字符设备驱动剖析>.嵌入式企鹅圈一直专注于嵌入式Linux和物联网IOT双方面的原创技术分享,稍后会公布嵌入式企鹅圈的2 ...
- opencv中RGB转HSV
cvCvtColor(src,dst,CV_BGR2HSV); 当中,src为三通道的,dst也为三通道的. OPENCV 中 H.S.V.顺序分别为3*x+0 3*x+1 3*x+2 open ...
- Spring -> Spring Boot > Spring Cloud
这几天刚刚上班,公司用的是Spring Cloud,接触不多.我得赶快学起来. 想学习就必须得知道什么是微服务,什么是Spring Boot,什么是Spring Cloud,以及两者之间有什么关系? ...
- 如何在vue项目中引入阿里巴巴的iconfont图库
1. 打开 http://www.iconfont.cn/ 2. 选择我们喜欢的图标,点击上面的小车,加入图标库,即右侧的购物车 3.点击购物车,点击下载代码 4.解压下载的文件夹,将文件夹复制到 a ...
- C#窗体间传值的简便方法/工具
一.问题:窗体间传值必须需要窗体之间有联系,具体有如下方式 窗体间传值涉及到窗体A必须拥有窗体B,这样才可以实现A-B之间传值 窗体A与窗体B在窗体/实例C中,A-B可互相通讯 其他方式,不细讨论,复 ...
- 客户端JavaScript基础 网页上的输入输出
创建: 2017/10/06 完成: 2017/10/07 更新: 2017/10/15 增加了通过事件监听器登陆事件的方法的链接 # TODO: 补充 基于Canvas的图象 客户端Java ...
- form表单点击后验证
function check(){ var customertype = document.getElementById("customertype"); //alert(cust ...
- 洛谷P1341 无序字母对(欧拉回路)
P1341 无序字母对 题目描述 给定n个各不相同的无序字母对(区分大小写,无序即字母对中的两个字母可以位置颠倒).请构造一个有n+1个字母的字符串使得每个字母对都在这个字符串中出现. 输入输出格式 ...
- 12 C#中的方法
还记得我们的第一个程序吗?忘记了?那你要努力了.我们的第一个程序是就是往dos窗口输出一些字符串.在哪个程序中只有一个方法,Main方法.Main方法是一个特殊的方法,但是它也是一个方法.为什么说Ma ...
- Hibernate中使用子查询
子查询: 子查询是SQL语句中非常重要的功能特性,它可以在SQL语句中利用另外一条SQL语句的查询结果,在Hibernate中HQL查询同样对子查询功能提供了支持. 如下面代码所示: List ...