【Java基础】栈(Stack) & 队列(Queue)

简介: 栈:一种特殊的线性表,其只允许在固定的一端进行插入和删除元素操作。队列:只允许在一端进行插入数据操作,在另一端进行删除数据操作的特殊线性表。

 1. (Stack)

1.1 概念

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

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

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

1.2 实现

1. 利用顺序表实现,即使用尾插 + 尾删的方式实现

2. 利用链表实现,则头尾皆可

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


基于数组的顺序栈,实现代码如下:

import java.util.ArrayList;
import java.util.List;
import java.util.NoSuchElementException;
/**
 * 基于数组的顺序栈实现
 * @param <E>
 */
public class MyStack<E> {
    // 当前栈的数据个数
    private int size;
    // 实际存储数据的动态数组 - ArrayList
    private List<E> data=new ArrayList<>();
    //入栈
    public void push(E val){
        //尾插
        data.add(val);
        size++;
    }
    //出栈,并返回栈顶元素
    public E pop(){
        if(isEmpty()){
            // 栈为空,没有栈顶元素
            throw new NoSuchElementException("stack is empty! cannot pop!");
        }
        // 删除栈顶元素
        E val = data.remove(size - 1);
        size --;
        return val;
        // 等同于 return data.remove(--size);
    }
    //只返回栈顶元素
    public E peek(){
        if(isEmpty()){
            // 栈为空,没有栈顶元素
            throw new NoSuchElementException("stack is empty! cannot peek!");
        }
        return data.get(size-1);
    }
    //判断栈是否为空
    public boolean isEmpty(){
        return size == 0;
    }
    @Override
    public String toString() {
        StringBuilder sb=new StringBuilder();
        sb.append("[");
        for (int i = 0; i < size; i++) {
            sb.append(data.get(i));
            if(i!=size-1){
                // 此时还没到栈顶,还没到数组末尾
                sb.append(",");
            }
        }
        sb.append("]");
        return sb.toString();
    }
}

image.gif

引用方法如下:

public class StackTest {
    public static void main(String[] args) {
        MyStack<Integer> stack=new MyStack<>();
        stack.push(1);
        stack.push(2);
        stack.push(3);
        //打印栈所有元素
        System.out.println(stack);
        //打印栈顶元素
        System.out.println(stack.peek());
        //出栈,并打印栈顶元素
        stack.pop();
        System.out.println(stack);
    }
}

image.gif

2. 队列(Queue)

2.1 概念

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

先进先出

2.2 实现

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

基于链表实现的基础队列,实现代码如下:

接口类:

public interface IQueue<E> {
    // 入队
    void offer(E val);
    //出队
    E poll();
    //返回队首元素
    E peek();
    //判断队列是否为空
    boolean isEmpty();
}

image.gif

队列类:

import stack_queue.queue.IQueue;
import java.util.NoSuchElementException;
/**
 * 基于链表实现的基础队列
 * @param <E>
 */
public class MyQueue<E> implements IQueue<E> {
    // 链表的每个节点
    private class Node{
        E val;
        Node next;
        public Node(E val){
            this.val=val;
        }
    }
    // 当前队列中的元素个数
    private int size;
    // 队首
    private Node head;
    //队尾
    private Node tail;
    @Override
    public void offer(E val) {
        Node node=new Node(val);
        if(head==null){
            // 此时链表为空
            head=tail=node;
        }else {
            tail.next=node;
            tail=node;
        }
        size++;
    }
    @Override
    public E poll() {
        if(isEmpty()){
            throw new NoSuchElementException("queue is empty! cannot poll");
        }
        Node node=head;
        head=node.next;
        // 将原来头节点脱钩
        node.next=null;
        size--;
        return node.val;
    }
    @Override
    public E peek() {
        if(isEmpty()){
            throw new NoSuchElementException("queue is empty! cannot peek");
        }
        return head.val;
    }
    @Override
    public boolean isEmpty() {
        return size==0;
    }
    @Override
    public String toString() {
        StringBuilder sb=new StringBuilder();
        sb.append("[");
        // 链表的遍历
        for(Node x=head;x!=null;x=x.next){
            sb.append(x.val);
            if(x.next!=null){
                // 还没走到链表尾部
                sb.append(",");
            }
        }
        sb.append("]");
        return sb.toString();
    }
}

image.gif

引用方法如下:

import stack_queue.queue.impl.MyQueue;
public class QueueTest {
    public static void main(String[] args) {
        IQueue iQueue=new MyQueue();
        iQueue.offer(1);
        iQueue.offer(2);
        iQueue.offer(3);
        System.out.println(iQueue);
        System.out.println(iQueue.peek());
        iQueue.poll();
        System.out.println(iQueue);
    }
}

image.gif


相关文章
|
5月前
|
前端开发 Java
java实现队列数据结构代码详解
本文详细解析了Java中队列数据结构的实现,包括队列的基本概念、应用场景及代码实现。队列是一种遵循“先进先出”原则的线性结构,支持在队尾插入和队头删除操作。文章介绍了顺序队列与链式队列,并重点分析了循环队列的实现方式以解决溢出问题。通过具体代码示例(如`enqueue`入队和`dequeue`出队),展示了队列的操作逻辑,帮助读者深入理解其工作机制。
150 1
|
7月前
|
存储 IDE Java
java设置栈内存大小
在Java应用中合理设置栈内存大小是确保程序稳定性和性能的重要措施。通过JVM参数 `-Xss`,可以灵活调整栈内存大小,以适应不同的应用场景。本文介绍了设置栈内存大小的方法、应用场景和注意事项,希望能帮助开发者更好地管理Java应用的内存资源。
352 4
|
8月前
|
存储 监控 Java
JAVA线程池有哪些队列? 以及它们的适用场景案例
不同的线程池队列有着各自的特点和适用场景,在实际使用线程池时,需要根据具体的业务需求、系统资源状况以及对任务执行顺序、响应时间等方面的要求,合理选择相应的队列来构建线程池,以实现高效的任务处理。
328 12
|
9月前
|
存储 算法 Java
Java 内存管理与优化:掌控堆与栈,雕琢高效代码
Java内存管理与优化是提升程序性能的关键。掌握堆与栈的运作机制,学习如何有效管理内存资源,雕琢出更加高效的代码,是每个Java开发者必备的技能。
224 5
|
10月前
|
存储 算法 Java
🧠Java零基础 - Java栈(Stack)详解
【10月更文挑战第17天】本文收录于「滚雪球学Java」专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅!持续更新中,up!up!up!!
366 2
|
11月前
|
存储 安全 Java
【用Java学习数据结构系列】探索栈和队列的无尽秘密
【用Java学习数据结构系列】探索栈和队列的无尽秘密
92 2
|
11月前
|
算法 Java API
【用Java学习数据结构系列】对象的比较(Priority Queue实现的前提)
【用Java学习数据结构系列】对象的比较(Priority Queue实现的前提)
99 1
|
11月前
|
存储 算法 Java
【用Java学习数据结构系列】用堆实现优先级队列
【用Java学习数据结构系列】用堆实现优先级队列
149 0
|
存储 算法 安全
【Java 数据结构及算法实战】系列 014:Java队列08——数组实现的双端队列ArrayDeque
【Java 数据结构及算法实战】系列 014:Java队列08——数组实现的双端队列ArrayDeque
241 0
【Java 数据结构及算法实战】系列 014:Java队列08——数组实现的双端队列ArrayDeque
|
存储 算法 安全
【Java数据结构及算法实战】系列012:Java队列06——数组实现的优先级阻塞队列PriorityBlockingQueue
【Java数据结构及算法实战】系列012:Java队列06——数组实现的优先级阻塞队列PriorityBlockingQueue
190 0

热门文章

最新文章