栈:如何实现浏览器的前进和后退功能?

       浏览器的前进、后退功能,其实就是利用了栈的数据结构

       当我们依次访问一串页面a-b-c,点击浏览器的后退按钮,就可以查看之前浏览过的页面b和a。当你后退到页面a,点击前进按钮,就可以重新查看页面b和c。但是如果后退到b后,点击了新的页面d,那就无法通过前进、后退功能看到页面c了。

1.如何理解“栈”?

        先进者后出,后进者先出,这就是典型的“栈”结构。

        从栈的操作特性上来看,栈是一种“操作受限”的线性表,只允许在一端插入和删除数据。当某个数据集合只涉及在一端插入和删除数据,并且满足后进先出、先进后出的特性,我们应该首选“栈”这种数据结构。

2.如何实现一个“栈”?

        从栈的定义中,我们可以发现栈的主要两个操作就是:入栈和出栈,也就是在栈顶插入一个数据和从栈顶删除一个数据。那么该如何实现一个栈呢?

       实际上,栈既可以用数组来实现,也可以用链表来实现。用数组实现的栈叫作:顺序栈,用链表实现的栈,叫作链式栈。

3.栈操作的时间空间复杂度是多少呢?

       不管是顺序栈还是链式栈,存储数据只需要一个大小为n的数组就够了。在入栈和出栈的时候,只需要一两个临时变量的存储空间,所以空间复杂度为O(1)。空间复杂度是指除了原始的数据存储空间以外,算法运行还需要额外的存储空间。

      不管是顺序栈还是链式栈,入栈、出栈只涉及栈顶个别数据的操作,所以时间复杂度是O(1)。

4.支持动态扩容的顺序栈

        要实现一个支持动态扩容的顺序栈,就需要底层依赖一个动态扩容的数组就可以了。当栈满了以后,就申请一个更大的数组,将原来的数据搬移到新数组中。

        分析一下支持动态扩容的数据顺序栈的入栈、出栈操作的时间复杂度。对于出栈操作来说,不会涉及到内存的重新申请和数据的搬移,所以出栈的时间复杂度是O(1)。但是对于入栈操作来说,情况就不一样了。当栈中有空闲空间时,入栈操作的时间复杂度是O(1),当空间不够时,就需要重新申请内存和数据搬移,所以时间复杂度就变成了O(n)。

5.栈在函数调用中的应用

        栈的一个比较经典的应用场景就是函数调用栈。操作系统给每个线程分配了一块独立的内存空间,这块内存被组织成“栈”这种结构,用来存储函数调用时的临时变量。每进入一个函数,就会将临时变量作为一个栈帧入栈,当被调用函数执行完毕之后,将这个函数对应的栈帧出栈。不是很明白这一块的逻辑

6.栈在表达式求值中的应用

        栈的另外一个应用场景就是编译器利用栈来实现表达式求值。编译器通过两个栈来实现的。其中一个保存操作数的栈,另外一个是保存运算符的栈。从左向右遍历表达式,当遇到数字,就直接压入操作数栈,当遇到运算符,就与运算符栈顶元素进行比较。如果比栈顶运算符元素优先级高,就将运算符压入栈;如果比栈顶运算符元素优先级相同或是低,从运算符栈中取出栈顶运算符,从操作数栈的栈顶取2个操作数,然后进行计算,再把计算结果压入栈,继续比较。

       下面以3+5*8-6这个表达式的计算过程为例进行图形的展示。

7.栈在括号匹配中的应用

        可以借助栈来检查表达式中的括号是否匹配。简化背景,只考虑三种括号:(),[],{},并且可以任意嵌套组合。现在给定一个包含三个括号的表达式字符串,如何检查它是否合法?

        用栈来保存未匹配的左括号,从左到右依次扫描字符串。当扫描到左括号时,将其压入栈中;当扫描到右括号时,从栈顶取出一个左括号。如果能够匹配,则继续扫描剩下的字符串。如果扫描的过程中,遇到不能配对的右括号,或是栈中没有数据,则说明为非法格式。

       当所有的括号都扫描完成以后,如果栈为空,则说明字符串为合格字符串;否则,则认为非法格式。

8.如何实现浏览器的前进、后退功能?

        用两个栈就可以完美解决这个问题。

       比如我们顺序查看了a,b,c三个页面,我们就依次把a,b,c压入栈,这个时候,两个栈的样子如下图所示:

        当我们从浏览器的后退按钮,从页面c后退到页面a之后,我们就依次把c和b从栈X放入到栈Y中,这个时候两个栈的数据就是如下图所示:

        这时你又想看页面b,点击前进按钮回到页面b,就是把b从栈Y中出栈,放入到栈X当中。此时,栈中的数据如下图所示:

        这时如果通过页面b跳转到一个新的页面d了,页面c就无法通过前后退按钮重复查看了,所以需要清空栈Y。此时两个栈如小图所示:

 

 

 

  • 3
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值