在一个数组里面实现三个栈
* 使用一个数组来实现三个栈:
* 这个问题是数组实现一个栈的升级版本,
* 一个数组实现两个栈比较的简单,可以从数组的两端到中间,也可以从中间到两端,以至于实现三个四个五个栈都行,关键是要记住栈的开始处,当栈的容量不够时做好调整
* 就单单对这个问题而言,一个数组实现三个栈又有一下两种处理方式:
* 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 }