java数据结构:Stack栈,双端栈的顺序存储结构

栈的顺序存储结构

定义

栈是限定仅在表尾进行插入和删除的线性表【后进先出,简称LIFO结构】
栈顶:允许插入和删除的一段
栈底:另一端
空栈:不包含任何数据元素的栈称为空栈
在这里插入图片描述

栈本身是一个线性表,其数据元素具有线性关系,只不过它是一种特殊的线性表
栈的插入操作,叫做进栈,也称压栈,入栈
栈的删除操作,叫做出栈,也称弹栈
在这里插入图片描述

栈的实现

  1. 使用链式结构
    使用单链表,通过在表的顶端插入来实现push,通过删除表顶端元素实现pop,top操作只是在读取其栈顶的值并进行返回。
  2. 使用数组

栈接口stack的定义

在这里插入图片描述

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();
}

栈的顺序存储结构ArrayStack的定义

在原有list的顺序存储基础上,写stack

在这里插入图片描述

package DS01;

import java.util.Iterator;
/*顺序栈内部是由顺序表实现的
 * ArrayStack
 *   ArrayList
 * */
public class ArrayStack<E> implements Stack<E> {
    private ArrayList<E> list;

    //创建一个默认大小的栈
    public ArrayStack(){
        list=new ArrayList<>();
    }

    //创建一个指定大小的栈
    public ArrayStack(int capacity){
        list=new ArrayList<>(capacity);
    }

    @Override
    public int getSize() {
        return list.getSize();
    }

    @Override
    public boolean isEmpty() {
        return list.isEmpty();
    }

    @Override
    public void push(E e) {
        list.addLast(e);
    }

    @Override
    public E pop() {
        return list.removeLast();
    }

    @Override
    public E peek() {
        return list.getLast();
    }

    @Override
    public void clear() {
        list.clear();
    }

    @Override
    public Iterator<E> iterator() {
        return list.iterator();
    }

    @Override
    public String toString() {
        StringBuilder sb=new StringBuilder();
        sb.append(String.format("ArrayStack: %d/%d\n",getSize(),list.getcapactiy()));
        sb.append('[');
        if(isEmpty()){
            sb.append(']');
        }else{
            for(int i=0;i<getSize();i++){
                sb.append(list.get(i));     //无法直接访问date数组,调用get函数
                if(i==getSize()-1){
                    sb.append(']');
                }else{
                    sb.append(',');
                }
            }
        }
        return sb.toString();
    }
}

编写主函数

package DS01;

import java.util.Iterator;

public class TestArrayStack {
    public static void main(String[] args) {
        ArrayStack<Integer> stack=new ArrayStack<>();
        System.out.println(stack);
        for(int i=1;i<=15;i++){
            stack.push(i);
        }
        System.out.println(stack);
        for(int i=1;i<=10;i++){
            stack.pop();
        }
        System.out.println(stack);

        for(Integer i:stack){
            System.out.print(i+" ");
        }

        Iterator<Integer> it=stack.iterator();
        while(it.hasNext()){
            System.out.print(it.next()+" ");
        }
    }
}

执行结果
在这里插入图片描述

双端栈的顺序存储结构

定义

是将一个线性表的两端当做栈底分别进行入栈和出栈操作
在这里插入图片描述
定义两个指针,leftTop与rightTop
在进行入栈操作时:左边的栈顶是leftTop的右边,右边的栈顶是rightTop的左边【先移动指针,后将值赋给指针所在的位置】
出栈操作时:在栈顶进行指针移动,移出元素,指针减一
在这里插入图片描述

双端栈的顺序存储结构ArrayStackDoubleEnd的定义

在这里插入图片描述

package DS01;

import java.util.Iterator;

//双端栈
class ArrayStackDoubleEnd<E> implements Stack<E> {
    private E[] data;
    //定义方向
    private int lefttop;
    private int righttop;
    //定义默认长度
    private static final int DESAULT_SIZE=10;

    //默认构造函数
    ArrayStackDoubleEnd(){
        this(DESAULT_SIZE);
    }
    //默认有参数的构造函数
    private ArrayStackDoubleEnd(int capacity){
        data=(E[])(new Object [capacity]);
        lefttop=-1;
        righttop=data.length;
    }

获取双端栈中有限元素的得个数

    //获取左边栈中有效元素的个数
    public int getleftSize(){
        return lefttop+1;
    }
    //获取右边栈中有效元素的个数
    public int getrigthSize(){
        return data.length-righttop;
    }
    //获取栈中所有元素的个数
    public int getSize(){
        return getleftSize()+getrigthSize();
    }

判断双端栈中是否为空

    //判断左栈是否为空
    public boolean isleftEmpty(){
        return lefttop==-1;
    }
    //判断右栈是否为空
    public boolean isrightEmpty(){
        return righttop==data.length;
    }
    //判断栈是否为空
    public boolean isEmpty(){
        return isrightEmpty()&&isrightEmpty();
    }

元素的进栈操作

    //在左栈进栈
    public void pushLeft(E e){
        if(lefttop+1==righttop){        //判定是否栈满
            resize(2*data.length);   //扩容
        }
        //进栈
        lefttop++;
        data[lefttop]=e;
    }
    //在右边进栈
    public void pushRight(E e){
        if(lefttop+1==righttop){
            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];
        }
        for (int i = righttop; i < data.length; i++) {
            newdata[i+data.length]=data[i];
        }
        righttop=righttop+data.length;
        data=newdata;
    }

进栈操作

    //进栈元素
    public void push(E e){
        //if(lefttop<=righttop)
        if(Math.random()>=0.5){
            pushLeft(e);
        }else{
            pushRight(e);
        }
    }

弹栈操作

    //左边弹栈
    private 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 data[lefttop--];
    }
    //右边弹栈
    private E popright(){
        if(isrightEmpty()){
            throw new IllegalArgumentException("右栈为空");
        }
        return data[righttop++];
    }
    //弹栈
    public E pop(){
        if(getrigthSize()>=getleftSize()){
            popright();
        }else{
            popLeft();
        }
        return null;
    }

读取栈顶元素

	//读取左边的栈顶元素
    public E peekleft(){
        if(isleftEmpty()){
            throw new IllegalArgumentException("左栈为空");
        }
        return data[lefttop];
    }
    //读取右边的栈顶元素
    public E peekright(){
        if(isleftEmpty()){
            throw new IllegalArgumentException("右栈为空");
        }
        return data[righttop];
    }
	//读取栈顶元素
    public E peek(){
        if(getleftSize()>=getrigthSize()){
            return peekright();
        }else{
            return peekleft();
        }
    }

清空双端栈

    public void clear(){
        data=(E[])(new Object[DESAULT_SIZE]);
        lefttop=-1;
        righttop=data.length;
    }

字符串输出

    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\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 [] 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 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);
    }
}

输出结果
在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值