看动画学算法之:栈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篇,从本篇开始我们将来了解栈的设计与实现,以下是本篇的相关知识点: 栈的抽象数据类型 顺序栈的设计与实现 链式栈的设计与实现 栈的应用 栈的抽象数据类型 栈是 ...
随机推荐
- Git脑图
ps:有时我们想一台有不同的git账号对应不同的git仓库时(gitLab/gitHub)时,除了全局的用户配置定义,我们可以为不同仓库自定义不同用户名和邮件 1.查询全局的配置:git config ...
- Ant的使用(一)
<?xml version="1.0" encoding="UTF-8"?> <project name="projectName& ...
- 回忆java输入输出流,走出误区
input read 将一个XXX读入(input)---从输入流中读取数据的下一个字节(code操作的).output write 将一个类型的数据写入此流(code操作的)---然后把XXX输出( ...
- JDBC基础篇(MYSQL)——使用statement执行DML语句(insert/update/delete)
注意:其中的JdbcUtil是我自定义的连接工具类:代码例子链接: package day02_statement; import java.sql.Connection; import java.s ...
- Linux中增加组和用户
新服务器增加用户: 1.创建一个新的组, groupadd oracle 2.useradd 命令用于建立用户账号(-g 指定用户所属的群组) useradd -g oracle oracle 3.再 ...
- 磁盘“Seagate”没有被推出,因为一个或多个程序可能正在使用它。
推出移动硬盘失败,解决方案: 执行 lsof /Volumes/Seagate/ 可以看到哪些进程在占用磁盘 $ lsof /Volumes/Seagate/ COMMAND PID USER FD ...
- js判断是在移动端还是在pc端
function chatQQ3(){ if(/Android|webOS|iPhone|iPod|BlackBerry/i.test(navigator.userAgent)) { //移动端打开 ...
- 《微服务架构设计模式》读书笔记 | 第8章 外部API模式
目录 前言 1. 外部API的设计难题 1.1 FTGO应用程序的服务及客户端 1.2 FTGO移动客户端API的设计难题 1.3 其他类型客户端API的设计难题与特点 2. API Gateway模 ...
- 对象赋值在PHP中到底是不是引用?
之前的文章中,我们说过变量赋值的问题,其中有一个问题是对象在进行变量赋值的时候,直接就是引用赋值.那么到底真实情况是怎样呢? 之前变量赋值的文章 PHP的变量赋值 对象引用测试 在继续深入的学习PHP ...
- Java基础系列(36)- 数组三种初始化及内存分析
内存分析 数组三种初始化 静态初始化 int[] a = {1,2,3}; Man[] mans = {new Man(1,1),new Man(2,2)} 动态初始化 int[] a = new i ...