Thứ tự duyệt kết hợp với tính chất BST
Trên BST, duyệt giữa thăm hết các khóa nhỏ hơn ở trái, thăm gốc rồi thăm các khóa lớn hơn ở phải, nên nhận dãy tăng dần. Duyệt ngược đổi thành **phải–gốc–trái** nên nhận dãy giảm dần.
Kết luận này cần điều kiện BST. Duyệt giữa một cây nhị phân bất kì chưa chắc cho dãy tăng dần. Với BST cơ bản khóa khác nhau, chèn lại 8 bị bỏ qua; vì vậy dùng nó sắp dãy [8,4,8,2] sẽ làm mất một lần xuất hiện của 8.
Biến thể: khóa bằng nhau đi sang phải
Để sắp xếp mà giữ đủ phần tử, dùng đúng biến thể của SGK: nhỏ hơn đi trái; lớn hơn hoặc bằng đi phải. Lúc này mọi khóa trái nhỏ hơn nút, mọi khóa phải lớn hơn hoặc bằng nút. Hàm insert_repeat khác insert đã học ở cách xử lí bằng nhau.
bst_sort trả danh sách mới và giữ nguyên A. Dùng inorder và các hàm chỉ số đã có.
```python
def insert_repeat(T, v):
k = 0
while k < len(T) and T[k] is not None:
k = left(k) if v < T[k] else right(k)
if k >= len(T):
T.extend([None] * (k-len(T)+1))
T[k] = v
def bst_sort(A):
T = Tree()
for x in A:
insert_repeat(T, x)
result = []
inorder(T, 0, result)
return result
```
Không đánh mất một số 8
Chèn 8 rồi 4,8,2 bằng insert_repeat tạo `[8,4,8,2]`. Duyệt giữa cho **[2,4,8,8]**. Duyệt ngược cho **[8,8,4,2]**.
```python
A = [8,4,8,2]
B = bst_sort(A)
print(A)
print(B)
```
A vẫn [8,4,8,2]; B là [2,4,8,8]. Muốn lấy thứ tự giảm từ cây đã tạo, khởi tạo out=[] rồi gọi reverseorder(T,0,out). Không thay phép duyệt ngược bằng trái–gốc–phải rồi gọi đó là giảm dần.
Bài luyện
bst_sort([8,4,8,2]) theo biến thể giữ khóa trùng trả về gì?
Đã làm mất một lần xuất hiện của 8.
Đây là giảm dần; hàm dùng inorder tăng dần.
Đây là đầu vào chưa sắp xếp.
Đúng. Giữ đủ bốn phần tử theo thứ tự tăng.
Lời giải
insert_repeat không bỏ qua khóa bằng nhau mà đi phải để chèn nút mới. Hai số 8 đều có trong cây, nên duyệt giữa trả [2,4,8,8].
Bài luyện
Phép duyệt nào cho thứ tự giảm dần trên BST?
Đây là tăng dần trên BST.
Đúng. Xử lí khóa lớn trước khóa nhỏ.
Duyệt trước chưa bảo đảm sắp khóa.
Duyệt sau chưa bảo đảm sắp khóa.
Lời giải
Cây con phải chứa khóa lớn hơn hoặc bằng gốc; cây con trái nhỏ hơn gốc trong biến thể đang dùng. Duyệt phải, gốc rồi trái tạo thứ tự không tăng, thường gọi giảm dần có thể có giá trị bằng nhau.
Bài luyện
Vì sao không dùng insert bỏ qua khóa trùng để sắp xếp một dãy cần giữ đủ phần tử?
BST ở bài này dùng được số nguyên.
inorder chỉ đưa dữ liệu vào out.
Đúng. Dãy sắp xếp phải giữ cả các lần lặp.
Sắp xếp không đồng nghĩa loại phần tử trùng.
Lời giải
Ví dụ dãy có hai số 8 nhưng insert cơ bản chỉ giữ một nút 8. Duyệt cây ấy sẽ có ít phần tử hơn đầu vào. Cần biến thể cho phép trùng hoặc lưu số lần lặp.
Đang học