栈,队列和链表三者之间的关系与区别
最近一直在学习算法,刷算法题,但是自从大学毕业以来,数据结构的知识都还给老师了,只会个数组,所以前期刷的题目也都是有关数组的
最近跟着小册重学了一遍数据结构,今天就记录一下栈,队列和链表三者之间的关系与区别,以及如何进行增删
栈和队列的实现一般都要依赖于数组,大家完全可以把栈和队列都看作是“特别的数组”。
两者的区别在于,它们各自对数组的增删操作有着不一样的限制。
要想学会栈和队列就必须要了解数组的几种增删方法
数组中增加元素的三种方法
unshift
添加元素到数组的头部*push
添加元素到数组的尾部*splice
添加元素到数组的任何位置数组中删除元素的三种方法shift
删除数组头部的元素*pop
删除数组尾部的元素*splice
删除数组任意位置的元素栈(Stack)
========
栈是 只用pop
和 push
完成增删的“数组”
栈是一种后进先出(LIFO,Last In First Out)的数据结构。
就拿小卖部老板放冰糕和卖冰糕举例:
他有两个特征:
- 只允许从尾部添加元素* 只允许从尾部取出元素对应到数组的方法,刚好就是 push 和 pop。因此,我们可以认为在 JavaScript 中,栈就是限制只能用 push 来添加元素,同时只能用 pop 来移除元素的一种特殊的数组。
栈顶元素:所谓栈顶元素,从图上我们不难看出来,实际上它指的就是数组尾部的元素。
// 初始状态,栈空
const stack = []// 入栈过程
stack.push('东北大板')
stack.push('可爱多')
stack.push('巧乐兹')// 栈顶元素 就是最后一个元素
stack[stack.length-1]// 出栈过程,栈不为空时才执行
while(stack.length) {// 单纯访问栈顶元素(不出栈)const top = stack[stack.length-1]console.log('现在取出的冰淇淋是', top)// 将栈顶元素出栈stack.pop()
}// 栈空
stack // []
队列(Queue)
队列是(Queue)只用 push 和 shift 完成增删的“数组”
队列是一种先进先出(FIFO,First In First Out)的数据结构。
就像派对做核酸
队列的特征就是:
- 只允许从尾部添加元素
- 只允许从头部移除元素
整个过程只涉及了数组的 push
和 shift
方法。
在栈元素出栈时,我们关心的是栈顶元素(数组的最后一个元素);队列元素出队时,我们关心的则是队头元素(数组的第一个元素)。
链表
链表和数组相似,它们都是有序的列表、都是线性结构(有且仅有一个前驱、有且仅有一个后继)。不同点在于,链表中,数据单位的名称叫做“结点”,而结点和结点的分布,在内存中可以是离散的。
数组的元素分布示意图:
而链表中的结点,则允许散落在内存空间的各个角落里。一个内容为1->2->3->4->5的链表,在内存中的形态可以是散乱如下的:
正是由于数组中的元素是连续的,每个元素的内存地址可以根据其索引距离数组头部的距离来计算出来。因此对数组来说,每一个元素都可以通过数组的索引下标直接定位。对链表来说,元素和元素之间似乎毫无内存上的瓜葛可言
在链表中,每一个结点的结构都包括了两部分的内容:数据域和指针域。JS 中的链表,是以嵌套的对象的形式来实现的:
{ // 数据域 val: 1, // 指针域,指向下一个结点 next: { val:2, next: ... }
}
数据域存储的是当前结点所存储的数据值,而指针域则代表下一个结点(后继结点)的引用。 有了 next 指针来记录后继结点的引用,每一个结点至少都能知道自己后面的节点在哪,原本相互独立的结点之间就有了如下的联系:
创建链表节点
function ListNode(val) { this.val = val; this.next = null;
}
// 创造一个节点,并且节点的值为1
const node = new ListNode(1)
在使用构造函数创建结点时,传入 val (数据域对应的值内容)、指定 next (下一个链表结点)即可:
const node1 = new ListNode(1)
node1.next = new ListNode(2)
经过上一步操作就创建出了一个数据域值为1,next 结点数据域值为2的链表结点:
链表的结点间关系是通过 next 指针来维系的。因此,链表元素的添加和删除操作,本质上都是在围绕 next 指针做文章。
添加节点
直接在尾部添加结点相对比较简单,我们改变一个 next 指针就行。
这里记值为2的 node 结点为 node2(假设 node2 是现在的尾部结点),值为3的 node 结点为 node3。
假如我要把 node3 添加到 node2 所在链表的尾部,直接把 node2 的 next 指针指向 node3 即可:
插入节点
如何在两个结点间插入一个结点?
由于链表有时会有头结点,这时即便你是往链表头部增加结点,其本质也是“在头结点和第一个结点之间插入一个新结点”。
大学时的计算机网络基础课,任意两结点间插入一个新结点这种类型的增加操作算是一道必考题了
我们需要变更的是前驱结点和目标结点的 next 指针指向,过程如下图:
代码这样写
// 如果目标结点本来不存在,那么记得手动创建
const node3 = new ListNode(3) // 把node3的 next 指针指向 node2
node3.next = node1.next// 把node1的 next 指针指向 node3
node1.next = node3
删除节点
如何把刚才添加的node3节点删除?
可以直接让它的前驱结点 node1 的 next 指针跳过它、指向 node3 的后继即可:
这个过程用代码表述如下:
node1.next = node3.next
涉及链表删除操作的题目中,重点不是定位目标结点,而是定位目标结点的前驱结点。
最后
为大家准备了一个前端资料包。包含54本,2.57G的前端相关电子书,《前端面试宝典(附答案和解析)》,难点、重点知识视频教程(全套)。
有需要的小伙伴,可以点击下方卡片领取,无偿分享
栈,队列和链表三者之间的关系与区别相关推荐
- java map与set的区别_java 集合(list,set,map)三者之间的关系和区别
原 java 集合(list,set,map)三者之间的关系和区别 一:先上一张关系图,让大家看的更明白. 备注:其中红色部分为实现,其他地方均为接口. 二:各自的特点. List 有序,可重复Arr ...
- JavaSE、JavaEE、JavaME三者之间的关系与区别
Java 平台有三个版本,这使软件开发人员.服务提供商和设备生产商可以针对特定的市场进行开发: Java SE (Java Platform,Standard Edition).Java SE 以前称 ...
- 睡眠、休眠、混合睡眠三者之间的关系与区别
1.先说一下"最古老"的待机:电脑待机待机(Standby):将系统切换到该模式后,除了内存,电脑其他设备的供电都将中断,只有内存依靠电力维持着其中的数据(因为内存是易失性的,只要 ...
- PHP-FPM,Nginx,FastCGI 三者之间的关系
2019独角兽企业重金招聘Python工程师标准>>> 本文介绍 PHP-FPM,Nginx,FastCGI 三者之间的关系,以及 Nginx 反向代理和负载均衡的配置. PHP-F ...
- python和pycharm之间的关系_浅析python,PyCharm,Anaconda三者之间的关系
一.它们是什么? 1.python Python是一种跨平台的计算机程序设计语言,简单来说,python就是类似于C,Java,C++等,一种编程语言. 2.Anaconda Anaconda指的是一 ...
- anaconda中的python如何进行关联分析_浅析python,PyCharm,Anaconda三者之间的关系
一.它们是什么? Python是一种跨平台的计算机程序设计语言,简单来说,python就是类似于C,Java,C++等,一种编程语言. 2.Anaconda Anaconda指的是一个开源的Pytho ...
- 浅谈javascript中原型(prototype)、构造函数、对象实例及三者之间的关系
转自:http://www.cnblogs.com/zhangwei412827/archive/2012/12/14/2816263.html 浅谈javascript中原型(prototype). ...
- 构造函数,对象原型,实例对象三者之间的关系
撸了今年阿里.头条和美团的面试,我有一个重要发现.......>>> 1.构造函数,原型对象,实例对象三者之间的关系 每创建一个函数,该函数都会自动带有一个prototype属性.该 ...
- 一次性掌握JDK、JRE、JVM的概念以及三者之间的关系【2021整理】
一.JDK.JRE.JVM概念解析 JDK(Java Development Kit):Java开发工具包,开发人员用来构建Java应用程序的软件包. JRE(Java Runtime Environ ...
最新文章
- android中xml tools属性详解
- Shell脚本攻略02-玩转变量与环境变量
- boost::spirit模块实现一个复数微生成器的测试程序
- HDU - 6635 Nonsense Time (暴力LIS)
- android界面设计字体大小,Andoird用户界面设计上手指南:设置字体大小
- 关于面试题的一些想法
- suse linux vnc 桌面号,在SUSE Linux下安装VNC的方法
- 帆软条件判断是否包含指定字符串
- 智能优化算法:水循环算法-附代码
- tomcat日志打印乱码
- epoch,batch_size,iteration,batch_idx什么意思
- ACM动态规划总结(by utobe67)
- 计算机专用英语(常用1695个单词,带音标)
- 软件定义和硬件重构知多少(三)
- iOS shareExtension总结分享
- 计算机图形学2-Liang-Barsky直线裁剪算法
- Spring Boot 2.3.0配置Graceful-Shutdown,Readiness和Liveness
- XSS笔记-来源于个人思路构造以及网络分享
- 怕扫描王泄露数据?5分钟自建一个文档扫描器。——基于opencv
- Delphi 2005 发布!