当前位置:网站首页>线性表 -- 栈和队列
线性表 -- 栈和队列
2022-07-27 05:39:00 【mmmenxj】
线性表:数组,链表,字符串,栈,队列
元素按照一条直线排列,线性表这个结构中,一次添加单个元素
非线性结构:树,图
栈stack:后进先出的线性表,支持三个核心操作:入栈PUSH、出栈pop、返回栈顶元素peek
栈和队列是一个使用上更加严格的线性表。
动态数组、链表可以在任意位置进行插入和删除
水杯就是一个天然的栈结构,后进先出LIFO (last in first out)
栈的实际应用
Ps:1.无处不在的撤销操作undo,撤销本质就是一个栈的pop
2.浏览器的前进后退,A-B-C,此时留在c页面,看完C想反悔B,点击后退箭头相当于将C出栈,此时栈顶就是B
3.开发中程序的“调用栈”操作系统栈底层就是我们的栈实现,碰到return就是方法的出栈
栈也是一个线性表,底层既可以使用数组,也可以使用链表
基于数组实现的栈--顺序栈--数组尾部的添加和删除,时间复杂度是O(1)--栈顶就是数组末尾
基于链表实现的栈--链式栈--尾插和尾删
public class MyStack <E>{
private int size;//当前栈的数据个数
private List<E> data = new ArrayList<>(); //实际存储数据的动态数组
//将value入栈
public void push(E val){
//默认尾插
data.add(val);
size++;
}
//弹出栈顶元素,返回栈顶的值,出栈,方法是E类型
public E pop(){
if(isEmpty()){
//栈为空
throw new NoSuchElementException("satck is empty!cannot pop!");
}else{
//删除栈顶元素
// 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(){
// if(size == 0) return true;
// return false;
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("] top");
return sb.toString();
}
//系统自带
// @Override
// public String toString() {
// return "MyStack{" +
// "size=" + size +
// ", data=" + data +
// '}';
// }
}
队列FIFO(first in first out)
队首出队,在队尾入队,先进先出的数据结构
生活中:银行食堂的排队
基于数组实现的队列 -- 顺序队列
基于链表实现的队列 -- 链式队列(由于队列是从队尾入队,队首出队,数组头部删除,因此用链表更好一些)
队列的子类比栈来说要复杂一些:
1.基础队列FIFO
2.基于优先级的队列 按照优先级大小出队
3.循环队列 基于数组实现的
4.双端队列
无论哪种队列,都需要支持三个核心操作:入队offer、出队poll、返回队首元素peek
因此我们设计队列为接口。
力扣20
public class MyQueue<E> implements Queue<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!");
}
E val = head.val;
Node node = head;
head = head.next;
//将原来头结点脱钩
node.next = null;
size --;
return 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("front[");
//链表的遍历
for (Node x = head;x != null; x = x.next) {
sb.append(x.val);
if(x.next != null){
//链表还没走到尾部
sb.append(", ");
}
}
sb.append("]");
return sb.toString();
}
}
循环队列:队列是一个环,逻辑上成环,物理上是线性表
head 指向当前队列的第一个元素下标
tail指向当前队列的最后一个元素的下一个位置
当tail走到数组末尾时,下一步再次返回数组头部
优点:1.比普通队列更省空间
2.出队时,直接将head引用向后移动即可,不需要再搬移元素。head = head+1
环形队列判空:head == tail
浪费一个空间,来区分数组是否已满。判满:tail = (tail+1)%data.length == head
head和tail不能简单地加一,要加一后对数组长度取模
tail = (tail+1)%data.length,让tail从末尾返回数组头部
head = (head+1) %data.length
如何获取到当前循环队列的最后一个元素的索引呢?
lastIndex = tail == 0? data.length - 1 :tail - 1
边栏推荐
- AI:业余时间打比赛—挣它个小小目标—【阿里安全×ICDM 2022】大规模电商图上的风险商品检测比赛
- Analysis on the current situation and optimization strategy of customer experience management in banking industry
- Auto encoder (AE), denoising auto encoder (DAE), variable auto encoder (VAE) differences
- C语言怎么学?这篇文章给你完整答案
- Analysis of pix2pix principle
- PNA peptide nucleic acid modified peptide suc Tyr Leu Val PNA | suc ala Pro Phe PNA 11
- 运行代码报错: libboost_filesystem.so.1.58.0: cannot open shared object file: No such file or directory
- The issuing process of individual developers applying for code signing certificates
- Add virtual network card and configure OP route in win10
- Dimension problems and contour lines
猜你喜欢

聊聊大火的多模态

Add virtual network card and configure OP route in win10

EasyCVR平台播放设备录像时,拖动时间轴播放无效是什么原因?

nvidia-smi 各参数意义

Introduction to the official functions of easyrecovery14 data recovery software

DNA科研实验应用|环糊精修饰核酸CD-RNA/DNA|环糊精核酸探针/量子点核酸探针

基于SSM实现的校园新闻发布管理系统

强网杯2021 pwn 赛题解析——babypwn

DNA偶联PbSe量子点|近红外硒化铅PbSe量子点修饰脱氧核糖核酸DNA|PbSe-DNA QDs

Why can cross entropy loss be used to characterize loss
随机推荐
R2live code learning record (3): radar feature extraction
Interpretation of deepsort source code (III)
NAT (network address translation)
regular expression
Add virtual network card and configure OP route in win10
C语言怎么学?这篇文章给你完整答案
Reasoning speed of model
【12】 Understand the circuit: from telegraph to gate circuit, how can we "send messages from thousands of miles"?
DNA coupled PbSe quantum dots | near infrared lead selenide PbSe quantum dots modified DNA | PbSe DNA QDs
Variance and covariance
Analysis of online and offline integration mode of o2o E-commerce
Web configuration software for industrial control is more efficient than configuration software
Auto encoder (AE), denoising auto encoder (DAE), variable auto encoder (VAE) differences
Introduction to the official functions of easyrecovery14 data recovery software
Interpretation of deepsort source code (6)
Vscode connection remote server development
Cass11.0.0.4 for autocad2010-2023 dog free usage
[latex format] there are subtitles side by side on the left and right of double columns and double pictures, and subtitles are side by side up and down
AI: play games in your spare time - earn it a small goal - [Alibaba security × ICDM 2022] large scale e-commerce map of risk commodity inspection competition
Brief introduction of simulation model