Java数据结构———栈

  • 前言

本文将使用链表来实现栈结构,如果你对链表还不熟悉,建议先看我的上一篇文章LinkedList源码解析(手把手带你熟悉链表) 有对链表的讲解,本文将不再讲解链表

  • 什么是栈?

栈是一种先进后出的数据结构,可以理解为一个容器,最先进入的数据在最底部,新数据会一层层累加在旧数据的顶部,而取数据的时候先从顶部开始取,所以取出来的数据肯定是最后添加的数据

生活中的小例子: 每次洗完碗,把碗一个一个摞在一起,当下次使用的时候,拿的第一个碗肯定是最顶部的,也就是最后一个洗完的碗

  • 栈结构图

 String[] arr = {"A","B","C","D","E"}

假如我们要把这个数组添加到栈,那么

进栈的顺序应该是:

A->进栈
B->进栈
C->进栈
D->进栈
E->进栈

出栈的顺序应该是:

E->出栈
D->出栈
C->出栈
B->出栈
A->出栈

在这里插入图片描述

下面我们将使用单链表来实现栈结构

  • 节点创建

在这里插入图片描述

  private class Node {
      public T item;
      public Node next;

      public Node(T item, Node next) {
          this.item = item;
          this.next = next;
      }
  }
  • 创建类 MyStack

成员变量:
headNode: 用为记录头结点
size: 用来记录链表长度
构造方法:
由于使用单链表,所以在构造方法的时候,需要先创建一个头结点

public class MyStack {
  //记录头结点
   private Node headNode;
   //链表长度
   private int size;

   /**
    * 构造方法中初始化头结点
    */
   public MyStack() {
       this.headNode = new Node(null, null);
   }
   
   /**
    * 节点实体类
    */
   private class Node {
      public T item;
      public Node next;

      public Node(T item, Node next) {
          this.item = item;
          this.next = next;
      }
  }
 }
  • 数据进栈 push

数据进栈有两种情况:

  1. 链表为空 直接添加到头结点后面
  2. 链表有数据 断开头结点与头结点后面的节点,并插入中间重新建立连接

先看链表为空的情况:
在这里插入图片描述

链表有数据的情况:
在这里插入图片描述

插入之后:
在这里插入图片描述

代码实现:

   /**
    * 数据进栈
    */
   public T push(T value) {
       //先拿到头结点
       Node headNode = this.headNode;
       //创建一个新的节点存储数据
       Node newNode = new Node(value, null);
       //判断链表是否为空
       if (isEmpty()) {
           //如果链表为空,数据直接添加在头结点后面
           headNode.next = newNode;
       } else {
           //如果链表不为空,先获取到头节点的下一个节点(老节点)
           //然后插入到两个节点之间
           Node oldNode = headNode.next;
           //头结点的下一个节点指向新节点
           headNode.next = newNode;
           //新节点的下一个节点指向老节点
           newNode.next = oldNode;
       }
       size++;
       return value;
   }
  • 数据出栈 pop

  1. 数据出栈每次最先弹出的是最前(上)面的数据
  2. 数据出栈需要删除该节点,并重新建立头结点与当前节点的下一个节点的连接

在这里插入图片描述

代码实现:

   /**
    * 数据出栈
    */
   public T pop() {
       //判断链表是否为空
       if (isEmpty()) {
           return null;
       }
       //获取头结点的下一个节点
       Node currentNode = this.headNode.next;
       //将准备弹出的节点断开连接
       this.headNode.next = currentNode.next;
       size--;
       return currentNode.item;
   }
  • 总结

栈作为一种数据结构,它按照先进后出的原则存储数据,先进入的数据被压入栈底,最后的数据在栈顶,需要读数据的时候从栈顶开始弹出数据(最后一个数据被第一个读出来)。

  • 完整代码

package test;

import java.util.Iterator;

/**
 * 自定义栈结构
 */
public class MyStack<T> implements Iterable<T> {
    //记录头结点
    private Node headNode;
    //链表长度
    private int size;

    /**
     * 构造方法中初始化头结点
     */
    public MyStack() {
        this.headNode = new Node(null, null);
    }

    /**
     * 数据进栈
     */
    public T push(T value) {
        //先拿到头结点
        Node headNode = this.headNode;
        //创建一个新的节点存储数据
        Node newNode = new Node(value, null);
        //判断链表是否为空
        if (isEmpty()) {
            //如果链表为空,数据直接添加在头结点后面
            headNode.next = newNode;
        } else {
            //如果链表不为空,先获取到头节点的下一个节点(老节点)
            //然后插入到两个节点之间
            Node oldNode = headNode.next;
            //头结点的下一个节点指向新节点
            headNode.next = newNode;
            //新节点的下一个节点指向老节点
            newNode.next = oldNode;
        }
        size++;
        return value;
    }

    /**
     * 数据出栈
     */
    public T pop() {
        //判断链表是否为空
        if (isEmpty()) {
            return null;
        }
        //获取头结点的下一个节点
        Node currentNode = this.headNode.next;
        //将准备弹出的节点断开连接
        this.headNode.next = currentNode.next;
        size--;
        return currentNode.item;
    }

    /**
     * 判断当前是否为空链表
     */
    public boolean isEmpty() {
        if (size == 0 || headNode == null || headNode.next == null) {
            return true;
        }
        return false;
    }

    public int getSize() {
        return size;
    }

    @Override
    public Iterator<T> iterator() {
        return new Iterator<T>() {
            Node currentNode = headNode;

            @Override
            public boolean hasNext() {
                return currentNode.next != null;
            }

            @Override
            public T next() {
                currentNode = currentNode.next;
                return currentNode.item;
            }
        };
    }

    private class Node {
        public T item;
        public Node next;

        public Node(T item, Node next) {
            this.item = item;
            this.next = next;
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值