【数据结构趣味多】栈和队列(详细解析)

本文涉及的产品
全局流量管理 GTM,标准版 1个月
云解析 DNS,旗舰版 1个月
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
简介: 【数据结构趣味多】栈和队列(详细解析)

1.1 栈的定义

栈:一种特殊的线性表,其只允许在表尾进行插入和删除操作。

栈顶和栈底:允许插入和删除的一端称为栈顶(top),另一端称为栈底(bottom),栈中的数据元素遵守后进先出LIFO(Last In First Out)的原则。

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

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



栈分为顺序栈和链栈,我们先研究顺序栈,链栈等以后再说。

下方是栈继承的类,以及栈实现的接口。



1.2 栈的模拟实现(顺序栈)

栈一共包含6个方法,我们模拟实现中所有数据类型都用int类型代替


1688715517374.png


push()方法

作用:此方法是让元素入栈。

实现原理:首先判断线性表是否已满,如果线性表已满,就需要扩容。之后就是将数据放入线性表,并将栈大小加一。

public void push(int val) {
        if(stack.length==stackSize) {
            stack=Arrays.copyOf(stack,2*stackSize);
        }
        stack[stackSize++]=val;
    }


pop()方法

作用: 此方法是让栈顶元素出栈。

实现原理:出栈的前提一直到栈中有元素;因此,我们先判断栈是否胃口,若为空栈,就抛出异常,让程序停下来,若不为空栈,就弹出栈底元素,并将栈大小减一。

public int pop() {
        if(empty()) {
            throw new RuntimeException("空栈!");
        }
        return  stack[--stackSize];
    }


peek()方法

作用: 如他的名字一样,peek 偷看,看一眼栈顶的元素,但不出栈。

实现原理:判断栈是否为空,若是空栈不能偷看到元素,抛异常停止运行;若不为空栈返回栈底元素即可。

public int peek() {
        if(empty()) {
            throw new RuntimeException("空栈!");
        }
        return  stack[stackSize-1];
    }


size()方法

作用: 得到栈中有多少个元素

实现原理:直接返回成员变量stackSize

栈模拟实现的全代码:

import java.util.Arrays;
public class MyStack {
    private int[]  stack;
    private int stackSize;
    public MyStack() {
        this.stack=new int[3];
    }
    public void push(int val) {
        if(stack.length==stackSize) {
            stack=Arrays.copyOf(stack,2*stackSize);
        }
        stack[stackSize++]=val;
    }
    public int pop() {
        if(empty()) {
            throw new RuntimeException("空栈!");
        }
        return  stack[--stackSize];
    }
    public int peek() {
        if(empty()) {
            throw new RuntimeException("空栈!");
        }
        return  stack[stackSize-1];
    }
    public int size() {
        return stackSize;
    }
    public  boolean empty() {
        if(stackSize==0) {
            return true;
        }
        return  false;
    }
}

1.3顺序栈和链栈的对比

 栈有链栈和顺序栈之分,上方是用顺序表实现的名叫顺序栈;我们还可以使用链表实现,对于用链表实现栈,会很好实现,因为我们不需要考虑栈满的情况,若链栈满了,那可以说是你的计算机操作系统就面临崩溃。


时间复杂度:链栈和顺序栈,它们在时间复杂度上都是O(1)。

空间复杂度:顺序栈需要事先确定一个长度,可能会造成内存空间的浪费,但是优势是存取时定位方便;链栈每个元素都要有一个指针域,增加了内存的开销,但长度无限。

两者如何选择:如果栈的使用过程中元素变化不可预知,最好用链栈;若变化在可控范围内,使用顺序栈更好。


2.队列

2.1队列的定义

队列: 只允许在一端进行插入操作,而在另一端进行删除操作的线性表,允许插入的一端称为队尾,允许删除的一端称为对头。一种先进先出的线性表。



队列实现的接口:

       在Java中,Queue是个接口,底层是通过链表实现的



2.1队列的模拟实现(单链表)

队列一共有5种方法


1688715640241.png


offer()函数

作用:将新元素入队,位置是单链表尾部。

实现原理:将给给定的数值new一个新节点,如果头节点为空,就让头结点和尾节点都等于noed,如果不为空,就使用尾插法将node插到链表尾部。

//入队
    public void offer(int val) {
        Node node=new Node(val);
        if(head==null) {
            head=node;
            last=node;
        }else {
            last.next=node;
            last=last.next;
        }
        usedSize++;
    }


poll()函数

作用:将队头元素出队,位置单链表头指针所指元素。

实现原理:首先判断链表是否为空,若空,抛出异常;若不空,出头指针指的元素,并将使用大小减一。

 //出队
    public int poll() {
        if(isEmpty()) {
            throw new RuntimeException("队列空");
        }
        int tmp=head.val;
        head=head.next;
        usedSize--;
        return val;
    }


peek()函数

作用:偷看一下队头元素,不出队

实现原理:将首先判断队列是否空,若空,抛出异常;若不为空,返回头节点所指数值。

public int peek() {
        if(isEmpty()) {
            throw new RuntimeException("队列空");
        }
        int tmp=head.val;
        return val;
    }


size()函数

作用:返回有多少个元素

实现原理:直接返回成员变量usedSize

public int size() {
        return usedSize;
    }


isEmpty()函数

作用:将判断队列是否空。

实现原理:如果头节点是空,证明没有元素入队。

//判断空队列
    public boolean isEmpty() {
        if(usedSize==0) {
            return true;
        }
        return false;
    }

队列实现的全代码

public class MyQueue {
    private int val;
    private  int usedSize;
    static class Node {
        public int val;
        public Node next;
        public Node(int val) {
            this.val = val;
        }
    }
    private Node head;
    private Node last;
    //入队
    public void offer(int val) {
        Node node=new Node(val);
        if(head==null) {
            head=node;
            last=node;
        }else {
            last.next=node;
            last=last.next;
        }
        usedSize++;
    }
    //出队
    public int poll() {
        if(isEmpty()) {
            throw new RuntimeException("队列空");
        }
        int tmp=head.val;
        head=head.next;
        usedSize--;
        return val;
    }
    //看队头
    public int peek() {
        if(isEmpty()) {
            throw new RuntimeException("队列空");
        }
        int tmp=head.val;
        return val;
    }
    //判断空队列
    public boolean isEmpty() {
        if(usedSize==0) {
            return true;
        }
        return false;
    }
    public int getUsedSize() {
        return usedSize;
    }
}


总结

1.栈和队列,他们都是特殊的线性表,只不过在删除和插入操作上做了限制。

2.栈(stack)是限制仅在表尾进行插入和删除操作的线性表。

3.队列(queue)是限制只允许一端进行插入操作,另一端进行删除操作的线性表。

相关文章
|
9天前
|
存储 C语言 C++
【C++数据结构——栈与队列】顺序栈的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现顺序栈的基本运算。开始你的任务吧,祝你成功!​ 相关知识 初始化栈 销毁栈 判断栈是否为空 进栈 出栈 取栈顶元素 1.初始化栈 概念:初始化栈是为栈的使用做准备,包括分配内存空间(如果是动态分配)和设置栈的初始状态。栈有顺序栈和链式栈两种常见形式。对于顺序栈,通常需要定义一个数组来存储栈元素,并设置一个变量来记录栈顶位置;对于链式栈,需要定义节点结构,包含数据域和指针域,同时初始化栈顶指针。 示例(顺序栈): 以下是一个简单的顺序栈初始化示例,假设用C语言实现,栈中存储
125 75
|
9天前
|
存储 C++ 索引
【C++数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】
【数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】初始化队列、销毁队列、判断队列是否为空、进队列、出队列等。本关任务:编写一个程序实现环形队列的基本运算。(6)出队列序列:yzopq2*(5)依次进队列元素:opq2*(6)出队列序列:bcdef。(2)依次进队列元素:abc。(5)依次进队列元素:def。(2)依次进队列元素:xyz。开始你的任务吧,祝你成功!(4)出队一个元素a。(4)出队一个元素x。
34 13
【C++数据结构——栈与队列】环形队列的基本运算(头歌实践教学平台习题)【合集】
|
9天前
|
存储 C语言 C++
【C++数据结构——栈与队列】链栈的基本运算(头歌实践教学平台习题)【合集】
本关任务:编写一个程序实现链栈的基本运算。开始你的任务吧,祝你成功!​ 相关知识 初始化栈 销毁栈 判断栈是否为空 进栈 出栈 取栈顶元素 初始化栈 概念:初始化栈是为栈的使用做准备,包括分配内存空间(如果是动态分配)和设置栈的初始状态。栈有顺序栈和链式栈两种常见形式。对于顺序栈,通常需要定义一个数组来存储栈元素,并设置一个变量来记录栈顶位置;对于链式栈,需要定义节点结构,包含数据域和指针域,同时初始化栈顶指针。 示例(顺序栈): 以下是一个简单的顺序栈初始化示例,假设用C语言实现,栈中存储整数,最大
34 9
|
9天前
|
C++
【C++数据结构——栈和队列】括号配对(头歌实践教学平台习题)【合集】
【数据结构——栈和队列】括号配对(头歌实践教学平台习题)【合集】(1)遇到左括号:进栈Push()(2)遇到右括号:若栈顶元素为左括号,则出栈Pop();否则返回false。(3)当遍历表达式结束,且栈为空时,则返回true,否则返回false。本关任务:编写一个程序利用栈判断左、右圆括号是否配对。为了完成本关任务,你需要掌握:栈对括号的处理。(1)遇到左括号:进栈Push()开始你的任务吧,祝你成功!测试输入:(()))
27 7
|
12天前
|
存储 运维 负载均衡
Hologres 查询队列全面解析
Hologres V3.0引入查询队列功能,实现请求有序处理、负载均衡和资源管理,特别适用于高并发场景。该功能通过智能分类和调度,确保复杂查询不会垄断资源,保障系统稳定性和响应效率。在电商等实时业务中,查询队列优化了数据写入和查询处理,支持高效批量任务,并具备自动流控、隔离与熔断机制,确保核心业务不受干扰,提升整体性能。
44 9
|
2月前
|
存储 缓存 算法
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式,强调了合理选择数据结构的重要性,并通过案例分析展示了其在实际项目中的应用,旨在帮助读者提升编程能力。
86 5
|
2月前
|
网络协议
网络通信的基石:TCP/IP协议栈的层次结构解析
在现代网络通信中,TCP/IP协议栈是构建互联网的基础。它定义了数据如何在网络中传输,以及如何确保数据的完整性和可靠性。本文将深入探讨TCP/IP协议栈的层次结构,揭示每一层的功能和重要性。
90 5
|
2月前
|
算法
数据结构之购物车系统(链表和栈)
本文介绍了基于链表和栈的购物车系统的设计与实现。该系统通过命令行界面提供商品管理、购物车查看、结算等功能,支持用户便捷地管理购物清单。核心代码定义了商品、购物车商品节点和购物车的数据结构,并实现了添加、删除商品、查看购物车内容及结算等操作。算法分析显示,系统在处理小规模购物车时表现良好,但在大规模购物车操作下可能存在性能瓶颈。
60 0
|
2月前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
106 2
|
24天前
|
存储 设计模式 算法
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析
行为型模式用于描述程序在运行时复杂的流程控制,即描述多个类或对象之间怎样相互协作共同完成单个对象都无法单独完成的任务,它涉及算法与对象间职责的分配。行为型模式分为类行为模式和对象行为模式,前者采用继承机制来在类间分派行为,后者采用组合或聚合在对象间分配行为。由于组合关系或聚合关系比继承关系耦合度低,满足“合成复用原则”,所以对象行为模式比类行为模式具有更大的灵活性。 行为型模式分为: • 模板方法模式 • 策略模式 • 命令模式 • 职责链模式 • 状态模式 • 观察者模式 • 中介者模式 • 迭代器模式 • 访问者模式 • 备忘录模式 • 解释器模式
【23种设计模式·全精解析 | 行为型模式篇】11种行为型模式的结构概述、案例实现、优缺点、扩展对比、使用场景、源码解析

热门文章

最新文章

推荐镜像

更多