【Java数据结构】手动实现——栈 和 队列

简介: 笔记

栈(Stack)


概念

栈: 一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。进行数据插入和删除操作的一端称为栈顶,另一端称为栈底。栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。


压栈: 栈的插入操作叫做进栈/压栈/入栈,入数据在栈顶。


出栈: 栈的删除操作叫做出栈。出数据在栈顶。


20.png

实现


  1. 利用顺序表实现,即使用尾插 + 尾删的方式实现
  2. 利用链表实现,则头尾皆可

相对来说,顺序表的实现上要更为简单一些,所以优先用顺序表实现栈。

import java.util.Arrays;
public class MyStack<T> {
    private T[]stack;//数组
    private int top;//当前可以存放数据元素的下标——>栈顶指针
    //用构造函数给定一个初始容量10的数组
    public MyStack( ){
        this.stack = (T[])new Object[10];//泛型不能实例化对象,但是可以类型转换
    }
    //判断栈是否满了
    public boolean isFull(){
        return (stack.length == this.top);
    }
    //判断栈是否为空
    public boolean empty(){
        return this.top == 0;
    }
    //入栈操作
    public void push(T value) {
        //判断栈是否已经满了
        if (isFull()){
            this.stack = Arrays.copyOf(stack,2*stack.length);//满了就扩容成原来容量的两倍
        }
        this.stack[this.top] = value;//给top位置添加元素
        this.top++;//top指针指向下一可用空间
    }
    //出栈操作,并返回弹出(删除)栈顶元素
    public T pop() {
        //先判断栈是否为空
        if (empty()) {
            throw new IllegalStateException("栈为空!");
        }
        //弹出元素
        T ret = this.stack[this.top-1];
        this.top--;
        return ret;//返回删除的元素
    }
    //得到栈顶元素,但是不删除
    public T peek() {
        //判断是否为空
        if (empty()){
            throw new IllegalStateException("栈为空!");
        }
        //返回栈顶元素,不删除
        return this.stack[top-1];
    }
    //展示栈元素
    public void show() {
        for (int i = top-1; i>=0 ; i--){
            System.out.print(stack[i]+" ");
        }
        System.out.println();
    }
}

代码测试:

21.png


队列(Queue)


概念


队列: 只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表,队列具有先进先出FIFO(FirstIn First Out)


入队列: 进行插入操作的一端称为队尾(Tail/Rear)


出队列: 进行删除操作的一端称为队头(Head/Front)

22.png


实现


队列也可以 数组链表 的结构实现,使用链表的结构实现更优一些,因为如果使用数组的结构,出队列在数组头上出数据效率会比较低

23.png

public class Node {
    private int val;
    private Node next;
    public Node(int val){
        this.val = val;
    }
    public int getVal() {
        return val;
    }
    public void setVal(int val) {
        this.val = val;
    }
    public Node getNext() {
        return next;
    }
    public void setNext(Node next) {
        this.next = next;
    }
}
public class MyQueue {
    private Node first;
    private Node last;
    //队列是否为空
    public boolean isEmpty() {
        return this.first == null;
    }
    //入队
    public void offer(int value){
        Node node = new Node(value);
        //尾插法,要判断是否第一次插入
        if (this.first == null){
            this.first = node;
            this.last = node;
        }else{
            this.last.setNext(node);
            this.last = node;
        }
    }
    //出队
    public int poll(){
        //判断是否为空
        if (isEmpty()){
            throw new IllegalStateException("队列为空");
        }
        int ret = this.first.getVal();
        this.first = this.first.getNext();
        return ret;//返回出队元素
    }
    //得到队头元素但是不删除
    public int peek() {
        //不要移动first
        if(isEmpty()) {
            throw new UnsupportedOperationException("队列为空!");
        }
        return this.first.getVal();
    }
    //展示队列
    public void show() {
        Node cur = this.first;
        while(cur != null) {
            System.out.print(cur.getVal()+" ");
            cur = cur.getNext();
        }
        System.out.println();
    }
}


代码测试:

24.png


双端队列


后边会专门出一篇双端队列的博客,有兴趣的小伙伴们可以关注一下


概念

双端队列(deque)是指允许两端都可以进行入队和出队操作的队列,deque 是 “double ended queue” 的简称。

那就说明元素可以从队头出队和入队,也可以从队尾出队和入队


Java中的栈和队列

又是这张图!这张图很重要,请务必记住

25.png


Stack

方法 解释
E push(E item) 压栈
E pop() 出栈
E peek() 查看栈顶元素
boolean empty() 判断栈是否为空


Queue

错误处理 抛出异常 返回特殊值
入队列 add(e) offer(e)
出队列 remove() poll()
队首元素 element() peek()


Deque26.png

相关文章
|
2月前
|
C语言
【数据结构】栈和队列(c语言实现)(附源码)
本文介绍了栈和队列两种数据结构。栈是一种只能在一端进行插入和删除操作的线性表,遵循“先进后出”原则;队列则在一端插入、另一端删除,遵循“先进先出”原则。文章详细讲解了栈和队列的结构定义、方法声明及实现,并提供了完整的代码示例。栈和队列在实际应用中非常广泛,如二叉树的层序遍历和快速排序的非递归实现等。
232 9
|
2月前
|
存储 算法
非递归实现后序遍历时,如何避免栈溢出?
后序遍历的递归实现和非递归实现各有优缺点,在实际应用中需要根据具体的问题需求、二叉树的特点以及性能和空间的限制等因素来选择合适的实现方式。
37 1
|
20天前
|
存储 缓存 安全
Java 集合江湖:底层数据结构的大揭秘!
小米是一位热爱技术分享的程序员,本文详细解析了Java面试中常见的List、Set、Map的区别。不仅介绍了它们的基本特性和实现类,还深入探讨了各自的使用场景和面试技巧,帮助读者更好地理解和应对相关问题。
37 5
|
1月前
|
存储 算法 Java
Java 内存管理与优化:掌控堆与栈,雕琢高效代码
Java内存管理与优化是提升程序性能的关键。掌握堆与栈的运作机制,学习如何有效管理内存资源,雕琢出更加高效的代码,是每个Java开发者必备的技能。
55 5
|
2月前
|
存储 缓存 算法
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式,强调了合理选择数据结构的重要性,并通过案例分析展示了其在实际项目中的应用,旨在帮助读者提升编程能力。
68 5
|
2月前
|
存储 算法 Java
数据结构的栈
栈作为一种简单而高效的数据结构,在计算机科学和软件开发中有着广泛的应用。通过合理地使用栈,可以有效地解决许多与数据存储和操作相关的问题。
|
2月前
|
缓存 算法 Java
本文聚焦于Java内存管理与调优,介绍Java内存模型、内存泄漏检测与预防、高效字符串拼接、数据结构优化及垃圾回收机制
在现代软件开发中,性能优化至关重要。本文聚焦于Java内存管理与调优,介绍Java内存模型、内存泄漏检测与预防、高效字符串拼接、数据结构优化及垃圾回收机制。通过调整垃圾回收器参数、优化堆大小与布局、使用对象池和缓存技术,开发者可显著提升应用性能和稳定性。
52 6
|
2月前
|
存储 Java 索引
Java中的数据结构:ArrayList和LinkedList的比较
【10月更文挑战第28天】在Java编程世界中,数据结构是构建复杂程序的基石。本文将深入探讨两种常用的数据结构:ArrayList和LinkedList,通过直观的比喻和实例分析,揭示它们各自的优势与局限,帮助你在面对不同的编程挑战时做出明智的选择。
|
2月前
|
存储 JavaScript 前端开发
执行上下文和执行栈
执行上下文是JavaScript运行代码时的环境,每个执行上下文都有自己的变量对象、作用域链和this值。执行栈用于管理函数调用,每当调用一个函数,就会在栈中添加一个新的执行上下文。
|
2月前
|
存储
系统调用处理程序在内核栈中保存了哪些上下文信息?
【10月更文挑战第29天】系统调用处理程序在内核栈中保存的这些上下文信息对于保证系统调用的正确执行和用户程序的正常恢复至关重要。通过准确地保存和恢复这些信息,操作系统能够实现用户模式和内核模式之间的无缝切换,为用户程序提供稳定、可靠的系统服务。
54 4