Đầu ở chỉ số 0, cuối ở chỉ số len(Q)-1
Lưu hàng đợi bằng list theo thứ tự đầu đến cuối. `append(x)` thêm cuối; `pop(0)` lấy và loại bỏ phần tử đầu. `front(Q)` chỉ xem đầu, không xóa.
```python
def Queue():
return []
def isEmptyQueue(Q):
return len(Q) == 0
def enqueue(Q, x):
Q.append(x)
def dequeue(Q):
if isEmptyQueue(Q):
raise ValueError("Hàng đợi rỗng")
return Q.pop(0)
def front(Q):
if isEmptyQueue(Q):
raise ValueError("Hàng đợi rỗng")
return Q[0]
```
Xen kẽ thêm và lấy
Với Q ban đầu rỗng:
|Lệnh|Q sau lệnh|Giá trị trả về nếu có|
|---|---|---|
|enqueue(Q,3); enqueue(Q,7)|[3, 7]|—|
|dequeue(Q)|[7]|3|
|enqueue(Q,2)|[7, 2]|—|
|front(Q)|[7, 2]|7|
|dequeue(Q)|[2]|7|
FIFO dựa trên thứ tự thêm, không dựa trên giá trị lớn hay nhỏ. Số 2 vẫn chờ sau 7 vì được thêm sau.
Trong cách cài đặt này, `pop(0)` làm các phần tử phía sau dịch vị trí nên chi phí tăng theo độ dài hàng đợi, thường viết O(n). Xem phần tử đầu là O(1); append có chi phí trung bình phân bổ O(1). Vì vậy không kết luận mọi thao tác hàng đợi dùng list đều O(1). Python có collections.deque phù hợp hơn khi cần lấy đầu thường xuyên; ở đây dùng list để theo cách biểu diễn của SGK.
Bài luyện
Lệnh nào lấy đúng phần tử đầu và loại bỏ nó trong cách cài đặt này?
Đây là xem phần tử cuối.
Không ghi chỉ số thì pop lấy cuối.
Đây là xem đầu nhưng chưa xóa.
Đúng. Chỉ số 0 là đầu hàng đợi.
Lời giải
Đầu được lưu tại Q[0]. pop(0) trả về và xóa phần tử tại vị trí đó; Q[0] đơn thuần chỉ xem, còn pop() mặc định lấy phần tử cuối.
Bài luyện
Theo bảng ví dụ, sau lần dequeue cuối, Q còn gì?
7 vừa bị lấy khỏi đầu.
Đúng. 3 rồi 7 đã được lấy ra.
2 vào sau và chưa được lấy.
Còn 2 trong hàng đợi.
Lời giải
Thêm 3,7 rồi lấy 3 để lại [7]. Thêm 2 tạo [7,2]; front chỉ xem 7. Lần dequeue kế tiếp lấy 7 nên còn [2].
Bài luyện
Vì sao dequeue dùng list.pop(0) thường có chi phí O(n)?
Đúng. Số phần tử phải dịch tăng cùng độ dài danh sách.
FIFO không yêu cầu sắp xếp theo giá trị.
Mã không có thao tác đảo.
front chỉ xem đầu.
Lời giải
Xóa ở vị trí 0 làm các phần tử còn lại đổi chỉ số để lấp chỗ trống. Với n phần tử, có thể cần dịch n−1 phần tử, nên chi phí tăng tuyến tính theo n.
Đang học