
🌸雨落在了我的手上:个人主页
🐟个人仓库:Gitee仓库
❄️个人专栏:<<JaveSe>> <<C语言>> <<C语言数据结构>>**
🔥🔥🔥 人生格言:无人扶我青云志,我自踏雪至山巅
🎬 博主简介:

目录
内容大纲:
本文介绍了三种常见的数据结构:栈、队列和双端队列。栈遵循后进先出(LIFO)原则,使用标准库Stack类演示了入栈、出栈等操作,并基于顺序表实现了自定义栈。队列遵循先进先出(FIFO)原则,通过LinkedList实现的Queue接口展示了队列操作,并基于单链表实现了自定义队列。双端队列(Deque)支持两端操作,通过ArrayDeque类演示了头尾插入、删除等特性。每种数据结构都包含概念讲解、标准库使用示例和模拟实现代码,帮助理解其底层原理和应用场景。
一:栈(Stack)
1.概念
栈:⼀种特殊的线性表,其只允许在固定的⼀端进⾏插⼊和删除元素操作。进⾏数据插⼊和删除操作 的⼀端称为栈顶,另⼀端称为栈底。栈中的数据元素遵守后进先出LIFO(LastInFirstOut)的原则。
压栈:栈的插⼊操作叫做进栈/压栈/⼊栈,⼊数据在栈顶。
出栈:栈的删除操作叫做出栈。出数据在栈顶。


2.栈的使用
这里我们直接调用标准库里面的类,给大家看下效果

代码如下:
java
import java.util.Stack;
//利用标准库里面的stack来测试栈
public class StackDemo {
public static void main(String[] args) {
Stack<Integer> stack = new Stack<>();
//入栈1-2-3-4
stack.push(1);
stack.push(2);
stack.push(3);
stack.push(4);
//出栈4-3-2-1
System.out.println(stack.pop());
System.out.println(stack.pop());
System.out.println(stack.pop());
System.out.println(stack.pop());
//取栈顶元素4
//System.out.println(stack.peek());
//检查栈是否为空
if (stack.empty()){
System.out.println("栈为空");
}else {
System.out.println("栈不为空");
}
}
}
结果:

3.栈的模拟实现

从上图中可以看到,Stack继承了Vector,Vector和ArrayList类似,都是动态的顺序表,不同的是 Vector是线程安全的。
这里我们来手搓实现Stack,这里我们是基于顺序表来实现的
java
//基于顺序表,手搓栈
public class MyStack {
public int[] array;
public int size;
public MyStack() {
array=new int[1000];
size=0;
}
//扩容
public void reallocate(){
int[] newArray =new int[array.length*2];
for (int i=0;i<size;i++){
newArray[i] = array[i];
}
this.array=newArray;
}
//入栈,本质就是尾插
public void push(int value){
//先判断空间是否还够,不够就扩容
if (size>=array.length){
reallocate();
}
array[size]=value;
size++;
}
//出栈,本质就是尾删
public int pop(){
if (size==0){
throw new RuntimeException("栈为空");
}
int ret = array[size-1];
size--;
return ret;
}
//取栈顶元素
public int peek(){
if (size==0){
throw new RuntimeException("栈为空");
}
return array[size-1];
}
public static void main(String[] args) {
MyStack stack = new MyStack();
stack.push(1);
stack.push(2);
stack.push(3);
stack.push(4);
System.out.println(stack.pop());
System.out.println(stack.pop());
System.out.println(stack.pop());
System.out.println(stack.pop());
System.out.println(stack.peek());
}
}
输出结果是一样的,这里我就不给结果了!!!
二:队列(Queue)
1.概念
队列:只允许在⼀端进⾏插⼊数据操作,在另⼀端进⾏删除数据操作的特殊线性表,队列具有先进先出FIFO(First In First Out)⼊队列:进⾏插⼊操作的⼀端称为队尾(Tail/Rear)出队列:进⾏删除操作 的⼀端称为队头(Head/Front)

2.队列的使⽤
在Java中,Queue是个接⼝,底层是通过链表实现的。


注意:Queue是个接⼝,在实例化时必须实例化LinkedList的对象,因为LinkedList实现了Queue接 ⼝。
这里我们通过标准库来实现队列,看看效果
代码如下:
java
import java.util.LinkedList;
import java.util.Queue;
//利用标准库Queue完成队列测试
public class QueueDemo {
public static void main(String[] args) {
Queue<Integer> queue = new LinkedList<>();
//入队
queue.offer(1);
queue.offer(2);
queue.offer(3);
queue.offer(4);
System.out.println(queue);
//出队
System.out.println(queue.poll());
System.out.println(queue.poll());
System.out.println(queue.poll());
System.out.println(queue.poll());
//取队首元素
System.out.println(queue.peek());
//判断是否为空
if (queue.isEmpty()){
System.out.println("链表为空");
}else
System.out.println("链表不为空");
}
}
输出结果:

3.队列模拟实现
队列中既然可以存储元素,那底层肯定要有能够保存元素的空间,通过前⾯线性表的学习了解到常⻅ 的空间类型有两种:顺序结构和链式结构。

这里我们基于单链表来手搓一个队列
代码如下:
java
//基于单链表,手搓一个队列
class LinkedNode{
public int val;
public LinkedNode next;
public LinkedNode(int val) {
this.val = val;
this.next=null;
}
}
//表示整个队列
public class MyQueue {
public LinkedNode head = null;
public LinkedNode tail =null;
//入队列,即尾插
public void offer(int val){
LinkedNode newNode = new LinkedNode(val);
//链表为空的情况
if (head==null){
head=newNode;
tail=newNode;
return;
}
//链表非空情况
tail.next=newNode;
tail=tail.next;
}
//出队列,即头删
public Integer poll(){
if (head==null){
return null;
}
int ret = head.val;
head=head.next;
return ret;
}
//取队首元素
public Integer peek(){
if (head==null){
return null;
}
return head.val;
}
public static void main(String[] args) {
MyQueue queue =new MyQueue();
queue.offer(1);
queue.offer(2);
queue.offer(3);
queue.offer(4);
// System.out.println(queue.poll());
// System.out.println(queue.poll());
// System.out.println(queue.poll());
// System.out.println(queue.poll());
System.out.println(queue.peek());
}
}
三:双端队列(Deque)
双端队列(deque)是指允许两端都可以进⾏⼊队和出队操作的队列,deque是"doubleended queue"的简称。那就说明元素可以从队头出队和⼊队,也可以从队尾出队和⼊队。
Deque是⼀个接⼝,使⽤时必须创建LinkedList的对象。

在实际⼯程中,使⽤Deque接⼝是⽐较多的,栈和队列均可以使⽤该接⼝
1.双端队列的使用
这里我们同样利用标准库里面的类,来看看双端队列的效果,基于顺序表
java
import java.util.ArrayDeque;
import java.util.Deque;
public class DequeDemo {
public static void main(String[] args) {
// 创建一个双端队列
Deque<String> deque = new ArrayDeque<>();
System.out.println("--- 双端队列 (Deque) 操作演示 ---");
System.out.println("初始状态: " + deque);
// 1. 从队尾添加元素 (等同于 offerLast())
deque.offer("Orange");
System.out.println("使用 offer() 从队尾添加 'Orange' 后: " + deque);
// 2. 从队头添加元素
deque.offerFirst("Apple");
System.out.println("使用 offerFirst() 从队头添加 'Apple' 后: " + deque);
// 3. 从队尾添加元素
deque.offerLast("Banana");
System.out.println("使用 offerLast() 从队尾添加 'Banana' 后: " + deque);
// 4. 查看队头元素 (不移除)
String frontElement = deque.peek();
System.out.println("使用 peek() 查看队头元素: " + frontElement);
// 5. 查看队尾元素 (不移除)
String lastElement = deque.peekLast();
System.out.println("使用 peekLast() 查看队尾元素: " + lastElement);
// 6. 从队头移除元素
String removedFirst = deque.poll();
System.out.println("使用 poll() 移除队头元素 '" + removedFirst + "' 后: " + deque);
// 7. 从队尾移除元素
String removedLast = deque.pollLast();
System.out.println("使用 pollLast() 移除队尾元素 '" + removedLast + "' 后: " + deque);
}
}
输出;

以上就是我们的全部内容了!!!