Cây và binary search tree: thuật ngữ và bất biến
Học từ vựng của cây, các loại cây nhị phân, và bất biến tìm kiếm làm nền cho treap, heap và cây quyết định.
DễCấu trúc dữ liệu ~45 phút
Ôn lại trước khi học
Giới thiệu
Bài này học từ vựng cây và cây tìm kiếm. Bạn dùng nó cho heap và treap sau này.
Kiến thức cần nhớ
Từ vựng cây
- Gốc là nút duy nhất không có cha.
- Lá là nút không có con nào.
- Anh em là 2 nút cùng cha.
- Ví dụ đời thường: cây gia phả có ông bà con cháu.
- Bậc của nút là số con trực tiếp.
Cây nhị phân và BST
- Cây nhị phân mỗi nút tối đa 2 con.
- BST thêm luật: trái nhỏ hơn, phải lớn hơn.
- Luật này đúng với mọi nút trong cây.
- Ví dụ đời thường: tủ hồ sơ xếp trái nhỏ phải lớn.
- Tìm kiếm thì so sánh rồi rẽ trái hoặc phải.
Cây lệch và cân bằng
- Chèn tăng dần tạo cây nghiêng như list.
- Cây lệch tìm kiếm tốn .
- Cây cân bằng tìm kiếm tốn .
- Ví dụ đời thường: thang thẳng đứng và thang rộng.
| Loại cây | Đặc điểm |
|---|---|
| Nhị phân | Tối đa 2 con |
| Đầy (full) | Mọi nút có 0 hoặc 2 con |
| Hoàn chỉnh (complete) | Mọi tầng đầy trừ tầng cuối, tầng cuối dồn trái (dùng cho heap) |
| Hoàn hảo | Đầy và mọi lá cùng tầng |
| BST | Trái nhỏ, phải lớn |
Ví dụ
- Input: BST gốc 10, trái 5, phải 15, tìm 7. Output: thăm 10, 5 rồi báo không thấy.
- Giải thích: nhỏ hơn thì rẽ trái, lớn hơn thì rẽ phải.
💻 Bài tập
Ngôn ngữ: C++ (hoặc C). Nộp vào day-007/. Khóa là int, không trùng.
Bài 1: BST cơ bản
struct Node { int key; Node *left = nullptr, *right = nullptr; };
class BST {
public:
bool insert(int key); // trả false nếu key đã có
bool contains(int key) const;
int height() const; // cây rỗng = -1, 1 nút = 0
size_t size() const;
std::vector<int> inorder() const;
~BST(); // giải phóng mọi nút
};
| Hàm | Độ phức tạp |
|---|---|
insert, contains | |
height, size, inorder |
insert 10, 5, 15, 3, 7, 12, 20 -> inorder = [3,5,7,10,12,15,20], height=2
insert 7 lần nữa -> false, size vẫn 7
contains(12) / contains(8) -> true / false
Bài 2: Kiểm tra BST và đường tìm
- Viết
bool isBST(const Node *root). Mỗi nút phải nằm trong khoảng(min, max)do tổ tiên quy định, không chỉ so với con trực tiếp. - Viết
std::vector<int> searchPath(int key)trả dãy khóa đã thăm.
Cây: 10 (trái 5 (phải 12), phải 15) -> isBST = false (12 nằm bên trái 10)
Cây Bài 1, searchPath(8) -> [10, 5, 7]
Cây Bài 1, searchPath(20) -> [10, 15, 20]
Bài 3: Cây lệch và cây cân (nâng cao)
- Chèn 1..1000 theo thứ tự tăng. In
height(). - Chèn cùng tập khóa theo thứ tự "giữa trước": viết
void insertBalanced(std::vector<int> &sorted, int l, int r)chèn phần tử giữa rồi đệ quy hai nửa. Inheight(). - Chèn 1000 khóa theo thứ tự ngẫu nhiên (seed cố định). In
height(). - Đo thời gian 10^5 lần
containsngẫu nhiên trên cả 3 cây.
Kỳ vọng: tăng dần -> height = 999; giữa trước -> height = 9; ngẫu nhiên -> khoảng 20
Cây 1000 nút chèn tăng dần mà dùng đệ quy có thể tràn stack ở máy yếu. Viết
insert bằng vòng lặp.✅ Tiêu chí hoàn thành
- Test mẫu pass,
inorderluôn tăng dần. -
isBSTbắt được ca vi phạm ở cháu, không chỉ ở con. - Bảng chiều cao và thời gian của Bài 3 có số thật.
- Sanitizer sạch, destructor giải phóng hết nút.
❓ Câu hỏi ôn tập
- Gốc, lá, anh em là gì?
- BST khác cây nhị phân thường ở đâu?
- Tìm kiếm trên BST đi thế nào?
- Vì sao cây lệch lại chậm?
🌕 Bạn đã hoàn thành ngày 7. Làm hết bài tập phía trên rồi sang ngày tiếp theo.