数据结构之栈(Java)

目录

自身的特点

适合解决的问题

时间复杂度

顺序栈和链栈的区别

代码

代码练习1(顺序栈的出入栈)

代码练习2(链栈反转数组)

代码练习3(链栈新增删除)

练习代码4(通过栈实现浏览器前进、后退)


  • 自身的特点

    • 只能在一端进行删除和插入操作
    • 先进后出,后进先出 (栈顶删除数据,栈顶插入数据)
    • 数组实现的栈称为顺序栈,链表实现的栈称为链式栈
  • 适合解决的问题

    • 函数调用栈
    • 表达式求值
  • 时间复杂度

    • 不管是顺序栈还是链栈,时间复杂度都是 O(1)
  • 顺序栈和链栈的区别

    • 顺序栈: 静态分配存储, 有闲置和溢出的现象 
    • 链  栈: 动态分配存储, 无闲置和溢出现象  存储利用率高, 元素自由扩充
    • 同顺序表和链表, 顺序栈随机读取快, 链栈 插入 删除快
  • 代码

  • 代码练习1(顺序栈的出入栈)

/**
 * 顺序栈实体类
 */
public class SeqEntity {
    int[] data;
    int top;

    public SeqEntity(int size) {
        this.data = new int[size];
    }

}


/**
 * 顺序栈实现类
 */
public class SeqStack implements BaseClass {
    protected int mixsize = 10;
    protected SeqEntity stack = new SeqEntity(mixsize);

    public SeqStack() {
        init();
    }
    // 初始化 Top
    public void init() {
        stack.top = -1;
    }

    @Override
    public void push(int value) throws Exception {
        if (this.isFull()) {
            throw new Exception("***满栈***");
        }
        stack.top++;
        stack.data[stack.top] = value;
    }

    @Override
    public int pop() throws Exception {
        if (this.isEmpty()) {
            throw new Exception("***空栈***");
        }
        int returnData = stack.data[stack.top];
        stack.data[stack.top] = 0;
        stack.top--;
        return returnData;
    }

    @Override
    public boolean isEmpty() {
        if (stack.top == -1) {
            return true;
        }
        return false;
    }

    @Override
    public boolean isFull() {
        if ((stack.top - 1) == mixsize) {
            return true;
        }
        return false;
    }

    public static void main(String[] args) throws Exception {
        SeqStack seqStack = new SeqStack();
        System.out.println("***开始入栈***");
        seqStack.push(2);
        seqStack.push(3);
        System.out.println(seqStack.stack.top);
        System.out.println(Arrays.toString(seqStack.stack.data));

        System.out.println("***开始出栈***");
        seqStack.pop();
        System.out.println(seqStack.stack.top);
        System.out.println(Arrays.toString(seqStack.stack.data));
    }
}
  • 代码练习2(链栈反转数组)

/**
 * 栈  反转数组
 * 思路 : 先将数组顺序入栈, 再将栈顺序出栈到新数组
 */
public class InvertArray extends SeqStack {
    int[] array = {1, 2, 3, 4, 5, 6, 7, 8, 9};
    protected int mixsize = array.length;

    public static void main(String[] args) throws Exception {

        InvertArray stack = new InvertArray();
        for (int i : stack.array) {
            stack.push(i);
        }
        int[] array_new = new int[stack.mixsize];
        for (int i = 0; i < stack.mixsize; i++) {
            array_new[i] = stack.pop();
        }
        System.out.println(Arrays.toString(array_new));
    }
}
  • 代码练习3(链栈新增删除)

/**
 * 描述链栈节点的数据结构
 */
public class LinkStackNodeEntity {
    /**
     * 数据域
     */
    private int data;
    /**
     * 指针域 指向上一个节点
     */
    private LinkStackNodeEntity next;

    public LinkStackNodeEntity(int value) {
        this.data = value;
    }

    public int getData() {
        return data;
    }

    public void setData(int data) {
        this.data = data;
    }

    public LinkStackNodeEntity getNext() {
        return next;
    }

    public void setNext(LinkStackNodeEntity next) {
        this.next = next;
    }
}



/**
 * 链栈结构体
 */
public class LinkStackEntity {
    /**
     * 描述栈顶, 总是指向最后入栈的节点
     */
    private LinkStackNodeEntity top;
    /**
     * 描述栈的总长度 或说成 链表有几个节点
     */
    private int size;

    public LinkStackNodeEntity getTop() {
        return top;
    }

    public void setTop(LinkStackNodeEntity top) {
        this.top = top;
    }

    public int getSize() {
        return size;
    }

    public void setSize(int size) {
        this.size = size;
    }
}



/**
 * 链栈实现类
 */
public class LinkStack implements BaseClass {

    LinkStackEntity stack = new LinkStackEntity();

    public LinkStack() {
        init();
    }

    /**
     * 初始化
     */
    public void init() {
        stack.setSize(0);
        stack.setTop(null);
    }

    @Override
    public void push(int value) throws Exception {
        LinkStackNodeEntity node = new LinkStackNodeEntity(value);
        node.setNext(stack.getTop());

        stack.setTop(node);
        stack.setSize(stack.getSize() + 1);
    }

    @Override
    public int pop() throws Exception {
        if (this.isEmpty()) {
            throw new Exception("***空栈***");
        }
        int returnData = stack.getTop().getData();
        // 栈顶指向栈顶元素的下一个元素(next指向的元素)
        stack.setTop(stack.getTop().getNext());
        stack.setSize(stack.getSize() - 1);
        return returnData;
    }

    @Override
    public boolean isEmpty() {
        return false;
    }

    @Override
    public boolean isFull() {
        // 链栈是存储空间动态分配的, 没有满栈的情况
        return false;
    }

    /**
     * 打印单链表中的每个元素
     *
     * @param node
     * @return
     */
    public ArrayList<Integer> printNode(LinkStackEntity node) throws Exception {
        ArrayList array = new ArrayList<Integer>();
        LinkStackNodeEntity tmp = node.getTop();
        if (node == null) {
            throw new Exception("***传入的链表为空***");
        }
        while (tmp.getNext() != null) {
            array.add(tmp.getData());
            tmp = tmp.getNext();
        }
        array.add(tmp.getData());
        return array;
    }

    public static void main(String[] args) throws Exception {
        LinkStack myStack = new LinkStack();
        System.out.println("***入栈***");
        myStack.push(1);
        myStack.push(2);
        myStack.push(3);
        myStack.push(4);
        System.out.println("栈的长度为" + myStack.stack.getSize());
        System.out.println(myStack.printNode(myStack.stack));
        System.out.println("***出栈***");
        int popValue = myStack.pop();
        System.out.println("出栈的值为:"+popValue);
        System.out.println("栈的长度为:" + myStack.stack.getSize());
        System.out.println(myStack.printNode(myStack.stack));

    }
}
  • 练习代码4(通过栈实现浏览器前进、后退)

/**
 * 练习题: 实现浏览器 前进、后退 动作
 * 场景会频繁的插入、删除, 选择链栈
 * 个人理解:
 * 浏览器前进操作事件 --> 数据入栈 并 后退栈出栈
 * 浏览器后退操作事件 --> 数据出栈 并 前进栈入栈
 */
public class Exercises01 {

    /**
     * 记录后退节点的栈
     */
    LinkStackEntity backwardStack;

    /**
     * 记录前进节点的栈  -- 前提是后退过
     */
    LinkStackEntity forwardStack;

    public Exercises01() {
        init();
    }

    /**
     * 初始化两个栈
     */
    public void init() {

        backwardStack = new LinkStackEntity();

        forwardStack = new LinkStackEntity();
        backwardStack.setTop(null);
        forwardStack.setTop(null);
        backwardStack.setSize(0);
        forwardStack.setSize(0);
    }

    /**
     * 处理后退事件
     *
     * @throws Exception
     */
    public void on_backward() throws Exception {
        if (isEmpty(forwardStack)) {
            throw new Exception("没有可退的节点了");
        } else {
            int value = pop(forwardStack);
            push(backwardStack, value);
        }
    }

    /**
     * 处理前进事件
     *
     * @return
     * @throws Exception
     */
    public void on_forward(int value) throws Exception {
        // 前进事件栈 --> 数据入栈
        push(forwardStack, value);

        if (!isEmpty(backwardStack)) {
            // 后退事件栈  数据出栈
            pop(backwardStack);
        }
    }

    /**
     * 入栈
     *
     * @param stack
     * @param value
     */
    public void push(LinkStackEntity stack, int value) {
        LinkStackNodeEntity node = new LinkStackNodeEntity(value);
        node.setNext(stack.getTop());
        stack.setTop(node);
        stack.setSize(stack.getSize() + 1);
    }

    /**
     * 出栈
     *
     * @param stack
     * @throws Exception
     */
    public int pop(LinkStackEntity stack) throws Exception {
        if (isEmpty(stack)) {
            throw new Exception("空栈");
        }
        int pop_value = stack.getTop().getData();
        stack.setTop(stack.getTop().getNext());
        stack.setSize(stack.getSize() - 1);

        return pop_value;
    }

    /**
     * 栈 是否为空
     *
     * @param stack
     * @return true 空 , false 非空
     */
    public boolean isEmpty(LinkStackEntity stack) {
        if (stack.getSize() == 0) {
            return true;
        }
        return false;
    }

}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值