順次記憶構造 - データ構造とアルゴリズム(IV)は、スタックの端部をビス

ダブルエンドスタック


ダブルエンドスタック定義は:プッシュとポップ操作の通りであったスタックの底部の両端の線形形態を指します。
ここに画像を挿入説明
スタックの端部が二重スタックであるので、それは直接スタックインターフェース実装することができ、その動作は同じスタックが、2つのスタックの等価物、スタックは左と右のスタックを定義することができ、内部の方法は、2つのスタックの場合について検討しました、その後、両方を達成するために統合。

/*
    双端栈
 */
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(isLeftEmpty()){
            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;
    }
    //按字符串返回
    public String toString(){
        StringBuilder sb=new StringBuilder();
        sb.append(String.format("ArrayStrackDoubleEnd: %d/%d\n",getSize(),data.length));
        if(isLeftEmpty()){
            sb.append("left :bottom [] top \n");
        }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 [] bottom \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();
    }
}


同じことが、完成した構造は、ここではそれらを繰り返さない、自分自身をテストするために行うことができます。

公開された70元の記事 ウォン称賛56 ビュー1986

おすすめ

転載: blog.csdn.net/qq_43624033/article/details/103569400
おすすめ