栈是计算机科学中的一种抽象数据类型,只容许在有序的线性数据集合的一端(称为堆栈顶端,英语:top)进行加入数据(英语:push)和移除数据(英语:pop)的运算。于是按照后进先出(LIFO, Last In First Out)的原理运做。(百科全书)
html
栈中有两个基本的操做数组
栈的基本提点就是浏览器
对于栈的画面的理解,能够想象成一个步枪弹夹添加子弹和射击的过程
弹夹只有一个出入口进行推入和弹出数据结构
<body style='width: 80%;height:80%; margin: 10% auto;'> <ul id="stackBox" style="width:100px;border:1px solid #1fb19e;"> </ul> <div style="width:400px; display:flex;"> <input id="funStackBox" value="执行函数"> <div style="margin-left:100px;"> <button onclick="pushStack()" type='primary'>进栈</button> <button onclick="popStack()" type='primary'>出栈</button> </div> </div> <script> // 栈盒子 let stackBox = document.getElementById('stackBox') // 执行函数盒子 let funStackBox = document.getElementById('funStackBox') // 栈类 class Stack { constructor(length) { this.list = [] this.length = length } // 新增栈 addStack(val) { if (this.length > this.list.length) { this.list.push(val) let beforeDom = document.getElementById(this.list.length - 1) // 新增栈 let el = document.createElement('li') el.id = this.list.length el.innerText = this.list[this.list.length - 1] stackBox.insertBefore(el, beforeDom) }else{ console.log('栈满了') } } // 弹出栈 popStack() { let delDom = document.getElementById(this.list.length) stackBox.removeChild(delDom) return this.list.pop() } // 栈的大小 stackLength() { console.log('当前栈大小为'+this.list.length) return this.list.length } // 栈的顶层元素 stackIsHas() { return this.list.length?this.list[this.list.length]:console.log('没有栈了') } //查看全部元素 showStack() { return this.list.join('\n'); } //清空队列 clearStack() { this.list = []; this.showStack() console.log('栈空了') } } stackOne = new Stack(5) /** * @author: 周靖松 * @information: 进栈 * @Date: 2019-06-10 12:47:16 */ function pushStack() { stackOne.addStack(funStackBox.value) console.log(funStackBox.value, '进栈') stackOne.stackLength() stackOne.stackIsHas() } /** * @author: 周靖松 * @information: 出栈 * @Date: 2019-06-10 12:47:16 */ function popStack() { let popStack = stackOne.popStack(funStackBox.value) console.log(popStack, '出栈') stackOne.stackLength() stackOne.stackIsHas() } </script> </body>
效果图以下函数
上边说了栈的基本结构和方法,那么栈被建立的时候又作了什么事情呢flex
首先在咱们的js在解释执行代码的时候,最早遇到的就是全局代码,因此在一开始的时候首先就会向栈里边压入一个全局执行上下文this
全局上下文 只有在全局执行环境被销毁的时候才会被弹出销毁
全局执行上下文 只有一个 就是浏览器中的window对象,this默认指向这个全局对象3d
而后当执行一个函数的时候,会在开始先建立一个执行上下文压入栈中,若是里边又执行其余的函数的时候,又会建立一个新的执行上下文压入执行栈中,直到函数执行完毕,就会把函数的上下文从执行栈中弹出指针
function fun3() { console.log('3') } function fun2() { fun3(); } function fun1() { fun2(); } fun1();
好比说上边这段代码 ,他的进栈出栈顺序就是一开始咱们放的那两张图的效果code
function fun1() { console.log('1') } function fun2() { console.log('2') } function fun3() { console.log('3') }
若是是这种的话 则会是最下边有一个全局的栈,而后三个函数分别进栈出栈
刚才咱们在上边提到了执行上下文的概念,执行上下文是跟函数相关的,执行上下文分为两个阶段
首先建立阶段
简单说一下词法环境和变量环境的区别,我我的理解的就是说词法环境是包含变量环境的
在js里边原型链你们都不陌生 ,js在当前的对象里边找不到所使用的属性的话会去他的上一级去找
直到Object,再找不到就会undefined ,这里边 当前对象的做用域就是他的变量环境,而词法环境则是与之关联的的执行上下文中声明的变量
在建立阶段 函数的声明会被储存在当前的变量环境之中,var的变量的话则会被设置成undefined
,因此咱们在声明以前就能够访问到var声明的变量 ,but他是一个undfined
而后就是执行阶段了
这个时候已经完成了对全部变量的分配,开始执行代码
队列是一种比较高效的数据结构,他与栈不一样的是,队列只能在队尾插入元素,在队首删除元素,
队列用生活中的事物距离的话,你们能够想一想一下沙漏,先进入的沙子先出去,后进去的沙子后出去
队列比栈高效的地方就在于,循环的时候,栈会开辟一个新的临时栈,而后进行排序,再循环,最后在确保不打乱原有顺序的状况下 排列回去
队列则不须要这么多步骤
队列经常使用的一些操做有
就先拿这些经常使用的方法实现如下,老规矩,请你们看代码
// 队列类 class Queue { constructor() { this.dataStore = [] } //新增 addQueue(val) { this.dataStore.push(val); } //删除队列首的元素 delQueue() { return this.queueIsNone()?console.log('队列空了'):this.dataStore.shift() } //队列是否为空 queueIsNone() { return this.dataStore.length == 0 } //查看全部元素 showQueue() { return this.dataStore.join('\n'); } //清空队列 clearQueue() { this.dataStor = []; this.showQueue() console.log('队列空了') } } // 队列实例 let queueOne = new Queue() /** * @author: 周靖松 * @information: 进队 * @Date: 2019-06-11 21:01:28 */ function QueueIn (){ queueOne.addQueue(funStackBox.value) console.log(queueOne.showQueue()) } /** * @author: 周靖松 * @information: 出队 * @Date: 2019-06-11 21:01:35 */ function QueueOut (){ queueOne.delQueue() console.log(queueOne.showQueue()) } /** * @author: 周靖松 * @information: 清空队列 * @Date: 2019-06-11 21:05:35 */ function QueueClear(){ queueOne.clearQueue() }
上边的代码 你们能够本身写个html试一下哈,html就不写了直接贴一下效果图
另外虽然刚才咱们再例子中是用数据去模拟的栈和队列的实现,but 数组他其实并非一个栈内存,他是一个堆内存
如果知足如下特性,便可称为堆:是计算机科学中的一种特别的树状数据结构。能够给堆中的任意节点添加新的节点(百科全书)
在JS中,每个数据都须要一个内存空间。内存空间又被分为两种,栈内存(stack)与堆内存(heap)。
也不是说不会自动释放,堆在没有引用的时候,下一次垃圾回收机制出现的时候会回收他的内存
js 的变量分为基本类型和引用类型
基本类型 (Undefined、Null、Boolean、Number和String)
基本类型在内存中占据空间小、大小固定 ,他们的值保存在栈(stack)空间,是按值来访问
引用类型 (对象、数组、函数)
引用类型占据空间大、大小不固定, 栈内存中存放地址指向堆(heap)内存中的对象。是按引用访问的
盗个图举个例子
js不容许直接访问堆内存中的位置,所以咱们不能直接操做对象的堆内存空间,因此栈中存的是一个指向堆内存的一个地址
当咱们要访问堆内存中的引用数据类型时,实际上咱们首先是从栈中获取了该对象的地址引用(或者地址指针),而后再从堆内存中取得咱们须要的数据。
今天就堆栈队列的内容就大概说到这里 下一篇博客 在继续说一下, 有什么说的不对或者不足的地方,请你们批评指正