Java数据结构漫谈-Stack
Stack(栈)是一种比较典型的数据结构,其元素满足后进先出(LIFO)的特点。
Java中Stack的实现继承自Vector,所以其天然的具有了一些Vector的特点,所以栈也是线程安全的。
class Stack<E> extends Vector<E> {
事实上,除了继承自Vector的那些方法之外,Stack只提供了5个方法:
public E push(E item) {
addElement(item);
return item;
}
public synchronized E pop() {
E obj;
int len = size();
obj = peek();
removeElementAt(len - 1);
return obj;
}
public synchronized E peek() {
int len = size();
if (len == 0)
throw new EmptyStackException();
return elementAt(len - 1);
}
public boolean empty() {
return size() == 0;
}
public synchronized int search(Object o) {
int i = lastIndexOf(o);
if (i >= 0) {
return size() - i;
}
return -1;
}
push函数是用来向Stack的顶部压入一个元素,影响其性能的是 addElement的性能:
public synchronized void addElement(E obj) {
modCount++;
ensureCapacityHelper(elementCount + 1);
elementData[elementCount++] = obj;
}
可以看出,其方法是在Vector的最后加入一个元素,其时间复杂度是o(1)。
peek函数是从查看栈顶元素,但是不删除。其性能主要是由Vector的elementAt函数决定的:
public synchronized E elementAt(int index) {
if (index >= elementCount) {
throw new ArrayIndexOutOfBoundsException(index + " >= " + elementCount);
}
return elementData(index);
}
E elementData(int index) {
return (E) elementData[index];
}
由于Vector的底层是数组实现的,通过下标可以直接进行定位,所以peek的时间复杂度也是o(1)。
pop函数是移除并获取到栈顶元素,在源码中可以看到,这里调用peek获取了栈顶元素,使用removeElementAt来删除栈顶元素,这个函数也正是决定pop性能的关键:
public synchronized void removeElementAt(int index) {
modCount++;
if (index >= elementCount) {
throw new ArrayIndexOutOfBoundsException(index + " >= " +
elementCount);
}
else if (index < 0) {
throw new ArrayIndexOutOfBoundsException(index);
}
int j = elementCount - index - 1;
if (j > 0) {
System.arraycopy(elementData, index + 1, elementData, index, j);
}
elementCount--;
elementData[elementCount] = null; /* to let gc do its work */
}
咋一看来,这里删除一个元素之后,都会对数组中的元素进行复制调整,时间复杂度是o(n),但是考虑到传进来的index值的特殊性:
index = elementCount -1;
这样的话if(j>0)的条件永远都不会成立,因为j永远都是0,中间复制调整元素的操作就避免了,仅仅是在最后把Vector最后的值赋值为null,时间复杂度是o(1)。
search是查找一个元素在Stack中的index,这里起作用的是Vector的lastIndexOf函数,代码如下:
public synchronized int lastIndexOf(Object o) {
return lastIndexOf(o, elementCount-1);
}
public synchronized int lastIndexOf(Object o, int index) {
if (index >= elementCount)
throw new IndexOutOfBoundsException(index + " >= "+ elementCount);
if (o == null) {
for (int i = index; i >= 0; i--)
if (elementData[i]==null)
return i;
} else {
for (int i = index; i >= 0; i--)
if (o.equals(elementData[i]))
return i;
}
return -1;
}
可以看出,查找的过程是从后向前,挨个比较,其时间复杂度必然是o(n)。
Stack是Vector的子类,所以Vector的函数这里也适用,这里不再赘述,在Vector相关的介绍文章中会有。
Stack是线程安全的,所以其性能必然受到影响,如果需要使用一个非线程安全的Stack,可以直接使用LinkedList,LinkedList本身提供的方法就包含了Stack的操作。
Java数据结构漫谈-Stack的更多相关文章
- Java 数据结构之Stack
Stack类表示后进先出(LIFO)的对象堆栈.栈是一种非常常见的数据结构.Stack继承Vector,并对其进行了扩展. 用法: 1.只有一个构造函数: public Stack() {} 2.创建 ...
- java数据结构 栈stack
栈(Stack) 栈(Stack)实现了一个后进先出(LIFO)的数据结构. 你可以把栈理解为对象的垂直分布的栈,当你添加一个新元素时,就将新元素放在其他元素的顶部. 当你从栈中取元素的时候,就从栈顶 ...
- [Java数据结构]使用Stack检查表达式中左右括号是否匹配
Stack是一种先进后出的数据结构后,这个特点决定了它在递归向下的场景中有独到的功效. 以下程序展示了它在检查表达式中括号匹配的有效性: 程序: package com.heyang.util; im ...
- Java数据结构漫谈-LinkedList
同样是List的数据结构,LinkedList是使用了前后指针,指明节点的方式来表示链表的,这与之前介绍的ArrayList http://www.cnblogs.com/yakovchang/p/j ...
- Java数据结构漫谈-ArrayList
ArrayList是一个基于数组实现的链表(List),这一点可以从源码中看出: transient Object[] elementData; // non-private to simplify ...
- Java数据结构漫谈-Vector
List除了ArrayList和LinkedList之外,还有一个最常用的就是Vector. Vector在中文的翻译是矢量,向量,所以大家喜欢把Vector叫做矢量数组,或者向量数组. 其实就底层实 ...
- 【Java数据结构学习笔记之二】Java数据结构与算法之栈(Stack)实现
本篇是java数据结构与算法的第2篇,从本篇开始我们将来了解栈的设计与实现,以下是本篇的相关知识点: 栈的抽象数据类型 顺序栈的设计与实现 链式栈的设计与实现 栈的应用 栈的抽象数据类型 栈是 ...
- java数据结构与算法之栈(Stack)设计与实现
本篇是java数据结构与算法的第4篇,从本篇开始我们将来了解栈的设计与实现,以下是本篇的相关知识点: 栈的抽象数据类型 顺序栈的设计与实现 链式栈的设计与实现 栈的应用 栈的抽象数据类型 栈是一种用于 ...
- java数据结构——栈(Stack)
学习数据结构与算法是枯燥的,但只有坚持不懈的积累,才会有硕果累累的明天. /** * 继续学习Java数据结构 ————栈 * 栈的实现其实还是使用数组,只不过我们不能直接访问数组下标,而是通过一个指 ...
随机推荐
- do/while(0) c4127
原文链接:http://cnicholson.net/2009/03/stupid-c-tricks-dowhile0-and-c4127/ // NOISY CODE #define MULTI_L ...
- 新安装的mysql必须调整的10项配置
还在为新安装的mysql服务,不知道修改哪些默认配置而发愁吗?mysql可调整参数有100多个,到底要立即!马上!调整哪些最重要的参数? 网络神贴答复你: 这篇文章主要介绍了MySQL优化必须调整的1 ...
- 在iis中调试asp.net程序
第一步,在iis中新建一个网站,名称为Langben,“物理路径”选择你的程序的根目录,端口你可以随便设置一个数,我这里设置为8888(后面要用到哦). 第二步,应用程序池设置一下 第三步,接下来,在 ...
- js大文件分割上传
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xht ...
- dede后台反应特别慢-转
找到织梦后台管理目录下的/templets/index_body.htm文件 将第25行至第35行部分js代码注释掉. 就这么简单
- jsonp跨域请求学习笔记
前言 ajax,用苍白的话赞扬:很好. 我们可以使用ajax实现异步获取数据,减少服务器运算时间,大大地改善用户体验:我们可以使用ajax实现小系统组合大系统:我们还可以使用ajax实现前端的优化.( ...
- libevent入门(1)
libevent是什么 libevent 库实际上没有更换 select().poll() 或其他机制的基础.而是使用对于每个平台最高效的高性能解决方案在实现外加上一个包 ...
- MobileProject
iOS开源项目MobileProject功能点介绍 一:MobileProject简介 MobileProject项目是一个以MVC模式搭建的开源功能集合,基于Objective-C上面进行编写,意在 ...
- Xcode本地文件 提交svn 的明细
XXXXX.xcscmblueprint 这个文件不用提交svn
- Lintcode--009(单词切分)
http://www.lintcode.com/zh-cn/problem/word-break/ 单词切分 给出一个字符串s和一个词典,判断字符串s是否可以被空格切分成一个或多个出现在字典中的单词. ...