数据结构之双端栈

一、了解双端栈

栈是由栈顶和栈尾构成的,栈顶进和出元素,栈底不变
双端栈就是栈的两边各有自己的栈顶和栈尾。分别可以在两端进行进栈和入栈操作

注意:双端栈的两端是它的栈底,它是不变的,栈顶我们一般用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);
    }
}

发布了162 篇原创文章 · 获赞 142 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/weixin_44571270/article/details/103508773