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

本文涉及的产品
云解析 DNS,旗舰版 1个月
全局流量管理 GTM,标准版 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)是限制只允许一端进行插入操作,另一端进行删除操作的线性表。

相关文章
|
18天前
|
C语言
【数据结构】栈和队列(c语言实现)(附源码)
本文介绍了栈和队列两种数据结构。栈是一种只能在一端进行插入和删除操作的线性表,遵循“先进后出”原则;队列则在一端插入、另一端删除,遵循“先进先出”原则。文章详细讲解了栈和队列的结构定义、方法声明及实现,并提供了完整的代码示例。栈和队列在实际应用中非常广泛,如二叉树的层序遍历和快速排序的非递归实现等。
94 9
|
9天前
|
存储 算法
非递归实现后序遍历时,如何避免栈溢出?
后序遍历的递归实现和非递归实现各有优缺点,在实际应用中需要根据具体的问题需求、二叉树的特点以及性能和空间的限制等因素来选择合适的实现方式。
19 1
|
12天前
|
存储 算法 Java
数据结构的栈
栈作为一种简单而高效的数据结构,在计算机科学和软件开发中有着广泛的应用。通过合理地使用栈,可以有效地解决许多与数据存储和操作相关的问题。
|
7天前
|
存储 网络协议 安全
30 道初级网络工程师面试题,涵盖 OSI 模型、TCP/IP 协议栈、IP 地址、子网掩码、VLAN、STP、DHCP、DNS、防火墙、NAT、VPN 等基础知识和技术,帮助小白们充分准备面试,顺利踏入职场
本文精选了 30 道初级网络工程师面试题,涵盖 OSI 模型、TCP/IP 协议栈、IP 地址、子网掩码、VLAN、STP、DHCP、DNS、防火墙、NAT、VPN 等基础知识和技术,帮助小白们充分准备面试,顺利踏入职场。
22 2
|
15天前
|
存储 JavaScript 前端开发
执行上下文和执行栈
执行上下文是JavaScript运行代码时的环境,每个执行上下文都有自己的变量对象、作用域链和this值。执行栈用于管理函数调用,每当调用一个函数,就会在栈中添加一个新的执行上下文。
|
17天前
|
存储
系统调用处理程序在内核栈中保存了哪些上下文信息?
【10月更文挑战第29天】系统调用处理程序在内核栈中保存的这些上下文信息对于保证系统调用的正确执行和用户程序的正常恢复至关重要。通过准确地保存和恢复这些信息,操作系统能够实现用户模式和内核模式之间的无缝切换,为用户程序提供稳定、可靠的系统服务。
44 4
|
22天前
|
存储 消息中间件 NoSQL
Redis数据结构:List类型全面解析
Redis数据结构——List类型全面解析:存储多个有序的字符串,列表中每个字符串成为元素 Eelement,最多可以存储 2^32-1 个元素。可对列表两端插入(push)和弹出(pop)、获取指定范围的元素列表等,常见命令。 底层数据结构:3.2版本之前,底层采用**压缩链表ZipList**和**双向链表LinkedList**;3.2版本之后,底层数据结构为**快速链表QuickList** 列表是一种比较灵活的数据结构,可以充当栈、队列、阻塞队列,在实际开发中有很多应用场景。
|
21天前
|
算法 安全 NoSQL
2024重生之回溯数据结构与算法系列学习之栈和队列精题汇总(10)【无论是王道考研人还是IKUN都能包会的;不然别给我家鸽鸽丢脸好嘛?】
数据结构王道第3章之IKUN和I原达人之数据结构与算法系列学习栈与队列精题详解、数据结构、C++、排序算法、java、动态规划你个小黑子;这都学不会;能不能不要给我家鸽鸽丢脸啊~除了会黑我家鸽鸽还会干嘛?!!!
|
22天前
|
存储 NoSQL 关系型数据库
Redis的ZSet底层数据结构,ZSet类型全面解析
Redis的ZSet底层数据结构,ZSet类型全面解析;应用场景、底层结构、常用命令;压缩列表ZipList、跳表SkipList;B+树与跳表对比,MySQL为什么使用B+树;ZSet为什么用跳表,而不是B+树、红黑树、二叉树
|
7天前
|
监控 Java 应用服务中间件
高级java面试---spring.factories文件的解析源码API机制
【11月更文挑战第20天】Spring Boot是一个用于快速构建基于Spring框架的应用程序的开源框架。它通过自动配置、起步依赖和内嵌服务器等特性,极大地简化了Spring应用的开发和部署过程。本文将深入探讨Spring Boot的背景历史、业务场景、功能点以及底层原理,并通过Java代码手写模拟Spring Boot的启动过程,特别是spring.factories文件的解析源码API机制。
23 2

推荐镜像

更多