栈的Java实现-分别使用数组和链表
栈是非常重要的数据结构,栈具有后进先出的特点。
在JVM内部,每个线程维护一个栈,对于每个方法调用,入栈一个元素,成为栈帧,当方法执行完成后,对应的栈帧出栈。
栈帧中,也包含一个栈,称为操作数栈。
一、定义栈
public interface Stack<Item> {
// 添加一个元素
void push(Item item);
// 删除最近添加的元素
Item pop();
// 栈是否为空
boolean isEmpty();
// 栈中的元素数量
int size();
}
二、数组实现
/**
* 数组实现
* @param <Item>
*/
public class ResizingArrayStack<Item> implements Stack<Item>, Iterable<Item> {
private Item[] a;
// 表示栈实际大小
int N;
/**
* 初始的数组容量为16
*/
public ResizingArrayStack(){ this(16); }
public ResizingArrayStack(int cap){ a = (Item[]) new Object[cap]; }
@Override
public void push(Item item) {
if(N == a.length) resize(2 * N);
a[N++] = item;
}
/**
* 扩容,每次扩2倍的空间
* @param size
*/
private void resize(int size) {
if(size <= 16){
return;
}
System.out.println("触发扩容,原容量: " + a.length + ", 扩容后:" + size);
Item[] temp = (Item[]) new Object[size];
for (int i = 0; i < N; i++) {
temp[i] = a[i];
}
a = temp;
}
@Override
public Item pop() {
if(N == a.length / 4) resize(a.length / 2);
return a[--N];
}
@Override
public boolean isEmpty() { return N == 0; }
@Override
public int size() { return N; }
// *********** 以下代码与算法实现无关,仅为方便测试使用 *************
@Override
public Iterator<Item> iterator() {
return new Iterator<Item>() {
private int i = N;
@Override
public boolean hasNext() { return i>0; }
@Override
public Item next() { return a[--i]; }
@Override
public void remove() { }
};
}
public void print(){
System.out.print("当前元素(自栈顶至栈底):\t");
Iterator<Item> iterator = iterator();
while (iterator.hasNext()){
System.out.print(iterator.next() + "\t");
}
System.out.println();
}
}
三、链表实现
/**
* 链表实现
* @param <Item>
*/
public class LinkStack<Item> implements Stack<Item>, Iterable<Item> {
private Node<Item> top;
private int N;
private class Node<Item>{ Item item;Node next;}
/**
* 入栈
* @param item
*/
@Override
public void push(Item item) {
Node node = new Node();
node.item = item;
node.next = top;
top = node;
N++;
}
/**
* 出栈
* @return
*/
@Override
public Item pop() {
Item item = top.item;
top = top.next;
N--;
return item;
}
@Override
public boolean isEmpty() { return N==0; }
@Override
public int size() { return N; }
//*********** 以下代码与算法实现无关,仅为方便测试使用 *************
@Override
public Iterator<Item> iterator() {
return new Iterator<Item>() {
Node<Item> temp = top;
@Override
public boolean hasNext() {
return temp != null;
}
@Override
public Item next() {
Item item = temp.item;
temp = temp.next;
return item;
}
};
}
public void print(){
System.out.print("当前元素(自栈顶至栈底):\t");
Iterator<Item> iterator = iterator();
while (iterator.hasNext()){
System.out.print(iterator.next() + "\t");
}
System.out.println();
}
}
四、测试结果
public class StackTest {
@Test
public void arrayStackTest(){
// ResizingArrayStack<String> stack = new ResizingArrayStack<>();
LinkStack<String> stack = new LinkStack<>();
System.out.print("初始化后, ");
stack.print();
String pop;
//压入元素to
System.out.print("入栈:to,");
stack.push("to");
stack.print();
//压入元素be
System.out.print("入栈:be,");
stack.push("be");
stack.print();
//压入元素or
System.out.print("入栈:or,");
stack.push("or");
stack.print();
//压入元素not
System.out.print("入栈:not,");
stack.push("not");
stack.print();
//压入元素to
System.out.print("入栈:to,");
stack.push("to");
stack.print();
//弹出元素
pop = stack.pop();
System.out.print("出栈:" + pop + ",");
stack.print();
//压入元素be
System.out.print("入栈:be,");
stack.push("be");
stack.print();
//弹出元素
pop = stack.pop();
System.out.print("出栈:" + pop + ",");
stack.print();
//弹出元素
pop = stack.pop();
System.out.print("出栈:" + pop + ",");
stack.print();
//压入元素that
System.out.print("入栈:that,");
stack.push("that");
stack.print();
//弹出元素
pop = stack.pop();
System.out.print("出栈:" + pop + ",");
stack.print();
//弹出元素
pop = stack.pop();
System.out.print("出栈:" + pop + ",");
stack.print();
//弹出元素
pop = stack.pop();
System.out.print("出栈:" + pop + ",");
stack.print();
//压入元素is
System.out.print("入栈:is,");
stack.push("is");
stack.print();
}
@Test
public void test2(){
ResizingArrayStack<Integer> stack = new ResizingArrayStack<>();
for (int i = 0; i < 100; i++) {
stack.push(i);
}
}
}
测试结果如下:
test1
test2
五、多说一点
在网上搜索数组和链表的区别时,最常见的说法是:数组访问较快,插入操作较慢;链表访问操作慢,修改便捷。
在实现栈时,由于栈仅涉及在最后插入一个值、在最后删除一个值,所以在这里比较2种实现方式优劣时,不能按照上述方式描述。
个人认为,数组实现,劣势在于需要扩容操作;链表实现,需要额外维护一个指向next的链接,占用更多空间;总体来说,2种实现方式优劣不明显,均比较合适。
栈的Java实现-分别使用数组和链表的更多相关文章
- “全栈2019”Java第三十一章:二维数组和多维数组详解
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
- “全栈2019”Java第三十章:数组详解(下篇)
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
- “全栈2019”Java第二十九章:数组详解(中篇)
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
- “全栈2019”Java第二十八章:数组详解(上篇)
难度 初级 学习时间 10分钟 适合人群 零基础 开发语言 Java 开发环境 JDK v11 IntelliJ IDEA v2018.3 文章原文链接 "全栈2019"Java第 ...
- 栈的数组和链表实现(Java实现)
我以前用JavaScript写过栈和队列,这里初学Java,于是想来实现栈,基于数组和链表. 下面上代码: import java.io.*; //用接口来存放需要的所有操作 interface st ...
- Java之--Java语言基础组成—数组
Java语言基础组成-数组 Java语言由8个模块构成,分别为:关键字.标识符(包名.类名.接口名.常量名.变量名等).注释.常量和变量.运算符.语句.函数.数组. 本片主要介绍Java中的数组,数组 ...
- 【老鸟学算法】包含 min函数的栈设计——java实现
要求: 1. 定义栈的数据结构,要求添加一个 min函数,能够得到栈的最小元素. 2. 要求函数 min.push 以及 pop 的时间复杂度都是 O(1). 这是考验“栈”数据结构设计.众所周知,栈 ...
- 剑指Offer——栈的java实现和栈的应用举例
剑指Offer--栈的java实现和栈的应用举例 栈是一种先进后出的数据结构, 栈的实现如下: 首先定义了栈需要实现的接口: public interface MyStack<T> { / ...
- Java基础--二维数组
1.二维数组的定义 二维数组表示行列二维结构,在栈空间中的二维数组的地址指向堆空间中的一维数组,堆空间中的一维数组的地址又指向一维数组所在的内存空间. 2.二维数组的声明 二维数组声明有3种方式,推荐 ...
随机推荐
- 实现图像的二值化(java+opencv)
书里的解释: 其他的没找到什么资料,直接参考百度百科 https://baike.baidu.com/item/%E5%9B%BE%E5%83%8F%E4%BA%8C%E5%80%BC%E5%8C%9 ...
- JavaSwing关于GridBagLayout(网格袋布局)的使用
下面的链接有初步的介绍: https://blog.csdn.net/xietansheng/article/details/72814552 关于GridBagConstraints: GridBa ...
- Python的序列数据和变量
本篇内容涉及字符串.列表.元组.Python中的报错,以及变量本质,包括引用计数技术 该篇只为抛砖引玉,其内容来自Python学习中总结,另外感谢李老师的教导和Python班同学们的帮助 附上李老师和 ...
- 第1章 Hive入门
第1章 Hive入门 1.1 什么是Hive Hive:由Facebook开源用于解决海量结构化日志的数据统计. Hive是基于Hadoop的一个数据仓库工具,可以将结构化的数据文件映射为一张表,并提 ...
- jmeter将上一个接口的返回值作为下一个接口的请求参数
接口响应结果,通常为HTML.Json格式的数据,对于HTML的响应结果的提取,可以通过正则表达式,XPath提取. 对于Json格式响应结果,可以通过正则表达式.JSON Extractor插件.B ...
- react+antd的todolist开发
使用localStorage缓存在cookie里刷新不会充重置 参考链接 create-react-app入门教程https://www.jianshu.com/p/77bf3944b0f4 http ...
- JAVA指令集——GETSTATIC
(indexbyte1<<8)|indexbyte2——得到index 1,从runtimeconstantpool中取得index处的FieldRef,FieldRef已经解析完成 Fi ...
- session 机制和 httpsession 详解 (转载)
https://www.cnblogs.com/bjanzhuo/archive/2013/02/27/3575884.html 一.术语session 在我的经验里,session这个词被滥用的程度 ...
- 每天定时下载gfs资料shell脚本
在数值天气预报应用中,经常需要下载一些输入资料,美国ncep的gfs资料是常用的一种分析场资料.业务运行,需要每天定时从ncep网站上下载,所以写了一个Shell脚本实现这一功能.脚本内容如下: #! ...
- java基础知识点整理
1.&和&&的区别? &:逻辑与(and),运算符两边的表达式均为true时,整个结果才为true. &&:短路与,如果第一个表达式为false时,第二 ...