java简单实现栈

泛型数组实现

利用泛型数组作为底层数据结构实现栈

定义属性和方法

public class MyStack<T> {
    //利用泛型数组作为底层数据结构实现栈
    private T [] elements;
    private int size = 0;
    //定义默认容量
    private static final int DEFAULT_CAPACITY = 10;
    //无参构造函数
    public MyStack() {
        elements = (T[]) new Object[DEFAULT_CAPACITY];
    }
    //添加元素到栈顶
    public void push(T t){
        ensureCapacity();
        elements[size++] = t;
        System.out.println("push succeed: " + t);
    }
    //扩容方法
    private void ensureCapacity() {
        if (size == elements.length){
            T[] oldElements = elements;
            elements = (T[]) new Object[size + (size >>> 1)];
            System.out.println(elements.length);
            System.arraycopy(oldElements,0,elements,0,size);
            System.out.println("stack is full, capacity is expanded to " + elements.length);
        }
    }
    //弹出栈顶元素并返回
    public T pop(){
        if (size == 0){
            throw new RuntimeException("stack is empty!!!!!!");
        }
        T element = elements[--size];
        elements[size] = null;
        System.out.println("pop succeed: " + element);
        return element;

    }
    //返回栈顶元素(不弹出)
    public T peek(){
        if (size == 0){
            throw new RuntimeException("stack is empty!!!!!!");
        }
        return elements[size - 1];
    }
    //判断栈是否为空
    public boolean isEmpty(){
        return size == 0;
    }

    public int size(){
        return size;
    }

    public String toString(){
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("[");
        for (int i = 0; i < size; i++) {
            stringBuilder.append(elements[i]);
            if (i != size - 1){
                stringBuilder.append(",");
            }
        }
        stringBuilder.append("]");
        return stringBuilder.toString();
    }
}

扩容方法

此处模拟java底层数组扩容机制

1、定义默认容量DEFAULT_CAPACITY = 10,并在构造函数初始化时才开辟空间赋值,节约内存空间。

2、在每次压栈压入元素时调用函数ensureCapacity()判断栈是否已满,已满则扩容致原来长度的1.5倍(java数组底层认为1.5倍对空间利用最合适)

 private static final int DEFAULT_CAPACITY = 10;

 private void ensureCapacity() {
        if (size == elements.length){
            T[] oldElements = elements;
            elements = (T[]) new Object[size + (size >>> 1)];
            System.out.println(elements.length);
            System.arraycopy(oldElements,0,elements,0,size);
            System.out.println("stack is full, capacity is expanded to " + elements.length);
        }
    }

    public void push(T t){
        ensureCapacity();
        elements[size++] = t;
        System.out.println("push succeed: " + t);
    }

测试

对所定义的栈进行方法的测试,包括异常的抛出(利用junit5的断言机制)

public class WorkOneTest {
    @Test
    public void MyStackTest(){
        MyStack<Character> ms = new MyStack<>();
        Assertions.assertThrows(Exception.class, () -> ms.pop());
        Assertions.assertThrows(Exception.class, () -> ms.peek());
        ms.push('a');
        ms.push('b');
        ms.push('@');
        ms.push('d');
        ms.push('e');
        System.out.println(ms.size());
        System.out.println(ms.isEmpty());
        System.out.println(ms.toString());
        System.out.println(ms.peek());
        ms.push('a');
        ms.push('b');
        ms.push('@');
        ms.push('d');
        ms.push('e');
        ms.push('e');
        System.out.println(ms.toString());
        System.out.println(ms.peek());
        System.out.println(ms.pop());
        System.out.println(ms.toString());

    }
}
测试通过

作业

给定一个字符串str。设计一个算法采用顺序栈判断str是否为形如“序列1@序列2”的合法字符串,其中序列2是序列1的逆序,str中恰好只有一个@字符。

思路

首先把字符串转成数组,然后定义两个个标签flag和flag2,遍历字符串入栈,读到@则使标签flag取反,终止本次循环,停止入栈,continue直接开始下一次循环。

从这开始,遍历的i继续,也就是从@的后面开始,由于flag已被取反,后面的入栈if将跳过,转而执行下面的判断if。即入栈元素为@前面的一半。

利用栈的”先进后出“结构,后面的判断为@后一半遍历的同时,把前一半已经入栈的元素先peek对比是否相同,相同则pop弹出释放,不相同则把标签flag2置为false,并直接break退出循环。

最后打印结果。

    @Test
    @DisplayName("作业第一题测试")
    @ParameterizedTest
    @ValueSource(strings = {"asd@dsa","!#$%@%$#!","你好@好你","@"})
    public void WorkOneTest(String str) {
        MyStack<Character> ms = new MyStack<>();
        char[] ch = str.toCharArray();
        boolean flag = false;
        boolean flag2 = true;
        for(int i = 0; i < ch.length; i++){
            if(ch[i] =='@'){
                flag = true;
                continue;
            }
            if(!flag) {
                ms.push(ch[i]);
            }
            else{
                if(ch[i] == ms.peek()){
                    ms.pop();
                }
                else{
                    flag2 = false;
                    break;
                }
            }
        }

        System.out.println("该字符串["+str+"]是否合法: " + flag2 );
    }
}

使用了JUnit5的参数化测试,方便传参测试

    @ParameterizedTest
    @ValueSource(strings = {"asd@dsa","!#$%@%$#!","你好@好你","@"})

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BenChuat

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值