【算法】---栈与队列基础

devtools/2024/10/21 21:14:35/

前置准备

数据结构篇:学习过栈与队列这两种基本数据结构
前面会迅速回顾栈与队列的使用

本篇以Java为主, 其它语言可自行对应内置的栈与队列容器。

栈是一种后进先出的容器。
如下图, 栈只有一个开口。

  • 栈顶:栈的开口处,所有的插入(push)和删除(pop)操作都只能在栈顶进行。
  • 栈底:栈的最底部,没有办法直接访问栈底的数据,必须通过逐步“弹出”栈顶元素才能到达栈底。
  • 后进先出(LIFO):最后放入栈中的元素会最先被取出,像叠盘子一样,最新放上去的盘子最先被拿走。
    增删查询操作只允许在栈顶进行。
    由于必定操作最近进入栈的数, 因此栈的特性是后进先出。
    在这里插入图片描述
  • Java中的Stack:Java—Stack
  • 全局静态数组实现:解算法题常用, 因为其常数时间快且可以空间复用算法题效率由于语言自带的栈, 比如纯C选手就可以用这个迅速手搓一个栈不需要封装直接用。
class Stack {public  int[] stack;public int r;public Stack(int n) {stack = new int[n];r = 0;}public void push(int val) {stack[r++] = val;}public int pop() {return stack[--r];}public int peek() {return stack[r-1];}public boolean isEmpty() {return r==0;}public int size() {return r;}
}
  • Java中的LinkedList(双向链表)和ArrayDeque(双端队列):两者也支持栈操作, 具体查看手册。

队列

队列是一种先进先出的容器
在这里插入图片描述

Java中的Queue接口位于java.util包中,它有两个常见实现类可以充当队列。
LinkedList,ArrayDeque.

  • offer(E e):将指定元素插入队列尾部,如果插入成功返回true
  • poll():移除并返回队首元素,如果队列为空则返回null
  • peek():获取队首元素但不移除,如果队列为空返回null
  • isEmpty():判断队列是否为空。
  • size():获取队列的长度
1. LinkedList使用

LinkedList类可以用来实现队列。支持队列操作。

import java.util.LinkedList;
import java.util.Queue;public class QueueExample {public static void main(String[] args) {// 使用LinkedList实现队列Queue<Integer> queue = new LinkedList<>();// 队列是否为空·System.out.println(queue.isEmpty());// 入队操作queue.offer(1);queue.offer(2);queue.offer(3);// 查看队首元素(不移除)System.out.println("队首元素: " + queue.peek());// 出队操作System.out.println("移除的元素: " + queue.poll());// 队列长度·System.out.println(queue.size());// 查看出队后的队列System.out.println("队首元素: " + queue.peek());}
}
2. ArrayDeque

ArrayDeque 是一个基于数组的双端队列,它可以高效地作为队列或栈使用。

import java.util.ArrayDeque;
import java.util.Queue;public class ArrayDequeExample {public static void main(String[] args) {// 使用ArrayDeque实现队列Queue<String> arrayDeque = new ArrayDeque<>();// 队列是否为空·System.out.println(arrayDueue.isEmpty());// 入队操作arrayDeque.offer("A");arrayDeque.offer("B");arrayDeque.offer("C");// 查看队首元素System.out.println("队首元素: " + arrayDeque.peek());// 出队操作System.out.println("移除的元素: " + arrayDeque.poll());// 队列长度System.out.println(arrayDueue.size());// 查看出队后的队列System.out.println("队首元素: " + arrayDeque.peek());}
}
3. 常数时间快的数组实现

如果题目确定最大数据量是5000, 那么意味着这个队列最多进入5000个元素。

public class MyQueue {public static int MAX = 5000;public int[] queue = new int[MAX];public int l,r,size;public MyQueue() {l = r = size = 0;}//[l,r)是有效数据, l==r意味队列为空public void offer(int val) {queue[r++] = val;size++;}public int poll() {size--;return queue[l++];}public int peek() {return queue[l];}public int size() {return size;}public boolean isEmpty() {return l==r;//或者size==0}public static void main(String[] args) {MyQueue queue = new MyQueue();System.out.println(queue.isEmpty());queue.offer(1);queue.offer(2);queue.offer(3);System.out.println("queue.size():"+queue.size());System.out.println(queue.poll());System.out.println("queue.size():"+queue.size());System.out.println(queue.poll());}
}

MAX取决于算法题的测试数据量。
这里没有引入多余的检查可自行补充。
事实上,这个类都不用封装,只需要MAX,queue数组l,r这3个字段就可以直接充当队列解题, 而且常数时间也优于Java自带的Queue的两个实现类。
C语言选手采用这种写法,时间性能最佳。

环形队列实现

  • 设计循环队列
    测试链接
//本题接口
/
class MyCircularDeque {public MyCircularDeque(int k) {}public boolean insertFront(int value) {}public boolean insertLast(int value) {}public boolean deleteFront() {}public boolean deleteLast() {}public int getFront() {}public int getRear() {}public boolean isEmpty() {}public boolean isFull() {}
}
  • 解决方案
  • 阅读题目。
    1. 引入size,limit字段,方便维护。
    1. 先实现isEmpty(),isFull()方法。
    1. 设计[l,r)区间,l指向当前有效数据,r当前第一个无效数据。,插入,先左移动后插入,r先插入再往后移动。注意数组边界处理, 使得整个数组循环起来。
    1. 删除同3,但只需要挪动l或者r, 注意边界。
    1. getFront(),getRear()方法中,如果队列为空要返回-1,否则返回队列中对应的值。再次强调l指向当前有效数据,r当前第一个无效数据.
public int[] queue;private int l,r,limit,size;//limit:队列的最大容量//size:队列的长度//[l,r) 队列区间。public MyCircularDeque(int k) {queue = new int[k];l = r = size = 0;limit = k;}public boolean insertFront(int value) {if(isFull()) {return false;}queue[l = l==0?limit-1:l-1] = value;size++;return true;}public boolean insertLast(int value) {if(isFull()) {return false;}queue[r] = value;r = r==limit-1?0:r+1;size++;return true;}public boolean deleteFront() {if(isEmpty()) {return false;}l = l==limit-1?0:l+1;size--;return true;}public boolean deleteLast() {if(isEmpty()) {return false;}r = r==0?limit-1:r-1;size--;return true;}public int getFront() {return isEmpty()?-1:queue[l];}public int getRear() {return isEmpty()?-1:queue[r==0?limit-1:r-1];}public boolean isEmpty() {return size == 0;}public boolean isFull() {return size == limit;}

结束


http://www.ppmy.cn/devtools/127650.html

相关文章

每日C#语法题

1&#xff0c;自定义一个strlen函数&#xff0c;既可以用递归&#xff0c;也可以用迭代 #include<stdio.h> //int Strlen(char *a) //{ // int count0; // while(*a) // { // a; // count; // } // return count; //}int Strlen(char *a) {if(*a\0)return 0;elseretur…

C/C++下读取ENVI栅格文件格式

ENVI使用的是通用栅格数据格式&#xff0c;包含一个简单的二进制文件&#xff08; a simple flat binary &#xff09;和一个相关的ASCII&#xff08;文本&#xff09;的头文件。 利用其他语言如C/C等直接读取ENVI的数据&#xff0c;则可以先对hdr文件进行解析&#xff0c;获取…

抢单超卖? 并发问题解决思路

1. 问题介绍 在用户抢单或者商品售卖的过程中&#xff0c;正常情况下是一人一件&#xff0c;但是当网络流量剧增时多个用户同时抢到一个商品应该如何分配&#xff1f;假设这样一个场景A商品库存是100个&#xff0c;但是秒杀的过程中&#xff0c;一共卖出去500个A商品。对于卖家…

【前端】制作一个自己的网页(4)

刚才我们完成了网页中标题与段落元素的学习。在实际开发时&#xff0c;一个网页通常会包含多个相同元素&#xff0c;比如多个标题与段落。 对于相同标签的元素&#xff0c;我们又该如何区分定位呢&#xff1f; 对多个相同的标签分类 比如右图设置了七个段落元素&#xff0c;它…

【机器学习】任务七:聚类算法 (K-means 算法、层次聚类、密度聚类对鸢尾花(Iris)数据进行聚类)

目录 1.基础知识 1.1 K-Means 算法 1.2 层次聚类&#xff08;Hierarchical Clustering&#xff09; 1.3 密度聚类&#xff08;DBSCAN&#xff09; 1.4 距离和相似度度量方法 1.5 总结&#xff1a; 2.K-means 算法对鸢尾花&#xff08;Iris&#xff09;数据进行聚类 2.1…

预训练模型通过 prompt(提示)生成的“软标签”是什么

预训练模型通过 prompt&#xff08;提示&#xff09;生成的“软标签”是指模型在处理输入数据时输出的概率分布&#xff0c;而不是明确的、唯一的硬标签。 什么是“软标签”&#xff1f; 软标签&#xff08;Soft Label&#xff09;通常指的是模型预测结果中输出的概率分布。例…

红黑树实现(附C++源码)

游凡/红黑树https://gitee.com/you-fan-a/red-black-tree 一、什么是红黑树 遵循 一定规则&#xff0c;每个节点都有颜色且都是红色或黑色的搜索二叉树就是红黑树。 红黑树的平衡性和查找效率不如AVL树&#xff0c;但是插入和删除比AVL树要强。 二、红黑树的规则 1、红黑树…

[JAVAEE] 线程安全的案例(一)-单例模式

目录 一. 单例模式 二. 单例模式的使用时机 三. 单例模式的关键代码 四. 单例模式的几种实现方式 4.1 饿汉方式(急) 4.2 懒汉模式(缓) a. 解决原子性的问题 b. 解决程序运行效率低下的问题 c. 解决指令重排序的问题(其次是为了解决内存可见性的问题) 五. 总结 一. …