一、了解双端栈
栈是由栈顶和栈尾构成的,栈顶进和出元素,栈底不变
双端栈就是栈的两边各有自己的栈顶和栈尾。分别可以在两端进行进栈和入栈操作
注意:双端栈的两端是它的栈底,它是不变的,栈顶我们一般用LeftTop和RightTop作为标记表示,进栈和出栈是直接在两端的Top位置进行。
二、双端栈的顺序存储结构ArrayStackDoubleEnd的定义
由图可知我们的双端栈是用数组作为基本来实现的,为什么不用线性表或者说用ArrayStack去实现呢?
答:因为线性表和顺序栈这两个和双端栈差异太大,复用它们的代码,实现不了双端栈的一些功能,所以我们就只能采用最基本的数组去实现它!
记住:所有的顺序存储结构都可以直接由数组进行实现,有时候采用其他的只是为了提高代码的复用。
运行机制差距太大的话,就不能采用其他的只能用数组实现了!
三、代码如下
Stack.java:
package DS01.动态数组;
/*
线性表的一种特殊情况 栈
ArrayStack extends ArrayList
ArrayList当做是ArraySatck的一个成员变量
*/
public interface Stack<E> extends Iterable<E>{
//获取栈中元素的个数
int getSize();
//判断栈是否为空
boolean isEmpty();
//将元素e进栈
void push(E e);
//弹栈一个元素并返回
E pop();
//查看当前栈顶元素
E peek();
//清空栈
void clear();
}
ArrayStackDoubleEnd.java:
package DS01.动态数组;
import java.util.Iterator;
/*
* 双端栈
* */
public class ArrayStackDoubleEnd<E> implements Stack<E>{
private static final int DEFAULT_SIZE=10;
private E[] data;
private int leftTop;
private int rightTop;
public ArrayStackDoubleEnd(){
this(DEFAULT_SIZE);
}
public ArrayStackDoubleEnd(int capacity){
data=(E[])(new Object[capacity]);
leftTop=-1;
rightTop=data.length;
}
//获取左栈中有效元素个数
public int getLeftSize(){
return leftTop+1;
}
//获取右栈中有效元素个数
public int getRightSize(){
return data.length-rightTop;
}
//获取栈中所有元素的个数
@Override
public int getSize() {
return getLeftSize()+getRightSize();
}
//判断左栈是否为空
public boolean isLeftEmpty(){
return leftTop==-1;
}
//判断右栈是否为空
public boolean isRightEmpty(){
return rightTop==data.length;
}
//判断栈是否为空
@Override
public boolean isEmpty() {
return isLeftEmpty()&&isRightEmpty();
}
//在左栈进栈
public void pushLeft(E e){
//满了扩容
if(leftTop+1==rightTop){
resize(2*data.length);
}
leftTop++;
data[leftTop]=e;
}
//在右栈进栈
public void pushRight(E e){
if(rightTop-1==leftTop){
resize(2*data.length);
}
rightTop--;
data[rightTop]=e;
}
private void resize(int newLen){
E[] newData=(E[])(new Object[newLen]);
//扩容和缩容时左边的复制
for(int i=0;i<=leftTop;i++){
newData[i]=data[i];
}
//扩容时右边的复制
if(newData.length>data.length){
for(int i=rightTop;i<data.length;i++){
newData[i+data.length]=data[i];
}
rightTop=rightTop+data.length;
}else{//缩容时右边的复制
for(int i=rightTop;i<data.length;i++){
newData[i-newData.length]=data[i];
}
rightTop=rightTop-newData.length;
}
data=newData;
}
//进栈元素e
@Override
public void push(E e) {
if(getLeftSize()<=getRightSize()){
pushLeft(e);
}else{
pushRight(e);
}
}
public E popLeft(){
if(isLeftEmpty()){
throw new IllegalArgumentException("左栈为空");
}
E ret=data[leftTop--];
if(getSize()<=data.length/4&&data.length/2>10){
resize(data.length/2);
}
return ret;
}
public E popRight(){
if(isRightEmpty()){
throw new IllegalArgumentException("右栈为空");
}
E ret=data[rightTop++];
if(getSize()<=data.length/4&&data.length/2>=10){
resize(data.length/2);
}
return ret;
}
@Override
public E pop() {
if(getLeftSize()>=getRightSize()){
return popLeft();
}else{
return popRight();
}
}
public E peekLeft(){
if(isLeftEmpty()){
throw new IllegalArgumentException("左栈为空");
}
return data[leftTop];
}
public E peekRight(){
if(isRightEmpty()){
throw new IllegalArgumentException("右栈为空");
}
return data[rightTop];
}
@Override
public E peek() {
if(getLeftSize()>=getRightSize()){
return peekLeft();
}else{
return peekRight();
}
}
@Override
public void clear() {
data= (E[]) new Object[DEFAULT_SIZE];
leftTop=-1;
rightTop=data.length;
}
@Override
public String toString() {
StringBuilder sb=new StringBuilder();
sb.append(String.format("ArrayStackDoubleEnd: %d/%d\n",getSize(),data.length));
if(isLeftEmpty()){
sb.append("left :bottom [] top");
}else{
sb.append("left :bottom [");
for(int i=0;i<=leftTop;i++){
sb.append(data[i]);
if(i==leftTop){
sb.append("] top");
}else{
sb.append(',');
}
}
}
sb.append('\n');
if(isRightEmpty()){
sb.append("right:top [] bootom\n");
}else {
sb.append("right:top [");
for(int i=rightTop;i<data.length;i++){
sb.append(data[i]);
if(i==data.length-1){
sb.append("] bottom");
}else{
sb.append(',');
}
}
}
return sb.toString();
}
@Override
public Iterator<E> iterator() {
return null;
}
}
测试类:
package DS01.动态数组;
public class TestArrayStackDoubleEnd {
public static void main(String[] args) {
ArrayStackDoubleEnd<Integer> stack=new ArrayStackDoubleEnd<>();
System.out.println(stack);
for(int i=1;i<=6;i++){
stack.pushLeft(i);
}
for(int i=1;i<=6;i++){
stack.pushRight(i);
}
System.out.println(stack);
for(int i=1;i<=8;i++){
System.out.print(stack.pop()+" ");
}
System.out.println();
System.out.println(stack);
}
}