Tên là khóa, giá là thông tin đi kèm
Mỗi nút lưu `[tên món, giá]`; None vẫn là vị trí không có nút. So sánh tên để đi trái/phải, không so giá khi tra theo tên. Ví dụ dữ liệu giả định:
|Tên món|Giá, đồng|
|---|---|
|Mì rau|25000|
|Cơm nấm|20000|
|Trà gừng|12000|
|Nước lọc|12000|
Tên món không trùng; hai món có thể cùng giá. Giá lưu dạng số nguyên để so sánh hoặc tính toán. Tệp menu.inp ghi hai trường cách bởi dấu phẩy, không viết dấu phân cách hàng nghìn trong giá.
Tìm và thêm hoặc cập nhật theo trường khóa
Các hàm dùng lại left, right và Tree. record_search trả chỉ số hoặc −1. record_upsert trả True khi cập nhật khóa đã có, False khi thêm khóa mới. Nó dùng bản sao row để lưu dữ liệu.
```python
def record_search(T, key):
k = 0
while k < len(T) and T[k] is not None:
if key == T[k][0]:
return k
k = left(k) if key < T[k][0] else right(k)
return -1
def record_upsert(T, row):
key = row[0]
k = 0
while k < len(T) and T[k] is not None:
if key < T[k][0]:
k = left(k)
elif key > T[k][0]:
k = right(k)
else:
T[k] = row.copy()
return True
if k >= len(T):
T.extend([None] * (k-len(T)+1))
T[k] = row.copy()
return False
def record_inorder(T, k, out):
if 0 <= k < len(T) and T[k] is not None:
record_inorder(T, left(k), out)
out.append(T[k].copy())
record_inorder(T, right(k), out)
```
Chạy menu.py trong bộ mẫu
Giải nén đủ bộ mẫu ở bài cuối. Chạy menu.py: chọn 1 rồi nhập `Trà gừng` để nhận 12000. Chọn 2, nhập lại `Trà gừng` và giá 15000; chọn 1 tra lại phải được 15000. Chọn 2 với `Sữa đậu`, giá 18000 để thêm mới, rồi tra phải được 18000. Tra `Món chưa có` phải báo không tìm thấy; nhập 0 để thoát.
Chương trình đọc UTF-8 bằng csv.reader và chuyển giá qua int; nó báo tên/giá nhập không hợp lệ nếu tên rỗng, giá không phải số nguyên hoặc không dương. Các phép so sánh tên dùng quy tắc chuỗi của Python và phân biệt hoa/thường; cần nhập đúng tên, dấu tiếng Việt như tệp. Thứ tự Unicode không tự tương đương quy tắc sắp từ điển tiếng Việt.
Thay đổi trong lần chạy chỉ nằm trong bộ nhớ; chương trình chưa ghi lại menu.inp. Sau khi thoát và chạy lại, dữ liệu trở về bản trong tệp. Có thể mở menu.py để xem vòng lặp chọn chức năng; không cần giao diện đồ họa.
Bài luyện
Khi tra giá theo tên trên cây thực đơn, khóa so sánh là trường nào?
Giá là dữ liệu đi kèm, không là khóa của cây này.
Đúng. Cây được tổ chức theo tên món.
Chỉ số dòng không dùng làm khóa.
Số lượng cùng giá không xác định tên cần tìm.
Lời giải
Nút lưu [tên,giá], thuật toán so sánh tên cần tìm với T[k][0]. Tìm được chỉ số k mới đọc T[k][1] để lấy giá.
Bài luyện
Thêm/cập nhật [Trà gừng,15000] khi tên đã có sẽ cho kết quả nào?
Hàm xử lí khóa bằng nhau bằng cập nhật.
Giá không thay vai trò của tên.
Đúng. Không tạo thêm khóa trùng.
Không tác động đến món khác.
Lời giải
record_upsert đi đến nút có khóa Trà gừng và thay dữ liệu tại chính nút đó bằng bản ghi mới. Vẫn chỉ có một khóa Trà gừng; giá là 15000.
Bài luyện
Sau cập nhật giá trong menu.py rồi thoát, chạy lại mà chưa sửa tệp đầu vào sẽ thế nào?
Đúng. Bộ mẫu chưa có bước ghi cập nhật ra tệp.
Dữ liệu trong bộ nhớ của lần chạy đã kết thúc.
Mã không tạo cơ sở dữ liệu.
Có thể chạy lại và nạp tệp ban đầu.
Lời giải
Mỗi lần mở, chương trình tạo cây mới từ menu.inp. Cập nhật trước đó chỉ nằm trong bộ nhớ và không được ghi ra tệp, nên lần chạy mới dùng giá đang lưu trong tệp.
Đang học