一、引言

我们浏览网页,会发现“前进”和“后退”是 Web 浏览器的常用功能,实现该功能的一种方式是使用两个栈(backward 栈和forward 栈)来存储用户访问的网址,用户的不同操作对应的具体实现方法如下:

  • 后退(BACK):如果backward 栈为空,则该命令被忽略。否则,将当前页面压入forward栈,并从backward 栈中弹出一个页面作为当前页面。
  • 前进(FORWARD):如果forward 栈为空,则该命令被忽略。否则,将当前页面压入backward 栈,并从forward 栈中弹出一个页面作为当前页面。
  • 访问某网址(VISIT <URL>):将当前页面压入backward 栈,并将此次访问的网页作为当前页面,清空forward 栈。

二、整体思路

根据栈结构后进先出的顺序,我们很容易想到,可以把用户当前浏览的网页入栈,当用户在新界面点击回退按钮的时候,直接让栈顶元素出栈,让浏览器加载,不就实现了后退功能了吗?前进的功能也类似,于是乎,我们想到用两个栈分别存储在用户当前浏览网页之前/之后的所有页面地址。理想的结构(BackStack回退栈,ForwardStack前进栈),如下图所示:

算法高级(10)-如何实现浏览器的前进、后退功能_java

三、c++实现代码

#include<iostream>
#include<string>
#include<stack>
using namespace std;
int main(){
stack<string> backward,forward;
string now,b,c="csw.jlu.edu.cn";
while(1){
cin>>b;
if(b=="VISIT"){
cin>>now;
cout<<now<<endl;
backward.push(c);
while(!forward.empty()){
forward.pop();
}
}
if(b=="BACK"){
if(backward.size()!=0){
c=backward.top();
backward.pop();
cout<<c<<endl;
forward.push(now);
now=c;
}
else{
cout<<"Ignored"<<endl;
c="csw.jlu.edu.cn";
}
}
if(b=="FORWARD"){
if(forward.size()!=0){
c=forward.top();
forward.pop();
cout<<c<<endl;
backward.push(now);
now=c;
}
else{
cout<<"Ignored"<<endl;
}
}
if(b=="QUIT"){
break;
}
if(b!="VISIT"&&b!="BACK"&&b!="FORWARD"&&b!="QUIT"){
cout<<"输入错误!"<<endl;
}
}
}

四、页面按钮实现的前进后退

<input type=button value=刷新 onclick="window.location.reload()"> 
<input type=button value=前进 onclick="window.history.go(1)">
<input type=button value=后退 onclick="window.history.go(-1)">
<input type=button value=前进 onclick="window.history.forward()">
<input type=button value=后退 onclick="window.history.back()">
<input type=button value=后退并刷新 onclick="window.history.go(-1);window.location.reload()">

下面是history源码,有没有什么发现呢?

interface History {
readonly length: number;
scrollRestoration: ScrollRestoration;
readonly state: any;
back(distance?: any): void;
forward(distance?: any): void;
go(delta?: any): void;
pushState(data: any, title?: string, url?: string | null): void;
replaceState(data: any, title?: string, url?: string | null): void;
}

五、总结

  1. 此面试题在安卓面试中出现比较多。
  2. history对象的存储结构与栈相同,先进后出。

我的微信公众号:架构真经(id:gentoo666),分享Java干货,高并发编程,热门技术教程,微服务及分布式技术,架构设计,区块链技术,人工智能,大数据,Java面试题,以及前沿热门资讯等。每日更新哦!

算法高级(10)-如何实现浏览器的前进、后退功能_#include_02