用数组实现栈

用数组表示栈

选择用数组表示栈内容必须预先估计栈的最大容量。在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()操作会调整数组的大小:这项操作的耗时和栈大小成正比。

 

posted @ 2016-06-11 22:42  谈笑风生~  阅读(5793)  评论(0编辑  收藏  举报