简易的浏览器历史记录系统

46 阅读6分钟

简易的浏览器历史记录系统

背景介绍

请你设计并实现一个简易的浏览器历史记录系统。这个系统需要模拟现代浏览器中的核心功能:访问新页面、后退、前进,并管理一个有容量上限的历史记录列表。

核心概念

  1. 浏览历史 (History List):

    • 可以看作一个线性的页面访问序列。
    • 例如: [pageA, pageB, pageC, pageD]
  2. 当前页指针 (Current Page Pointer):

    • 在任何时候,总有一个指针指向历史记录列表中的某个页面,这个页面就是用户当前正在浏览的页面。
    • back() 操作会使该指针向列表的左侧(更早的记录)移动。
    • forward() 操作会使该指针向列表的右侧(更新的记录)移动。
  3. 历史容量 (History Capacity):

    • 系统最多只能缓存 maxCount 个历史记录。
    • 如果在添加新页面后,历史记录总数超过了 maxCount,系统会自动删除最早的一条历史记录(即列表最左侧的条目)。

功能要求

你需要实现一个 BrowserHistorySys 类,支持以下操作:

BrowserHistorySys(string homepage, int maxCount)
  • 功能: 系统初始化。

  • 效果:

    • homepage 作为第一个页面,放入浏览历史中。
    • 设置历史记录的容量上限为 maxCount
    • 当前页指针指向 homepage
visit(string url)
  • 功能: 访问一个新的 URL。

  • 规则:

    1. 如果 url当前页相同,则不做任何操作。

    2. 如果 url 是一个新页面,则:

      a. 清除前进记录: 丢弃当前页指针右侧的所有历史记录。

      b. 添加新记录: 将 url 添加到历史记录的末尾(即当前页之后)。

      c. 更新指针: 将当前页指针移动到这个新添加的 url 上。

      d. 检查容量: 如果此时历史记录的总数超过了 maxCount,则从历史记录的最开头移除一个最旧的页面。

  • 返回值: 返回操作完成后,浏览历史中的缓存页面总数量。

back()
  • 功能: 在浏览历史中后退一步。
  • 规则: 将当前页指针向移动一个位置。
  • 边界: 如果光标已经位于历史记录的最开头,则无法再后退,停留在原地。
  • 返回值: 返回后退后所停留页面的 URL。
forward()
  • 功能: 在浏览历史中前进一步。
  • 规则: 将当前页指针向移动一个位置。
  • 边界: 如果光标已经位于历史记录的最后,则无法再前进,停留在原地。
  • 返回值: 返回前进后所停留页面的 URL。

输入格式

  • homepage, url: 字符串,由小写字母、数字、./ 组成,长度 [8, 32)
  • maxCount: 0 < maxCount < 20
  • 函数调用总次数不超过 1000 次。

输出格式

  • 根据每个函数的原型要求返回相应的值。最终的整体输出由评测框架完成。

样例

输入样例 1

["BrowserHistorySys", "visit", "back", "forward", "forward", "visit", "visit", "back", "visit", "back", "visit"]
[["w3.huawei.com", 10], ["google.com"], [], [], [], ["baidu.com"], ["youtube.com"], [], ["baidu.com"], [], ["mails.huawei.com"]]

输出样例 1

[null, 2, "w3.huawei.com", "google.com", "google.com", 3, 4, "baidu.com", 4, "google.com", 3]

样例 1 执行流程详解

  • 当前页用 *...* 标记
#调用解释与系统状态变化返回值
1BrowserHistorySys("w3.huawei.com", 10)初始化。历史记录: [*w3.huawei.com*]null
2visit("google.com")访问新页面。历史记录: ["w3.huawei.com", *"google.com"*]。大小为 2。2
3back()后退一步。历史记录: [*w3.huawei.com*, "google.com"]"w3.huawei.com"
4forward()前进一步。历史记录: ["w3.huawei.com", *"google.com"*]"google.com"
5forward()已在历史记录末尾,无法前进,停留在原地。历史记录: ["w3.huawei.com", *"google.com"*]"google.com"
6visit("baidu.com")访问新页面,无前进记录可清除。历史记录: ["w3.huawei.com", "google.com", *"baidu.com"*]。大小为 3。3
7visit("http://...")访问新页面。历史记录: ["w3.huawei.com", ..., *"http://..."*]。大小为 4。4
8back()后退一步。历史记录: [..., "google.com", *"baidu.com"*, "http://..."]"baidu.com"
9visit("baidu.com")访问的 URL 与当前页相同,不做任何操作。历史记录和大小不变。4
10back()后退一步。历史记录: [..., *"google.com"*, "baidu.com", "http://..."]"google.com"
11visit("mails.huawei.com")访问新页面。当前页为 google.com,其后的前进记录 ["baidu.com", "http://..."] 被清除。然后添加新页面。历史记录: ["w3.huawei.com", "google.com", *"mails.huawei.com"*]。大小为 3。3
import java.util.ArrayList;
import java.util.List;

/**
 * 模拟一个浏览器的历史记录系统.
 * 该系统使用一个列表来存储浏览历史,并用一个指针来跟踪当前页面。
 * 它支持访问新页面、后退和前进等核心功能。
 */
public class BrowserHistorySys {

    // --- 系统状态变量 ---

    /** 使用列表来存储浏览历史记录的URL. */
    private final List<String> history;

    /** 缓存的最大页面数量. */
    private final int maxCount;

    /** 一个整数索引,作为指针,指向 history 列表中当前页面的位置. */
    private int currentIndex;

    /**
     * BrowserHistorySys(string homepage, int maxCount) -- 初始化系统.
     * @param homepage 初始化的主页URL
     * @param maxCount 浏览历史的最大缓存数量
     */
    public BrowserHistorySys(String homepage, int maxCount) {
        this.history = new ArrayList<>();
        this.maxCount = maxCount;
        // 初始时,将主页加入历史记录
        this.history.add(homepage);
        // 当前指针指向唯一的记录,即索引0
        this.currentIndex = 0;
    }

    /**
     * visit(string url) -- 跳转访问新页面.
     * @param url 要访问的新页面的URL
     * @return 操作后,浏览历史中的缓存页面数量
     */
    public int visit(String url) {
        // 获取当前页面的URL
        String currentPage = this.history.get(this.currentIndex);

        // 如果要访问的URL和当前页相同,则不做任何操作
        if (url.equals(currentPage)) {
            return this.history.size();
        }

        // --- 如果是新的URL,则执行以下操作 ---

        // 1. 清除浏览历史中原当前页的所有“前进”记录。
        // subList 创建了一个从 currentIndex+1 到列表末尾的视图,.clear() 操作会从原始列表中删除这些元素。
        if (this.currentIndex < this.history.size() - 1) {
            this.history.subList(this.currentIndex + 1, this.history.size()).clear();
        }

        // 2. 将新访问的URL添加到历史记录的末尾
        this.history.add(url);

        // 3. 检查缓存是否超出容量上限
        if (this.history.size() > this.maxCount) {
            // 如果超出,则移除历史记录中最早的一条(即列表的第一个元素)
            this.history.remove(0);
        }
        
        // 4. 更新当前页指针。在访问新页面后,当前页总是历史记录中的最后一项。
        // 这一步必须在可能发生的 remove(0) 操作之后执行,以确保索引正确。
        this.currentIndex = this.history.size() - 1;

        // 5. 返回当前历史记录的数量
        return this.history.size();
    }

    /**
     * back() -- 在浏览历史中后退一步.
     * @return 后退后停留页面的URL
     */
    public String back() {
        // 检查是否还有后退的空间(即当前不是第一条记录)
        if (this.currentIndex > 0) {
            // 如果可以后退,则将指针向前移动一位
            this.currentIndex--;
        }
        // 如果已无法后退,指针保持不变。
        
        // 返回指针当前指向的页面的URL
        return this.history.get(this.currentIndex);
    }

    /**
     * forward() -- 在浏览历史中前进一步.
     * @return 前进后停留页面的URL
     */
    public String forward() {
        // 检查是否还有前进的空间(即当前不是最后一条记录)
        if (this.currentIndex < this.history.size() - 1) {
            // 如果可以前进,则将指针向后移动一位
            this.currentIndex++;
        }
        // 如果已无法前进,指针保持不变。

        // 返回指针当前指向的页面的URL
        return this.history.get(this.currentIndex);
    }
}