Trang hiện tại được giữ riêng
Mô hình có `current` là trang đang xem, `backward` lưu các trang có thể Quay lại, `forward` lưu các trang có thể Tiến tới. Đỉnh mỗi ngăn xếp là trang sẽ được mở ở lần bấm tương ứng.
Khi thăm trang mới, đưa trang hiện tại vào backward rồi đổi current. Khi Quay lại, đưa current vào forward, lấy đỉnh backward làm current mới. Tiến tới làm ngược lại. Nếu ngăn xếp cần lấy đang rỗng thì giữ current.
Sau khi Quay lại rồi thăm một trang mới, xóa forward vì đã rẽ sang nhánh lịch sử mới. Mô hình này chỉ minh họa thứ tự chuyển trang, không mở website hoặc mô phỏng mọi tính năng của trình duyệt.
Các hàm dùng lại push và pop
Dùng các hàm ngăn xếp của bài trước. Khởi tạo `backward = Stack()`, `forward = Stack()`, `current = None`; luôn gán lại giá trị hàm trả về cho current, chẳng hạn `current = visit(backward, forward, current, 'A')`.
```python
def visit(backward, forward, current, page):
if current is not None:
push(backward, current)
forward.clear()
return page
def go_back(backward, forward, current):
if isEmptyStack(backward):
return current
push(forward, current)
return pop(backward)
def go_forward(backward, forward, current):
if isEmptyStack(forward):
return current
push(backward, current)
return pop(forward)
```
Một lần rẽ sang trang mới
Trong bảng, ngăn xếp viết từ đáy đến đỉnh.
|Thao tác|backward|current|forward|
|---|---|---|---|
|Thăm A, B, C|[A, B]|C|[]|
|Quay lại|[A]|B|[C]|
|Tiến tới|[A, B]|C|[]|
|Quay lại, rồi thăm D|[A, B]|D|[]|
Ở dòng cuối, C bị loại khỏi forward khi thăm D. Nếu tiếp tục Tiến tới thì vẫn ở D. Nếu chỉ pop trang hiện tại khỏi một ngăn xếp rồi lại trả chính trang đó, mô hình sẽ không thực sự chuyển về trang trước.
Bài luyện
Đang ở C, backward=[A,B], forward=[]. Sau Quay lại, trạng thái nào đúng?
B ở đỉnh nên được lấy trước A.
Đúng. Lưu C sang forward rồi lấy B.
C phải được chuyển sang forward.
C thuộc forward, không thêm vào backward lúc Quay lại.
Lời giải
Quay lại trước hết lưu current=C vào forward. pop(backward) lấy B ở đỉnh và đặt current=B; backward còn [A], forward là [C].
Bài luyện
Đang ở B sau khi Quay lại từ C. Tiếp đó thăm trang mới D. Vì sao cần xóa forward?
Thăm D đặt current=D, không phải A.
Trang hiện tại giữ riêng.
Đúng. Nhánh cũ qua C không được dùng làm Tiến tới.
Quay lại chuyển một trang sang forward, không xóa hết.
Lời giải
Từ B thăm D tạo nhánh A→B→D. C thuộc nhánh đã bỏ khi quay về B. Xóa forward giúp nút Tiến tới không mở C như thể vẫn ở nhánh cũ.
Bài luyện
backward đang rỗng. Theo go_back đã định nghĩa, kết quả là gì?
Đúng. Hàm trả về current trước khi gọi pop.
Nhánh kiểm tra rỗng tránh gọi pop.
Hàm không đổi current ở trường hợp này.
Không có thao tác đảo hai ngăn xếp.
Lời giải
isEmptyStack(backward) là True nên go_back trả về current ngay. Không có trang để Quay lại, vì vậy cả trang hiện tại và hai ngăn xếp được giữ nguyên.
Đang học