数据结构与算法---顺序存储结构(栈)

顺序栈(ArrayStack)
顺序栈是限定仅在表尾进行插入和删除操作的线性表
顺序栈要进行的某些功能,其顺序表ArrayList中也有同样的操作,基于面向对象,可用对象直接调用。

  1. 写一个接口Stack,在里面定义顺序栈即将要实现的某些功能。同样,跟List一样需要继承Iterable类,在测试类中遍历数组时,可使用foreach循环,支持不使用下标来遍历数组。
package DS01.动态数组;

public interface Stack<E> extends Iterable<E> {
    //获取当前栈的有效元素个数
    int getSize();
    //栈是否为空
    boolean isEmpty();
    //弹栈
    E pop();
    //进栈
    void push(E e);
    //返回当前栈顶的元素
    E peek();
    //清空当前栈
    void clear();
}

  1. 顺序栈ArrayStack继承Stack接口,实现多种方法,在实现某些方法时,发现于顺序表ArrayList的某些操作一样,基于面向对象思想,可直接通过对象直接引用。
package DS01.动态数组;
/*
* 顺序栈是基于顺序表而实现的
* 可以在ArrayStack内部直接创建一个ArrayList的对象
* 就可以通过对象直接调用ArrayList的方法了
* */
import java.util.Iterator;

public class ArrayStack<E> implements Stack<E> {
  //定义一个ArrayList类型的变量
    private ArrayList<E> list;
    //创建一个默认长度的栈
    public  ArrayStack(){//在创建ArrayStack的对象时其实就是创建了一个ArrayList的对象

        list=new ArrayList<>();
    }
    //创建一个一个指定长度capacity长度的栈
    public ArrayStack(int capacity){
        list=new ArrayList<>(capacity);
    }
    @Override
    public int getSize() {
        return list.getSize();
    }

    @Override
    public boolean isEmpty() {
        return list.isEmpty();
    }
	//弹栈操作其实就是顺序表的删除表尾元素
    @Override
    public E pop() {
         return list.removeLast();
    }
	//压栈操作就是顺序表中的在表尾添加元素
    @Override
    public void push(E e) {
        list.addLast(e);
    }
	//返回当前栈顶元素其实就是在顺序表中返回最后一个位置的元素
    @Override
    public E peek() {
        return list.get(getSize()-1);
    }
    @Override
    public void clear() {
        list.clear();
    }
	//接口Stack继承Iterable类
	//就继承了iterator()这个函数
	//然后实现此接口Stack的类ArrayStack就必须重写此函数
    @Override
    public Iterator<E> iterator() {
        return list.iterator();
    }
    public String toString(){
        StringBuilder sb=new StringBuilder();//运用这个是因为在打印字符串时每次都要重新打印一个字符串
        sb.append(String.format("ArrayList: %d/%d\n",getSize(),list.getCapacity()));
        sb.append('[');
        if(isEmpty()){
            sb.append(']');
        }else {
            for(int i=0;i<getSize();i++){
                sb.append(list.get(i));
                if(i==getSize()-1){
                    sb.append(']');
                }else {
                    sb.append(',');
                }
            }
        }
        return sb.toString();
    }
}

  1. 编写测试类,进行调试
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<=5;i++) {
            stack.push(i);
        }
        //打印对象就是打印该对象的toString();
        System.out.println(stack);
    }
}

4.运行结果
在这里插入图片描述注意:顺序栈的一系列操作都是基于顺序表来实现的,所以在进行ArrayStack一系列操作时,ArrayList的准备工作一定要做好。

双端栈(ArrayStackDoubleEnd)
所谓双端链栈,其实就是将一个线性表的两端当作栈底分别进行入栈和出栈操作。

  1. 双端栈有些方法也是实现接口Stack的,然后也是实现自己的,跟线性表就没有关系了。
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){
        if(capacity<=0){
            throw new IllegalArgumentException("容量不能小于0");
        }
        //创建一个新数组
        data=(E[])(new Object[capacity]);
        //左栈顶初始化下标为-1
        leftTop=-1;
        //右栈顶初始化下标为数组长度
        rightTop=data.length;
    }
    //获取左栈中有效元素个数
    public int getLeftSize(){
        return  rightTop+1;
    }
    //获取右栈中有效元素个数
    public int getRightSize(){
        return data.length-rightTop;
    }
    //获取栈中所有元素的个数
    @Override
    public int getSize() {
        return getLeftSize()+getRightSize();
    }
    //判断左栈是否为空
    public  boolean LeftisEmpty(){
        return leftTop==-1;
    }
    //判断右栈是否为空
    public boolean RightisEmpty(){
        return rightTop==data.length;
    }
    //判断栈是否为空
    @Override
    public boolean isEmpty() {
        return LeftisEmpty()&&RightisEmpty();
    }
    public E Leftpop(){
        if(LeftisEmpty()){
           throw new IllegalArgumentException("左栈为空");
        }
        E ret=data[leftTop--];
        //如果当前容量小于总容量的1/4切当前容量除2之后必须大于默认容量时缩容
        if(getSize()<=data.length/4&&data.length/2>10){
            resize(data.length/2);
        }
        return ret;

    }
    public E Rightpop(){
        if(RightisEmpty()){
            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 Leftpop();
        }else{
           return  Rightpop();
        }
    }

    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=data.length-1;i>=rightTop;i--){
                newData[i+data.length]=data[i];
            }
            rightTop=rightTop+data.length;//更新右栈顶
        }else{//缩容时右边
            for(int i=data.length-1;i>rightTop;i--){
                newData[i-newData.length]=data[i];
            }
            rightTop=rightTop-newData.length;
        }
        data=newData;

    }
    public  void Leftpush(E e){
    	//判满
        if(leftTop+1==rightTop){
            resize(data.length*2);
        }
        leftTop++;
        data[leftTop]=e;
    }
    public void Rightpush(E e){
        if(rightTop-1==leftTop){
            resize(data.length*2);
        }
        rightTop--;
        data[rightTop]=e;
    }
    @Override
    public void push(E e) {
        if(getLeftSize()<=getRightSize()){
            Leftpush(e);
        }else{
            Rightpush(e);
        }
    }
    public E Leftpeek(){
        if(LeftisEmpty()){
            throw new IllegalArgumentException("左栈为空");
        }
        return data[leftTop];
    }
    public E Rightpeek(){
        if(RightisEmpty()){
            throw new IllegalArgumentException("右栈为空");
        }
        return data[rightTop];
    }
    @Override
    //返回当前栈顶的元素
    public E peek() {
        if(getLeftSize()>=getRightSize()){
            return Leftpeek();
        }else{
            return Rightpeek();
        }
    }
    //清空当前的栈
    @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("ArrayStackDoubleEnd: %d/%d\n",getSize(),data.length));
        if(LeftisEmpty()){
            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(RightisEmpty()){
            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;
    }
}

  1. 编写测试类
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.Leftpush(i);
        }
        for(int i=1;i<=6;i++){
            stack.Rightpush(i);
        }
        System.out.println(stack);


    }
}
  1. 运行结果
    在这里插入图片描述
    注意哦,代码中有大部分代码解释,相信以大家的智慧肯定能读懂的。
发布了49 篇原创文章 · 获赞 4 · 访问量 904

猜你喜欢

转载自blog.csdn.net/weixin_45404784/article/details/103487284