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

本文是学习算法的笔记,《数据结构与算法之美》,极客时间的课程

我们浏览网页,经常会用到前进,后退的功能。比如依次浏览了a-b-c 三个页面,这时点后退,可以回到 b 页面,再次点击回到 a 页面。如果这时,又进入 新页面d ,那就无法通过前进,后退功能回到b、c页面了。

这样一个功能,要如何实现呢?

其实这样一个功能,可以借助栈来实现。

什么是栈?它是一个数据结构,数据先进后出,后进先出。打一个比方,放一叠盘子,放的时候,都放最上面,取的时候也从最上面取。典型的后进先出。

栈,可以用数组来实现,也可以用链表来实现。前者叫顺序栈,后者是链式栈。

为什么会有栈这种数据结构,直接用数组或是链表不就好了么?栈有严格的限制,只能从栈顶压入数据,从栈顶取数据,可以满足特定场景的需求,而链表或是数组暴露了太多的接口,容易出错。

如何实现一个栈

public class ArrayStack{
	private String [] items; // 数组
	private int count; // 栈中元素个数
	private int n; //栈的大小
	
	// 初始化数组,申请一个大小为 n 的数组空间
	public ArrayStack(int n){
		items = new String [n];
		this.n = n;
		count = 0;
	}
	// 入栈操作
	public boolean push(String item){
		if(count == n){
			return false;
		}
		items[count-1] = item;
		count++;
		return true;
	}
	// 出栈操作
	public String pop(){
	if(count == 0){
		return null;
	}
	String temp = items[count-1];
	count--;
	return temp;
	}
}

栈的实际应用

栈作为一个基础的数据结构,经典的应用场景是函数调用。

我们知道,操作系统,为每个线程分配了独立的内存空间,这些内存空间组织成栈的结构,来存储函数调用产生的临时变量。每次进入一个函数,将临时变量作为栈桢入栈,当函数调用完成,有结果返回时,函数对应的栈桢出栈。便于理解,我们看一看下面的一段代码

int main() {
	int a = 1;
	int ret = 0;
	int res = 0;
	ret = add(3, 5);
	res = a+ret;
	printf("%d", res);
	return 0;
}
int add(int x, int y){
	int sum = 0;
	sum = x + y;
	return sum;
}

为了清晰地看到这个函数调用的过程中,出栈、入栈的操作,贴一张图
在这里插入图片描述

栈在表达式求值中的应用

再看一个常见的应用场景,编译器如何利用栈来实现表达式求值。

我们用一个简单的四则运算来说明这个问题,比如3+5*8-6,对于计算机来说,如何理解这个表达式,是个不太容易的事儿。

事实上,编译器是通过两个栈来实现的,其中一个保存数字,暂且叫A,一个保存运算符暂且叫B。从左到右遍历表达式,当遇到数字,直接压入A栈,当遇到运符时,就与B栈中栈顶元素进行比较。

如果比栈顶元素的优先级高,就将运算符压入栈,如果相同或者低,从B栈中取出栈顶元素,从A栈的栈顶取出两个数字,进行计算,再把计算结果压入A栈,继续比较。如下图在这里插入图片描述

解答开篇的那个问题

我们使用两个栈,X和Y,首次浏览的页面,依次压入栈X。当点击回退时,依次从X栈中取出数据,并依次放入Y栈。点击前进时,从Y栈中取出数据,并依次放入X栈。当X栈中没有数据时,就说明不能再回退了;当Y中没有数据时,就说明不能再前进了。

比如你依次浏览了a b c 三个页面,我们依次把 a b c 压入栈,这时两个栈是这个样子
在这里插入图片描述
浏览器通过后退按钮,回退到页面 a 时,我们把 c b 依次压入Y栈,这时两个栈是这个样子
在这里插入图片描述
这时候,你又通过前进按钮,又回到 b 页面,这时两个栈的数据是这个样子
在这里插入图片描述

这时,你由 b 页面打开新的页面 d,那么你就不能再通过后退回到 c 页面,Y栈数据要清空。这时两个栈是这个样子
在这里插入图片描述

  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值