在一个数组里面实现三个栈

* 使用一个数组来实现三个栈:
* 这个问题是数组实现一个栈的升级版本,
* 一个数组实现两个栈比较的简单,可以从数组的两端到中间,也可以从中间到两端,以至于实现三个四个五个栈都行,关键是要记住栈的开始处,当栈的容量不够时做好调整
* 就单单对这个问题而言,一个数组实现三个栈又有一下两种处理方式:
* 1、把数组均分成三部分 [0, n/3) [n/3, 2n/3) [2n/3, n-1)
* 这种做法有个弊端,就是三个栈的大小都是固定的,有时某个栈实际使用的空间可能很小,而有的栈的空间却又不够用,于是造成了很大的浪费,有一种可以考虑的做法就是事先预估
* 这三个栈各自可能的大小,按需分配空间大小。实践中更有意义的做法是使用下面弹性大小的方法
* 2、所谓弹性大小的方法,就是记录各个栈的初试位置,然后就可以快乐的使用栈了,当某个栈的空间不够时就移动栈。
* 这种想法来实现三个栈时,恰恰又有一个小诀窍之处:数组的两端作为两个栈的base,第三个栈同时标记栈顶和栈顶,数组头和数组尾栈均向数组中间长,中间的数组向数组
* 低地址长,任何一个数组push操作空间不够时 就需要 shift中间的栈
* 还有就是注意,中间的栈左右移动的距离每次是1,本来想设计的 是可以自己随意修改这个移动的步长,但是发现这样没有实际意义,还是不如每次移动一个步长

  1 ublic class Arr3Stack {
  2     public static void main(String[] args) {
  3         ThreeStackUsingOneArray<Integer> arr = new ThreeStackUsingOneArray<Integer>();
  4         
  5         System.out.println("array is full : "+arr.isFull());
  6         
  7         arr.push(0,1);
  8         arr.push(1, 3);
  9         arr.push(1, 2);
 10         arr.push(2, 5);
 11         arr.push(2, 4);
 12         
 13         System.out.println("array is full : "+arr.isFull());
 14         
 15         arr.print();
 16     }
 17 }
 18 
 19 class ThreeStackUsingOneArray <AnyType>{
 20     private AnyType[] array = null;
 21     private int arrayLength = 5;    //定义数组的初试长度
 22     
 23     // 以为 stack2 stack3的栈底是 数组的首和尾所以 定义这两个站的 栈顶
 24     int stackOneTop;    // stack 1的栈顶
 25     int stackTwoTop;    // stack 2 的栈顶
 26     int stackTwoBase;    //stack 2的
 27     int stackThreeTop;    //stack 3的栈顶
 28     /*
 29      * 中间栈需要移动的方向
 30      * 0 不用搬动,Array is full
 31      * 1 向后移动
 32      * -1 向前移动
 33      */
 34     int flag = -2;
 35     
 36     public ThreeStackUsingOneArray()
 37     {
 38         init();
 39     }
 40     public ThreeStackUsingOneArray(int len)
 41     {
 42         arrayLength = len;
 43         init();
 44     }
 45     
 46     public void init()
 47     {
 48         array = (AnyType[]) new Object[arrayLength];    //应对创建 泛型数组的问题
 49         
 50         stackOneTop = 0;
 51         stackThreeTop = arrayLength - 1;
 52         stackTwoBase = (arrayLength-1) * 2 / 3;
 53         stackTwoTop = stackTwoBase;
 54         
 55     }
 56     
 57     //print the array
 58     public void print()
 59     {
 60         for (int i = 0; i < array.length; i ++)
 61         {
 62             System.out.println(array[i]);
 63         }
 64     }
 65 
 66     // 判断当前数组是不是full
 67     public boolean isFull()
 68     {
 69         if(stackOneTop > stackTwoTop && stackTwoBase >= stackThreeTop)
 70             return true;
 71         return false;
 72     }
 73     
 74     /**
 75      * 后面的栈的操作 一律都带有一个栈的标号 stackNum = 0 , 1, 2, 表示堆第stacjNum进行操作
 76      */
 77     public void push(int stackNum, AnyType x)
 78     {
 79         if(isFull())
 80             throw new RuntimeException(new Exception("array is full"));
 81         
 82         
 83         if(stackNum == 0)
 84         {
 85             if(flag == 1)    // 需要把中间的一个栈 往后面移动
 86                 shiftStackTwo();
 87             
 88             array[stackOneTop ++] = x;
 89             
 90         }else if(stackNum == 1){
 91             if(flag == 1)
 92                 shiftStackTwo();
 93             
 94             array[stackTwoTop --] = x;
 95             
 96         }else if(stackNum == 2){
 97             if(flag == -1)
 98                 shiftStackTwo();
 99             array[stackThreeTop --] = x;
100             
101         }else
102             throw new RuntimeException(new Exception("stackNum is out"));
103     
104         if(isFull())
105             flag = 0;    //array os full
106         if(stackOneTop > stackTwoTop)
107         {
108             flag = 1;    //中间的栈 往后面移动
109         }
110         if (stackTwoBase == stackThreeTop)
111         {
112             flag = -1;    //中间的栈 往前面移动
113         }
114     }
115 
116     public void shiftStackTwo() {
117         switch(flag)
118         {
119             case 0:
120                 throw new RuntimeException(new Exception("array is full"));
121             case 1:    //中间的栈 向后移动 step
122                 // 检查 还有没有可以往后移动的空间
123                 if(stackTwoBase+1 > stackThreeTop)
124                     throw new RuntimeException(new Exception("array is full"));
125                 for( int i = stackTwoBase; i >= stackTwoTop-1; i --)
126                     array[i+1] = array[i];
127                 stackTwoTop ++; stackTwoBase ++;
128                 break;
129             case -1:
130                 // 检查前面还有没空间
131                 if(stackOneTop-1 > stackTwoTop)
132                     throw new RuntimeException(new Exception("array is full"));
133                 for(int i = stackTwoTop-1; i <= stackTwoBase; i++)
134                     array[i-1] = array[i];
135                 stackTwoTop --; stackTwoBase --;
136                 break;
137             default:
138                 break;
139         }
140     }
141     
142     public boolean isEmpty(int stackNum)
143     {
144         boolean b = false;
145         switch (stackNum) {
146         case 0:
147             if(stackOneTop == 0) b = true;
148             break;
149             
150         case 1:
151             if(stackTwoTop == stackTwoBase) b = true;
152             break;
153 
154         case 2:
155             if(stackThreeTop == arrayLength-1) b = true;
156             break;
157             
158         default:
159             throw new RuntimeException(new Exception("stacknum is out"));
160         }
161         return b;
162     }
163     
164     /*
165      * 出站操作
166      */
167     public AnyType pop(int stackNum)
168     {
169         AnyType x ;
170         switch (stackNum) {
171         case 0:
172             if(isEmpty(stackNum))
173                 throw new RuntimeException(new Exception("stack"+stackNum+" is empty"));
174             x = array[--stackOneTop];
175             break;
176         
177         case 1:
178             if(isEmpty(stackNum))
179                 throw new RuntimeException(new Exception("stack"+stackNum+" is empty"));
180             x = array[++stackTwoTop];
181             break;
182             
183         case 2:
184             if(isEmpty(stackNum))
185                 throw new RuntimeException(new Exception("stack"+stackNum+" is empty"));
186             x = array[++stackThreeTop];
187             break;
188             
189         default:
190             throw new RuntimeException(new Exception("stacknum is out"));
191         }
192         return x;
193     }
194     
195 }
View Code

 

posted @ 2017-03-29 20:24  zhangoliver  阅读(583)  评论(0编辑  收藏  举报