数据结构之栈(超详细)java实现

栈的定义

栈是一种数据结构,它是一种受限制的线性表,只能在一端添加或删除元素,具有特定的操作规则。栈的特点是先进后出(LIFO,Last In First Out),即最后入栈的元素最先出栈,而最先入栈的元素最后出栈

栈只能在一端删除或者添加元素,这一端称为栈顶

另外一端称为栈底

   生活中类似的栈结构 

  1. 在超市购物时,将购买的商品放入购物篮或购物车中,形成一层一层的堆叠,就像是在组织一个临时的栈结构。

  2. 在餐厅用餐时,将盘子一层一层地叠放在餐桌上,然后按照用餐的顺序依次清理,就像是在处理一个栈结构。

  3. 在电脑中,浏览器的后退按钮就是一个栈结构,每次点击后退按钮就会返回上一个浏览页面,就像是在操作一个栈结构。

 栈的使用:

  java已经给我们提供了实现类 Stack

 

  1. empty(): 这个方法通常用于检查栈是否为空。

  2. peek(): 返回栈顶的元素但不移除它。

  3. pop(): 移除并返回栈顶的元素。

  4. push(element): 将指定的元素压入栈顶。

  5. search(element): 在栈中搜索指定的元素并返回其位置,其中最顶部的元素位置为1。

 代码示例

package stack;

import java.util.Stack;

public class test {
    public static void main(String[] args) {
        Stack<Integer> stack = new Stack<Integer>();

        // 将元素压入栈
        stack.push(5);
        stack.push(10);
        stack.push(15);

        // 查看栈顶元素
        System.out.println("栈顶元素: " + stack.peek());

        // 弹出栈顶元素
        int poppedElement = stack.pop();
        System.out.println("弹出的元素: " + poppedElement);

        // 检查栈是否为空
        System.out.println("栈是否为空? " + stack.isEmpty());

        // 搜索元素
        int index = stack.search(10);
        System.out.println("元素10在栈中的位置: " + index);
    }
}

运行结果:

      

 模拟栈实现

    顺序栈 

          顺序栈使用数组实现,可以用动态数组arraylist,也可以用静态数组,我这里采用后者

          我这里初始化栈顶指针为-1,代表当前栈顶指针永远指向当前元素,有的小伙伴可能会初始化栈   顶指针为0,代表栈顶指针永远指向当前元素的下一个元素

          栈的初始化
private int top;//栈顶指针
    private int maxSize;//最大长度
    private int[] arr;

    public ArrayStack() {
        this.top = -1; // 栈顶指针
        maxSize = 5; // 初始最大长度
        arr = new int[maxSize];
    }
     判断栈是否为空

          如果当前栈顶指针等于初始值-1,那这个栈就是空的,这个没有什么好说的,如果刚开始初始化栈顶指针等于0,那么这里就应该判断栈顶指针是否等于0

 public boolean isEmpty() {
        return top == -1;
    }
 判断栈是否满 

       只要当前栈顶指针等于最大长度等于maxsize-1,那么这个栈就满了, 如果刚开始初始化栈顶指针等于0,那么这里就应该判断栈顶指针是否等于maxsize,而不是maxsize-1;

  public boolean isFull() {
        return top == maxSize - 1;
    }
入栈

入栈之前一定要判断栈是否满了,满了就扩容,如果用的是动态数组,就不需要自己扩容,程序会帮你扩容  然后后移指针

    public void push(int data) {
        // 判断栈满
        if (isFull()) {
            // 扩容,扩大到原来的两倍
            int[] newArray = Arrays.copyOf(arr, 2 * arr.length);
            arr = newArray;
            maxSize = 2 * maxSize;
        }
        arr[++top] = data;
    }
 出栈

 出栈的话,一定要先保存当前指针值,然后再前移指针

  public int pop() {
        if (isEmpty()) {
            throw new EmptyStackException();
        } else {
            int val = arr[top];
            top--;
            return val;
        }
    }
 取栈顶元素

 取栈顶元素和出栈差不多,只不过出栈需要移动栈顶指针

    public int peek() {
        if (isEmpty()) {
            throw new EmptyStackException();
        } else {
            int val = arr[top];
            return val;
        }
    }
完整代码 
class ArrayStack {
    private int top;//栈顶指针
    private int maxSize;//最大长度
    private int[] arr;

    public ArrayStack() {
        this.top = -1; // 栈顶指针
        maxSize = 5; // 初始最大长度
        arr = new int[maxSize];
    }

    // 入栈
    public void push(int data) {
        // 判断栈满
        if (isFull()) {
            // 扩容,扩大到原来的两倍
            int[] newArray = Arrays.copyOf(arr, 2 * arr.length);
            arr = newArray;
            maxSize = 2 * maxSize;
        }
        arr[++top] = data;
    }

    // 出栈
    public int pop() {
        if (isEmpty()) {
            throw new EmptyStackException();
        } else {
            int val = arr[top];
            top--;
            return val;
        }
    }
   //取栈顶元素
    public int peek() {
        if (isEmpty()) {
            throw new EmptyStackException();
        } else {
            int val = arr[top];
            return val;
        }
    }

    // 判断满
    public boolean isFull() {
        return top == maxSize - 1;
    }

    // 判断非空
    public boolean isEmpty() {
        return top == -1;
    }
}

    链表栈

链表栈和数组实现的栈的基本功能是相似的,都是遵循后进先出(LIFO)的原则。不过,链表栈不需要像数组实现的栈一样进行判断是否已满,也不需要扩容。这是因为链表在内存中可以动态地分配空间,因此可以根据需要动态地增加或减少节点,从而避免了数组实现的栈可能遇到的容量限制和扩容问题。

 这里直接上完整代码

我这里用到是泛型类 

class LinkedListStack<T> {
    private Node<T> head;

    // 入栈
    public void push(T data) {
        // 头插法
        head = new Node<>(data, head);
    }

    // 出栈
    public T pop() {
        if (isEmpty()) {
            throw new IllegalStateException("Stack is empty");
        }
        T data = head.data;
        head = head.next;
        return data;
    }

    // 打印栈顶元素
    public T peek() {
        if (isEmpty()) {
            throw new IllegalStateException("Stack is empty");
        }
        return head.data;
    }

    // 判断栈为空
    public boolean isEmpty() {
        return head == null;
    }

    // 节点类
    private static class Node<T> {
        T data;
        Node<T> next;

        public Node(T data, Node<T> next) {
            this.data = data;
            this.next = next;
        }
    }
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值