看动画学算法之:栈stack
简介
栈应该是一种非常简单并且非常有用的数据结构了。栈的特点就是先进后出FILO或者后进先出LIFO。
实际上很多虚拟机的结构都是栈。因为栈在实现函数调用中非常的有效。
今天我们一起来看学习一下栈的结构和用法。
栈的构成
栈一种有序的线性表,只能在一端进行插入或者删除操作。这一端就叫做top端。
定义一个栈,我们需要实现两种功能,一种是push也就是入栈,一种是pop也就是出栈。
当然我们也可以定义一些其他的辅助功能,比如top:获取栈上最顶层的节点。isEmpty:判断栈是否为空。isFull:判断栈是否满了之类。
先看下入栈的动画:

再看下出栈的动画:

栈的实现
具有这样功能的栈是怎么实现呢?
一般来说栈可以用数组实现,也可以用链表来实现。
使用数组来实现栈
如果使用数组来实现栈的话,我们可以使用数组的最后一个节点作为栈的head。这样在push和pop栈的操作的时候,只需要修改数组中的最后一个节点即可。
我们还需要一个topIndex来保存最后一个节点的位置。
实现代码如下:
public class ArrayStack {
//实际存储数据的数组
private int[] array;
//stack的容量
private int capacity;
//stack头部指针的位置
private int topIndex;
public ArrayStack(int capacity){
this.capacity= capacity;
array = new int[capacity];
//默认情况下topIndex是-1,表示stack是空
topIndex=-1;
}
/**
* stack 是否为空
* @return
*/
public boolean isEmpty(){
return topIndex == -1;
}
/**
* stack 是否满了
* @return
*/
public boolean isFull(){
return topIndex == array.length -1 ;
}
public void push(int data){
if(isFull()){
System.out.println("Stack已经满了,禁止插入");
}else{
array[++topIndex]=data;
}
}
public int pop(){
if(isEmpty()){
System.out.println("Stack是空的");
return -1;
}else{
return array[topIndex--];
}
}
}
使用动态数组来实现栈
上面的例子中,我们的数组大小是固定的。也就是说stack是有容量限制的。
如果我们想构建一个无限容量的栈应该怎么做呢?
很简单,在push的时候,如果栈满了,我们将底层的数组进行扩容就可以了。
实现代码如下:
public void push(int data){
if(isFull()){
System.out.println("Stack已经满了,stack扩容");
expandStack();
}
array[++topIndex]=data;
}
//扩容stack,这里我们简单的使用倍增方式
private void expandStack(){
int[] expandedArray = new int[capacity* 2];
System.arraycopy(array,0, expandedArray,0, capacity);
capacity= capacity*2;
array= expandedArray;
}
当然,扩容数组有很多种方式,这里我们选择的是倍增方式。
使用链表来实现
除了使用数组,我们还可以使用链表来创建栈。
使用链表的时候,我们只需要对链表的head节点进行操作即可。插入和删除都是处理的head节点。
public class LinkedListStack {
private Node headNode;
class Node {
int data;
Node next;
//Node的构造函数
Node(int d) {
data = d;
}
}
public void push(int data){
if(headNode == null){
headNode= new Node(data);
}else{
Node newNode= new Node(data);
newNode.next= headNode;
headNode= newNode;
}
}
public int top(){
if(headNode ==null){
return -1;
}else{
return headNode.data;
}
}
public int pop(){
if(headNode ==null){
System.out.println("Stack是空的");
return -1;
}else{
int data= headNode.data;
headNode= headNode.next;
return data;
}
}
public boolean isEmpty(){
return headNode==null;
}
}
本文的代码地址:
本文已收录于 http://www.flydean.com/10-algorithm-stack/
最通俗的解读,最深刻的干货,最简洁的教程,众多你不知道的小技巧等你来发现!
欢迎关注我的公众号:「程序那些事」,懂技术,更懂你!
看动画学算法之:栈stack的更多相关文章
- 看动画学算法之:排序-count排序
目录 简介 count排序的例子 count排序的java实现 count排序的第二种方法 count排序的时间复杂度 简介 今天我们介绍一种不需要作比较就能排序的算法:count排序. count排 ...
- 看动画学算法之:队列queue
目录 简介 队列的实现 队列的数组实现 队列的动态数组实现 队列的链表实现 队列的时间复杂度 简介 队列Queue是一个非常常见的数据结构,所谓队列就是先进先出的序列结构. 想象一下我们日常的排队买票 ...
- 看动画学算法之:linkedList
目录 简介 linkedList的构建 linkedList的操作 头部插入 尾部插入 中间插入 删除节点 简介 linkedList应该是一种非常非常简单的数据结构了.节点一个一个的连接起来,就成了 ...
- 看动画学算法之:平衡二叉搜索树AVL Tree
目录 简介 AVL的特性 AVL的构建 AVL的搜索 AVL的插入 AVL的删除 简介 平衡二叉搜索树是一种特殊的二叉搜索树.为什么会有平衡二叉搜索树呢? 考虑一下二叉搜索树的特殊情况,如果一个二叉搜 ...
- 看动画学算法之:hashtable
目录 简介 散列表的关键概念 数组和散列表 数组的问题 hash的问题 线性探测 二次探测 双倍散列 分离链接 rehash 简介 java中和hash相关并且常用的有两个类hashTable和has ...
- 看动画学算法之:二叉搜索树BST
目录 简介 BST的基本性质 BST的构建 BST的搜索 BST的插入 BST的删除 简介 树是类似于链表的数据结构,和链表的线性结构不同的是,树是具有层次结构的非线性的数据结构. 树是由很多个节点组 ...
- 看动画学算法之:doublyLinkedList
目录 简介 doublyLinkedList的构建 doublyLinkedList的操作 头部插入 尾部插入 插入给定的位置 删除指定位置的节点 简介 今天我们来学习一下复杂一点的LinkedLis ...
- 看动画学算法之:双向队列dequeue
目录 简介 双向队列的实现 双向队列的数组实现 双向队列的动态数组实现 双向队列的链表实现 双向链表的时间复杂度 简介 dequeue指的是双向队列,可以分别从队列的头部插入和获取数据,也可以从队列的 ...
- 【Java数据结构学习笔记之二】Java数据结构与算法之栈(Stack)实现
本篇是java数据结构与算法的第2篇,从本篇开始我们将来了解栈的设计与实现,以下是本篇的相关知识点: 栈的抽象数据类型 顺序栈的设计与实现 链式栈的设计与实现 栈的应用 栈的抽象数据类型 栈是 ...
随机推荐
- java 常用Bean 转换工具类
package com.hnf.framework.utils; import com.alibaba.fastjson.JSON; import com.fasterxml.jackson.data ...
- windows 10 + tensorflow-gpu 环境搭建
安装过程可基本按照ubuntu装法,参考https://www.cnblogs.com/xbit/p/9768238.html 其中: conda配置文件:C:\Users\Administrator ...
- 状态码1xx-6xx的含义
1xx (临时响应)表示临时响应并需要请求者继续执行操作的状态代码. 100 (继续) 请求者应当继续提出请求. 服务器返回此代码表示已收到请求的第一部分,正在等待其余部分. 101 (切换协议) 请 ...
- AbpVnext使用分布式IDistributedCache Redis缓存(自定义扩展方法)
AbpVnext使用分布式IDistributedCache缓存from Redis(带自定义扩展方法) 我的依赖包的主要版本以及Redis依赖如下 1:添加依赖 <PackageReferen ...
- 菜鸟入门Linux之路(方法论浅谈)
Linux是为人熟知的OS之王,已"统治"世界.要想学好绝非易事. 作为菜鸟,可以与Linux亲密接触的方法很多,如视频.书籍.各种企培资料等等,如今的在线教育也如火如荼. 总结说 ...
- Hibernate持久层ORM框架
一.概念 hibernate交互数据库时,对象的属性转成sql,mybatis直接写sql,性能更高: 二.
- 海量列式非关系数据库HBase 架构,shell与API
HBase的特点: 海量存储: 底层基于HDFS存储海量数据 列式存储:HBase表的数据是基于列族进行存储的,一个列族包含若干列 极易扩展:底层依赖HDFS,当磁盘空间不足的时候,只需要动态增加Da ...
- JAVA安全基础之反射
JAVA安全基础之反射 在JAVA安全中,反射是一个经常使用的技术,所以熟悉使用反射是非常必要的.下面就简单的讲下JAVA的反射的用法 什么是反射 每个类都有对应的Class类对象,该Class类对象 ...
- 多选Combobox的实现(适合MVVM模式)
MVVM没有.cs后台逻辑,一般依靠command驱动逻辑及通过binding(vm层的属性)来显示前端 我的数据类Student有三个属性int StuId ,string StuName ,boo ...
- WPF 通过进程实现异常隔离的客户端
当 WPF 客户端需要实现插件系统的时候,一般可以基于容器或者进程来实现.如果需要对外部插件实现异常隔离,那么只能使用子进程来加载插件,这样插件如果抛出异常,也不会影响到主进程.WPF 元素无法跨进程 ...