- Cho cha và bác thành màu đen Ông của x thành màu đỏ
Tiến trình chung
-Tìm nút là nút có khoá k trong cây
-Tiến hành huỷ z (hoặc huỷ phần tử thế mạng) và tạo liên kết với các nhánh con của z
Quy ước
GV: TRẦN HỮU QUỐC THƯ
Do khi xoá và cân bằng cây, sẽ có nhiều trường hợp cần phải xử lý, trong đó có việc kiểm tra nút là nút NULL?
Giải pháp : thay tất cả các nút NULL bằng 1 nút đặc biệt, có tên là Null. Đây là nút thật sự luôn có màu đen, các trị của nó (key, trái , phải, cha)
Quy ước
pNode Null; Int main() {
Null -> color = BLACK;
Null ->pParent= Null->pLeft=Null- >pRight = NULL;
Null -> Key = 0; }
Phân tích
GV: TRẦN HỮU QUỐC THƯ
Khi nào cần cân bằng lại cây?
+ Khi nút bị xoá là nút có màu đen
Khi cân bằng cần để ý đến sự vi phạm t/c nào? + t/c chiều cao cây đen
Phân tích
Khi huỷ một nút đen thì chiều cao đen của nhánh chứa nó sẽ bị sụt giảm 1 đơn vị, ta có thể:
+ Biến nút đen cùng cấp ở cây con còn lại thành nút đỏ (nếu được)
+ Thực hiện xoay cây để tạo sự cân bằng => KL: Kết hợp đổi màu và xoay cây
CODE
GV: TRẦN HỮU QUỐC THƯ
void Delete(RBTree &t, int k) {
//Tìm nút z cần xoá if (isEmpty(t)) return; pNode z = t.root;
while (z!=Null && z->key !=k){ if (z->key > k) z= z->pLeft; else z= z->pRight; } if (z==Null)
CODE
Xác định nút y là nút cần thực sự xoá
If (z->pLeft ==Null !! z->pRight == Null) y = z; //z không đủ 2 con => xoá
else
//y chỉ có thể có 1 con y = SearchStandFor(z);
CODE
GV: TRẦN HỮU QUỐC THƯ
//Tiến hành xoá y
pNode x; // x là nút con của y if (y->pLeft != Null)
x=y->pLeft; else
x = y->pRight;
//cha của x là cha của y
//Nếu x là Null vẫn không báo lỗi x->pParent = y->pParent;
CODE
if (y->pParent == Null) //y là gốc t.root = x; else if (y->Parent->pLeft ==y) y->pParent->pLeft = x; else y->pParent->pRight =x;
CODE
GV: TRẦN HỮU QUỐC THƯ
//Kiểm tra cân bằng
if (y != z) // y là phần tử thế mạng z->key = y->key;
if (y->color == BLACK)
FIXUP(t,x); // cân bằng lại
//Xoá y
y->pLeft = y->pRight = y->pParent=Null; Delete y;