用数组实现栈

用数组表示栈

选择用数组表示栈内容必须预先估计栈的最大容量。在Java中,数组一旦创建,其大小是无法改变的,而数组设置过大可能会浪费大量内存,设置过小又可能会溢出。

所以我们希望能够动态调整数组a[i]的大小,使得它既足以保存所有元素,又不至于浪费过多的空间。

首先,实现一个方法将栈移动到另一个大小不同的数组中。

1 private void resize(int max) {
2
3         Item[] temp = (Item[]) new Object[max];
4         for (int i = 0; i < N; i++) {
5             temp[i] = a[i];
6         }
7         a = temp;
8     }

然后在push()中检测数组是否太小。如果没有多余的空间,就将数组的长度加倍。

1  public void push(Item item) {
2
3         if (N == a.length) resize(2*a.length);
4         a[N++] = item;
5
6     }

类似的,在pop()中,先删除栈顶元素,然后如果栈大小小于数组的四分之一就将数组的长度减半(这样数组长度被减半之后约为半满,在下次需要改变数组大小之前仍然能够进行多次push()和pop()操作)。

1  public Item pop() {
2
3         Item item = a[--N];
4         a[N] = null;                              //避免对象游离(见标注)
5
6         if (N > 0 && N == a.length/4) resize(a.length/2);
7         return item;
8     }

注:在对pop()的实现中,被弹出的元素的引用仍然存在于数组中。它永远不会再被访问了,但Java的垃圾回收集器无法知道这一点,除非该引用被覆盖。这种情况(保存一个不需要的对象的引用)称为游离。

在这里,只需将被弹出的数组元素的值设置为null即可。

下面给出用数组表示栈的代码实现:

  下压(LIFO)栈(能够动态调整数组大小的实现):

 1 public class ResizingArrayStack<Item> implements Iterable<Item> {
 2     private Item[] a;
 3     private int N;
 4
 5     public ResizingArrayStack() {
 6         a = (Item[]) new Object[2];
 7         N = 0;
 8     }
 9
10
11     public boolean isEmpty() {
12         return N == 0;
13     }
14
15
16     public int size() {
17         return N;
18     }
19
20
21     private void resize(int capacity) {
22         assert capacity >= N;
23         Item[] temp = (Item[]) new Object[capacity];
24         for (int i = 0; i < N; i++) {
25             temp[i] = a[i];
26         }
27         a = temp;
28     }
29
30
31     public void push(Item item) {
32         if (N == a.length) resize(2*a.length);
33         a[N++] = item;
34     }
35
36     public Item pop() {
37         Item item = a[--N];
38         a[N] = null;
39
40         if (N > 0 && N == a.length/4) resize(a.length/2);
41         return item;
42     }
43
44
45     public Item peek() {
46         return a[--N];
47     }
48
49
50     public Iterator<Item> iterator() {
51         return new ReverseArrayIterator();
52     }
53
54     private class ReverseArrayIterator implements Iterator<Item> {
55         private int i;
56
57         public ReverseArrayIterator() {
58             i = N;
59         }
60
61         public boolean hasNext() {
62             return i >= 0;
63         }
64
65         public void remove() {
66             throw new UnsupportedOperationException();
67         }
68
69         public Item next() {
70             return a[--i];
71         }
72     }
73
74 }

用数组表示栈的优点:

每项操作的用时都与集合大小无关;

空间需求总是不超过集合大小乘以一个常数。

用数组表示栈的缺点:

某些push()和pop()操作会调整数组的大小:这项操作的耗时和栈大小成正比。

使用链表来实现栈可以解决这个问题。我们下次再说。

时间: 2024-10-31 20:39:00

用数组实现栈的相关文章

Hdu 3887树状数组+模拟栈

题目链接 Counting Offspring Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1757    Accepted Submission(s): 582 Problem Description You are given a tree, it’s root is p, and the node is numbered fr

用数组模拟栈的结构

package datastruct; import java.util.Arrays; /** * 用数组模拟栈的结构:后进先出(LIFO) 线性表结构 * @author stone * 2014-07-29 06:34:49 */ public class SimulateStack<E> { public static void main(String[] args) { SimulateStack<String> ss = new SimulateStack<Str

HUID 5558 Alice&#39;s Classified Message 后缀数组+单调栈+二分

http://acm.hdu.edu.cn/showproblem.php?pid=5558 对于每个后缀suffix(i),想要在前面i - 1个suffix中找到一个pos,使得LCP最大.这样做O(n^2) 考虑到对于每一个suffix(i),最长的LCP肯定在和他排名相近的地方取得. 按排名大小顺序枚举位置,按位置维护一个递增的单调栈,对于每一个进栈的元素,要算一算栈内元素和他的LCP最大是多少. 如果不需要输出最小的下标,最大的直接是LCP(suffix(st[top]),  suff

JavaScript高级程序设计--对象,数组(栈方法,队列方法,重排序方法,迭代方法)

1.使用对象字面量定义对象 var person={}; 使用这种方式创建对象时,实际上不会调用Object构造函数. 开发人员更喜欢对象字面量的语法. 2.有时候需要传递大量可选参数的情形时,一般来讲使用对象字面量来封装多个可选参数. 3.对象属性的点表示法与方括号表示法的区别 (1)功能上:两者没区别 (2)但是方括号的有点是可以通过变量来访问属性 例如: var person={ name:"Nic" } 点表示法:person.name 方括号表示法:var prop=“nam

java、C语言实现数组模拟栈

java: public class ArrayStack { private int[] data; private int top; private int size; public ArrayStack(int size) { this.data = new int[size]; this.size = size; this.top = -1; } public boolean isEmpty() { if (this.top == -1) { return true; } return

Javascript用数组实现栈和队列

栈是遵循后进先出(LIFO)规则的一种有序集合,比如桌上的一叠书,我们只能从上面放或取. 队列是遵循先进先出(FIFO)规则的一种有序集合,比如排队,先排到的先离开. 数组也是一种有序的集合,它与上面两种数据结构类似.由于JavaScript中的数组本身拥有许多简单的方法,如push(), 所以用数组来表示栈和队列非常简单. 首先回顾一下相关的方法: push():向数组尾部添加一个或多个项. pop():删除数组尾部的一个项. unshift():先数组头部添加一个或多个项. shift():

用数组实现栈demo

package cn.aust.zyw.demo; import java.util.Iterator; /** * Created by zyw on 2016/2/19. * 用数组实现栈 */ public class MyStack<T> implements Iterable<T>{ public static void main(String args[]){ MyStack<Integer> myStack=new MyStack<>(); f

【bzoj3238】[Ahoi2013]差异 后缀数组+单调栈

题目描述 输入 一行,一个字符串S 输出 一行,一个整数,表示所求值 样例输入 cacao 样例输出 54 题解 后缀数组+单调栈,几乎同 bzoj3879 的后半部分. 我明显是做题做反了... 这里还是说一下这道题的做法. 先用后缀数组求出height. 然后由于有LCP(a,c)=min(LCP(a,b),LCP(b,c))(rank[a]<rank[b]<rank[c]),所以我们只需要知道排名相邻的两个后缀的LCP,而这就是height数组的定义. 转化为子问题:给出n个数,求所有子

笔记六:基于数组的栈的实现

栈 定义:后进先出的数据结构 实现一:基于数组表示的线性表的派生栈的实现. 原理:把线性表的插入和删除操作限制在同一端进行,即得到栈的表现形式. 操作:把数组线性表的右端定义为栈顶. 代码: template<typename T> class stack { public: virtual ~stack() {}; virtual bool empty() const = 0; virtual int size() const = 0; virtual T& top() = 0; v