重学数据结构(二、栈)
1、栈的定义和特点
栈(Stack)又称堆栈, 是限制在表的一端进行插入和删除运算的线性表。
如果要拿一个东西对比,羽毛球筒比较合适。
栈遵循后进先出( Last-in-first-out,LIFO)的原则。
比如上面的羽毛球筒,只能将最顶端的羽毛球移出,也只能将新的羽毛球放到最顶端——这两种操作分别称作入栈( Push)和出栈( Pop)。入栈和出栈的示意图如下:
最顶端的羽毛球叫栈顶栈顶 (top),最底端的羽毛球称为栈底 (bottom)。
2、栈的基本操作
栈的基本操作除了入栈和出栈外, 还有栈的初始化、 栈空的判定, 以及取栈顶元素等。
根据这些操作,我们定义一个接口:
/**
* @Author 三分恶
* @Date 2020/8/26
* @Description 栈接口
*/
public interface Stack {
public int getSize(); //返回栈中元素数目
public boolean isEmpty(); //判空
public Object top(); //取栈顶元素但不删除
public void push(Object element); //入栈
public Object pop(); //出栈
}
线性表有顺序和链式两种实现,栈同样有两种实现。
3、顺序栈
这里我们通过一个可扩容的数组来实现。
/**
* @Author 三分恶
* @Date 2020/8/26
* @Description 顺序栈--数组实现
*/
public class ArrayStack implements Stack{
private static int defaultSize=15; //默认容量
private int size; //实际容量:实际存储元素个数
private Object[] data; //存放元素的数组
/**
* 无参构造方法:按默认容量构造元素数组
*/
public ArrayStack() {
data=new Object[defaultSize];
size=0;
}
/**
* 有参构造方法:指定元素数组容量
* @param size
*/
public ArrayStack(int size){
data=new Object[size];
}
public int getSize() {
return size;
}
public boolean isEmpty() {
return size==0;
}
/**
* 取栈顶元素:不删除栈顶元素
* @return
*/
public Object top() {
if (isEmpty())
throw new RuntimeException("栈空");
size--;
return data[size-1];
}
/**
* 入栈
* @param element
*/
public void push(Object element) {
//数组已满,扩容
if (size==data.length){
//扩容两倍的新数组
Object [] newData=new Object[size<<1];
//拷贝数组
System.arraycopy(data,0,newData,0,size);
data=newData;
}
//栈顶上插入新元素
data[size]=element;
size++;
}
/**
* 出栈
* @return
*/
public Object pop() {
if (isEmpty())
throw new RuntimeException("栈空");
Object top=data[size-1];
data[size-1]=null;
size--;
return top;
}
}
时间复杂度分析:
- getSize():O(1)
- isEmpty():O(1)
- top():O(1)
- push():平均O(1),最坏(扩容)O(n)
- pop(): O(1)
3、链栈
链栈指的是链式存储结构实现的栈。在前面的学习中,我们已经完成了单向链表的实现,代码如下,具体说明可查看上一篇内容:
现在我们通过单向链表来实现链栈:
/**
* @Author 三分恶
* @Date 2020/8/26
* @Description
*/
public class ListStack implements Stack{
//单向链表
private SinglyLinkedList list;
/**
* 构造函数:初始化单向链表
*/
public ListStack(){
list=new SinglyLinkedList();
}
/**
* 获取栈的容量
* @return
*/
public int getSize() {
return list.getSize();
}
public boolean isEmpty() {
return list.getSize()==0;
}
/**
* 取栈顶元素
* @return
*/
public Object top() {
//取列表的尾节点
return list.get(list.getSize()-1);
}
/**
* 入栈
* @param element
*/
public void push(Object element) {
//队列尾插入
list.addTail(element);
}
/**
* 出栈
* @return
*/
public Object pop() {
int topIndex=list.getSize()-1;
//列表为节点
Object top=list.get(topIndex);
//删除尾结点
list.remove(topIndex);
return top;
}
}
时间复杂度分析:
- getSize():O(1)
- isEmpty():O(1)
- top():O(1)
- push():O(1)
- pop(): O(1)
4、java中的栈
在Java中有一个java.util.Stack类,它实现了栈的结构。
它是Vector的子类,也自定义了一些作为栈的方法。
java.util.Stack类是Vector的子类,实际上并不建议使用它。
在Java中还有另外一个集合,可以作为栈使用,它就是LinkedList。LinkedList中实现了push、pop方法。具体可以查看LinkedList源码阅读笔记。
源码地址:https://gitee.com/LaughterYoung/data-structure-learn.git
上一篇:重学数据结构(一、线性表)
本文为学习笔记类博客,主要资料来源如下!
参考:
【1】:邓俊辉 编著. 《数据结构与算法》 【2】:王世民 等编著 . 《数据结构与算法分析》 【3】: Michael T. Goodrich 等编著.《Data-Structures-and-Algorithms-in-Java-6th-Edition》 【4】:严蔚敏、吴伟民 编著 . 《数据结构》 【5】:程杰 编著 . 《大话数据结构》 【6】:Java Stack 类
- 让BASH,VIM美美的Powerline
- 极品三数666.cn易主,价格让人大惊!
- ui-router中使用ocLazyLoad和resolve
- rpc框架之 avro 学习 2 - 高效的序列化
- rpc框架之HA/负载均衡构架设计
- 使用Docker-Docker for Web Developers(2)
- 打造高效前端工作环境-tmuxinator
- 在Linux Mint上安装node.js和npm
- JS魔法堂:再识Number type
- (cljs/run-at (JSVM. :browser) "搭建刚好可用的开发环境!")
- (cljs/run-at (->JSVM :browser) "语言基础")
- 微博爬虫
- 电话域名受欢迎,微语言融资3000万
- 前端魔法堂——异常不仅仅是try/catch
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 直播带货APP开发,圆形旋转动画
- 显存优化:纹理压缩功能介绍与使用说明
- Android编程简易实现XML解析的方法详解
- Android中SeekBar拖动条控件使用方法详解
- Android编程简单解析JSON格式数据的方法示例
- Android控件BottomSheet实现底边弹出选择列表
- Android中CheckBox复选框控件使用方法详解
- Android Recyclerview实现水平分页GridView效果示例
- Android编程之ListView和EditText发布帖子隐藏软键盘功能详解
- 建造者模式_动力节点Java学院整理
- Android ScrollView嵌套横向滑动控件时冲突问题
- Android用户输入自动提示控件AutoCompleteTextView使用方法
- Android自定义View实现水波纹效果
- Android如何获取系统通知的开启状态详解
- Handler实现线程之间的通信下载文件动态更新进度条