数组结构栈和链表结构栈(两种push方式),分别实现先入后出的有序列表

本文介绍了栈的先入后出特性,并对比了数组结构和链表结构栈的实现。数组栈通过初始化数组大小和top指针管理元素,提供了isEmpty和isFull方法。链表栈分为向头和尾部push数据两种情况,前者效率高,后者需要循环操作。总结中指出,向链表头push数据是高效的选择。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

(1)栈是一个先入后出(Filo-Frist In last out)的有序列表
(2)栈是限制线性表中元素的插入和删除只能在线性表的同一端进行的一种特殊线性表。允许插入和删除的一端,为变化的一端,称为栈顶(top),另一端为固定的一端,称为栈底(bottom)
(3)根据栈的定义可知,最先放入栈中元素在栈底,最后放入的元素在栈顶,而删除元素刚好相反,最后放入的元素最先删除,最先放入的元素最后删除

数组结构栈

  1. 使用数组结构栈,需要实例化数组,且传入数组的大小(即最大栈空间)
  2. 需要一个maxSize初始化栈的最大空间,构造器时传入该值
  3. 还需要一个top变量记录栈顶,默认的初始化值为-1
  4. 因为是数组结构,所以需要判断栈是否为空的方法boolean isEmpty(){}
  5. 判断栈是否已满的方法boolean isFall(){}
  6. 入栈::void push(Tree value){}
  7. 出栈::Tree pop(){}
  8. 遍历栈中内容::void showStack(){}

数组栈流程图
在这里插入图片描述
代码

public class StackTest {
    public static void main(String[] args) {
        //创建数组栈
        ArrayStack arrayStack = new ArrayStack(5);
        //入栈
        arrayStack.push(new Tree(1));
        //输出栈
        arrayStack.showStack();
        //出栈
        arrayStack.pop();
        arrayStack.showStack();
    }
}

class ArrayStack {
    //最大栈空间
    public int maxSize;
    //栈顶
    public int top = -1;
    //栈数组
    public Tree[] stack;

    //构造器
    public ArrayStack(int maxSize) {
        this.maxSize = maxSize;
        //初始化栈数组
        stack = new Tree[this.maxSize];
    }
    //判断栈是否满
    public boolean isFall() {
        return top == this.maxSize - 1;
    }
    //判断栈是否空
    public boolean isEmpty() {
        return top == -1;
    }
    //入栈
    public void push(Tree value) {
        if (isFall()) {
            System.out.println("栈满!");
            return;
        }
        //先自身加 1
        stack[++top] = value;
    }
    //出栈
    public Tree pop() {
        if (isEmpty()) {
            throw new RuntimeException("栈为空!");
        }
        Tree value = stack[top];//接收到值之后
        top--;//top--
        return value;
    }
    //循环遍历栈
    public void showStack() {
        if (isEmpty()) {
            System.out.println("栈为空!");
            return;
        }
        for (int i = top; i >= 0 ; i--) {
            System.out.println("stack["+i+"]"+ stack[i]);
        }
    }
}
//创建树类
class Tree {
    private int no;

    public Tree(int no) {
        this.no = no;
    }

    @Override
    public String toString() {
        return "Tree{" +
                "no=" + no +
                '}';
    }
}

控制台

stack[0]Tree{no=1}
栈为空!

链表结构栈

向链表头push数据

  1. 创建链表栈需要Tree结构维护一个指向属性Tree next;
  2. 链表栈不需要指针(top)之类的属性进行记录
  3. 链表栈没有长度限制,不需要进行扩容
  4. 向链表头push数据,更简单,push(入栈)和pop(出栈)不需要进行循环操作,性能最好
  5. 输出数据时,向链表头push数据跟向链表尾push数据,数据顺序是相反的

链表栈流程图
在这里插入图片描述

链表栈代码

public class 优快云LinkedStack {
    public static void main(String[] args) {
        //创建链表栈
        LinkedStack linkedStack = new LinkedStack();
        //入栈
        linkedStack.push(new Tree(1));
        linkedStack.push(new Tree(2));
        linkedStack.push(new Tree(3));
        //显示栈中数据
        linkedStack.showLinkedStack();
        //出栈
        System.out.println("*******出栈*******");
        System.out.println(linkedStack.pop());
        System.out.println("*******出栈后*******");
        linkedStack.showLinkedStack();
    }
}

class LinkedStack {
    //维护一个头节点
    public Tree head = new Tree(0);

    //入栈
    public void push(Tree tree) {
        //保存head的下一个节点
        Tree next = head.next;//头节点的下一个节点,如果是第一次便是空,第二次就不是空了
        //给头节。next点赋值
        head.next = tree;
        //然后把之间的链接起来
        tree.next = next;
    }
    //出栈
    public Tree pop() {
        if (head.next == null) {
            throw new RuntimeException("栈为空!");
        }
        //保存一个节点
        Tree cur = head.next;
        /*
        * 将头节点的下一个指针指向头节点的下一个的下一个
        * 这样就完成了最简单的删除操作
        * */
        head.next = head.next.next;//自我删除
        return cur;
    }
    //循环显示
    public void showLinkedStack() {
        if (head.next == null) {
            System.out.println("栈空!");
            return;
        }
        //维护指针
        Tree temp = head.next;
        while (temp != null) {
            System.out.println(temp);
            temp = temp.next;//指针后移
        }
    }
}

//创建树类
class Tree {
    public int no;
    public Tree next;//保存指向的下一个Tree

    //构造器
    public Tree(int no) {
        this.no = no;
    }

    @Override
    public String toString() {
        return "Tree{" +
                "no=" + no +
                '}';
    }
}

向链表尾push数据

  1. 向链表尾添加数据和删除数据比较麻烦,都需要循环操作,效率低
  2. 由于是向链表尾添加数据,循环输出时是按照加入的顺序进行输出

流程图

在这里插入图片描述
代码

public class 优快云LinkedStack2 {
    public static void main(String[] args) {
        //创建链表栈
        LinkedStack linkedStack = new LinkedStack();
        //入栈
        linkedStack.push(new Tree(1));
        linkedStack.push(new Tree(2));
        linkedStack.push(new Tree(3));
        //显示栈中数据
        linkedStack.showLinkedStack();
        //出栈
        System.out.println("*******出栈*******");
        System.out.println(linkedStack.pop());
        System.out.println("*******出栈后*******");
        linkedStack.showLinkedStack();
    }
}

class LinkedStack {
    //维护一个头节点
    public Tree head = new Tree(0);

    //入栈
    public void push(Tree tree) {
        //维护一个辅助指针
        Tree temp = head;
        while (temp.next != null) {
            temp = temp.next;
        }
        temp.next = tree;//入栈
    }
    //出栈
    public Tree pop() {
        if (head.next == null) {
            System.out.println("栈为空!");
            return null;
        }
        //维护一个辅助指针
        Tree temp = head;
        //temp.next.next找到当前节点的后一个节点的后一个节点为空的
        while (temp.next.next != null) {//如果temp.next.next不等于空,就接着找下一个
            temp = temp.next;//指针后移
        }
        //将需要pop的变量保存起来
        Tree temp1 = temp.next;
        //置空
        temp.next = null;
        return temp1;//返回
    }
    //显示栈
    public void showLinkedStack() {
        if (head.next == null) {
            System.out.println("空!");
            return;
        }
        //维护指针
        Tree temp = head.next;
        while (temp != null) {
            System.out.println(temp);
            temp = temp.next;
        }
    }
}
//创建树类
class Tree {
    public int no;
    public Tree next;//保存指向的下一个Tree

    //构造器
    public Tree(int no) {
        this.no = no;
    }

    @Override
    public String toString() {
        return "Tree{" +
                "no=" + no +
                '}';
    }
}

控制台

Tree{no=1}
Tree{no=2}
Tree{no=3}
*******出栈*******
Tree{no=3}
*******出栈后*******
Tree{no=1}
Tree{no=2}

总结

  1. 数组结构栈:结构比较容易理解,缺点是如果栈的大小不合适需要进行扩容
  2. 链表结构栈,向链表头push数据:不需要进行扩容操作,且出栈和入栈都不需要进行循环,效率高
  3. 链表结构栈,向链表尾push数据:不需要进行扩容,但是出栈和入栈都需要进行循环,效率低,不推荐

PS:如果有错误请指正


END

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值