Академический Документы
Профессиональный Документы
Культура Документы
Hồ Chí Minh
CTDL2 – HIENLTH
HIENLTH, HCMUP 3
Các tính chất
CTDL2 – HIENLTH
HIENLTH, HCMUP 4
Ví dụ:
CTDL2 – HIENLTH
HIENLTH, HCMUP 5
Cây đỏ đen
• Chiều cao đen (black height – hb(x)) là số
node đen trên đường đi từ node x đến lá
(không bao gồm x)
• Từ quy tắc [4] Không thể tồn tại node cha
và node con cùng đỏ. Khi cây đỏ đen vi
phạm quy tắc này gọi là hiện tượng xung đột
đỏ - đỏ.
CTDL2 – HIENLTH
HIENLTH, HCMUP 6
Nhận xét
• Cây đỏ đen có N nút trong (internal node) có
chiều cao tối đa là 2logn(N+1)
• Chiều cao của cây (h) <= 2 * chiều cao đen
(hb)
• Các nút lá là NIL (nút ngoài – external node)
luôn là node đen.
• Mỗi cạnh đến 1 node đen được gọi là cạnh
đen.
• Thời gian tìm kiếm O(logN)
CTDL2 – HIENLTH
HIENLTH, HCMUP 7
Cây đỏ đen
Cấu trúc lưu trữ:
• Thông tin lưu trữ tại node (key)
• Địa chỉ node gốc của cây con bên trái
(*pLeft)
• Địa chỉ node gốc của cây con bên phải
(*pRight)
• Địa chỉ node cha (*pParent)
• Thuộc tính màu của node (color)
CTDL2 – HIENLTH
HIENLTH, HCMUP 8
b. Biểu diễn cây đỏ - đen
struct Node
{
int Key; //Dữ liệu
Node* pLeft, *pRight;
int color; //RED - BLACK
Node* pParent; //Trỏ đến nút cha
};
+ Khởi tạo
void Init (RBTree &t);
+ Kiểm tra rỗng
int isEmpty (RBTree t);
CTDL2 – HIENLTH
HIENLTH, HCMUP 10
d. Xuất cây ra màn hình
CTDL2 – HIENLTH
HIENLTH, HCMUP 11
d. Xuất cây ra màn hình (tt)
void Print (pNode p, int level)
{
if (!p)
{
textcolor(BLACK);
for (int i = 0 ; i < level; ++ i)
{
cout<<“ “;
cout<<“NULL “<<endl;
}
CTDL2 – HIENLTH
HIENLTH, HCMUP 12
d. Xuất cây ra màn hình (tt)
Print(p->pRight, level + 1);
for (i= 0; i < level;i++)
cout<<“ “;
if (p->color == RED)
textcolor (RED);
else
textcolor (BLACK);
cout<<p->Key;
Print(p->pLeft , level +1)
}
}
CTDL2 – HIENLTH
HIENLTH, HCMUP 13
e. Chèn một nút vào cây đỏ đen
Chèn một nút như trong cây tìm kiếm nhị phân
bình thường và gán cho nó màu đỏ.
B1. Tìm vị trí thích hợp để chèn khoá K
B2. Phát sinh 1 nút mới có khoá K, màu
đỏ (RED) và gắn liên kết tại vị trí tìm
được.
B3. Hiệu chỉnh lại cây nếu có vi phạm
tính chất (tô màu lại & quay)
CTDL2 – HIENLTH
HIENLTH, HCMUP 14
Các tính chất có thể vi phạm khi thêm nút
• Mọi node là đỏ hoặc đen OK
• Node gốc là đen Not OK nếu thêm node
mới là node gốc
• Các node lá (NIL) phải luôn đen OK
• Nếu 1 node là đỏ, các node con của nó phải
là đen Not OK nếu cha node thêm màu đỏ
2 node đỏ liên tiếp.
• Mọi đường dẫn từ gốc đến lá chứa một số
lượng node đen như nhau OK
CTDL2 – HIENLTH
HIENLTH, HCMUP 15
void RBTree_Insertion(RBTree &root, int key)
{
x = getNode(key,RED, NIL);
BSTree_Insert(root, x);
Insertion_Fixup(root, x);
}
CTDL2 – HIENLTH
HIENLTH, HCMUP 16
Gọi:
• X: Con trỏ, trỏ đến nút
vừa chèn vào
• P: Con trỏ, nút cha của g
CTDL2 – HIENLTH
HIENLTH, HCMUP 17
Một số định nghĩa
U
U CTDL2 – HIENLTH
HIENLTH, HCMUP 18
* Phép quay phải tại y
x γ
α β
CTDL2 – HIENLTH
HIENLTH, HCMUP 19
Phép quay (như BST)
y
Quay phải
x
γ
α
x Quay trái
y
α β β γ
CTDL2 – HIENLTH
HIENLTH, HCMUP 20
Các trường hợp sau khi thêm:
• Nếu p đen Dừng (1)
• Nếu p đỏ:
– Nếu u đỏ, đảo màu 3 nút p, u, g (2)
– Nếu u đen:
• Nếu x là cháu ngoại của g: Thực hiện 1
phép quay (3)
• Nếu x là cháu nội của g: Thực hiện 2
phép quay (4)
CTDL2 – HIENLTH
HIENLTH, HCMUP 21
Trường hợp 1
• P đen Bình thường (dừng)
CTDL2 – HIENLTH
HIENLTH, HCMUP 22
Trường hợp 2
• P đỏ, U đỏ Đảo màu G, P, U
g g
p u p u
x x
CTDL2 – HIENLTH
HIENLTH, HCMUP 23
G
P X
U
G
X
P U
Case 2 – P, U is Red
Just Recolor and move up
CTDL2 – HIENLTH
HIENLTH, HCMUP 24
Trường hợp 3
• P đỏ, U đen, x là cháu ngoại Quay tại
P; Đổi màu P, G
CTDL2 – HIENLTH
HIENLTH, HCMUP 25
G
P U
S P
X
X G
Case 3 – Zig-Zig
Single Rotate P around G
S U
Recolor P and G
CTDL2 – HIENLTH
HIENLTH, HCMUP 26
Trường hợp 4
• P đỏ, U đen, x là cháu nội Quay tại P
(trở thành cháu ngoại), sau đó Quay tại
G; Đổi màu P, G
Tương tự
TH3
CTDL2 – HIENLTH
HIENLTH, HCMUP 27
G
P U
S X X
P G
Case 4 – Zig-Zag
Double Rotate S
X around P; X around G
U
Recolor G and X
CTDL2 – HIENLTH
HIENLTH, HCMUP 28
Hàm quay trái (tương tự cho quay phải)
void LeftRotate(RBTree t, pNode x){
pNode y = x->pRight;
x->pRight = y->pLeft; //Bên phải x là β
if (p->pLeft !=NULL)
p->pLeft ->pParent = x; //cha β là x
p->pParent = x->pParent; // cha của x là cha của y
y->pLeft = x;
x ->pParent = y;
}
CTDL2 – HIENLTH
HIENLTH, HCMUP 30
Ví dụ: Chèn một nút vào cây đỏ đen
Lần lượt chèn vào các nút có giá trị:
50, 75, 25, 80, 100, 110, 105
50
“ông” x
“bác” x 75
“cha” x
25
x
80
CTDL2 – HIENLTH
HIENLTH, HCMUP 31
TH2: Cha, bác x đều có màu đỏ
- Cho cha và bác thành màu đen
-Ông của x thành màu đỏ
(lưu ý: nút gốc qui ước là màu đen)
50 “ông” x
“bác” x 75
“cha” x
25
x
80
CTDL2 – HIENLTH
HIENLTH, HCMUP 32
TH3: Bác x đều có màu đen x là con phải của cha x
75
80
25 25
80
100
x
75
100 x
CTDL2 – HIENLTH
HIENLTH, HCMUP 33
50
80
25
100
75
110
105
x
CTDL2 – HIENLTH
HIENLTH, HCMUP 34
TH4: x là con trái, cha x là phải
hoặc x là con phải, cha x là trái
Quay trái (phải) tại cha (không đổi màu)
50
80
25
100
75
105 TH.3
110
CTDL2 – HIENLTH
HIENLTH, HCMUP 35
CODE
void Insert(RBTree &t, int k)
{
-Tìm vị trí cần chèn k
-Phát sinh 1 nút x có khoá là k, màu đỏ, và chèn vào vị
trí cần chèn
//Bắt đầu cân bằng
while (x!=t.root && x->pParent->color==RED)
{
//cha x là con trá của ông x
if ( x -> p == x->pParent->pParent->pLeft)
{
//y là “bác” của x
y = x->pParent->pParent->pRight;
}
CTDL2 – HIENLTH
HIENLTH, HCMUP 36
CODE
if (y->color == RED){ //TH1
x->pParent->Color = BLACK;
y->color = BLACK;
x->pParent -> pParent -> color = RED
x = x->pParent -> pParent;
}
CTDL2 – HIENLTH
HIENLTH, HCMUP 37
CODE
else
if (x== x->pParent->pRight){ //TH3
x = x->pParent;
LeftRotate(t,x);
}
//TH2 luôn xảy ra sau đó
X->pParent ->color = BLACK;
X->pParent->pParent->color = RED;
RightRotae(t,x->pParent->pParent);
}
CTDL2 – HIENLTH
HIENLTH, HCMUP 38
CODE
CTDL2 – HIENLTH
HIENLTH, HCMUP 39
Red-Black Trees
Insertion example
11
2 14
1 7 15
5 8
CTDL2 – HIENLTH
HIENLTH, HCMUP 40
Red-Black Trees
Insertion example
11
2 14
1 7 15
5 8
4 Case 1
CTDL2 – HIENLTH
HIENLTH, HCMUP 41
Red-Black Trees
Insertion example
11
7 14
2 8 15
1 5
4 Case 2
CTDL2 – HIENLTH
HIENLTH, HCMUP 42
Red-Black Trees
Insertion example
2 11
1 5 8 14
15
4
Case 3
CTDL2 – HIENLTH
HIENLTH, HCMUP 43
CTDL2 – HIENLTH
HIENLTH, HCMUP 44
CTDL2 – HIENLTH
HIENLTH, HCMUP 45
f. Huỷ một nút trong cây đỏ đen
• Tìm và hủy giống cây NPTK (BST).
• Kiểm tra tính cân bằng mất cân bằng
cân bằng lại.
Sau khi xóa:
• Nếu y đỏ Không cần cân bằng lại.
• Nếu y đen:
– Tất cả các đường đi con từ gốc đến nút lá (qua
y) sẽ ít hơn 1 nút đen so với những đường đi
còn lại (vi phạm t/c 4)
– Nếu p và x cùng đỏ thì vi phạm t/c 3.
CTDL2 – HIENLTH
HIENLTH, HCMUP 46
Gọi:
• y: Con trỏ, trỏ đến nút bị xóa
thật sự
• x: Con trỏ, trỏ đến nút con p
của nút trỏ bởi y, sẽ thay thế
nút y w
y
• w: Con trỏ, trỏ đến nút anh
em của nút trỏ bởi x
• p: Con trỏ, trỏ đến nút cha x
của nút trỏ bởi y
CTDL2 – HIENLTH
HIENLTH, HCMUP 47
Dấu hiệu đen (black token)
• Được gán cho nút trỏ bởi x (nút con thật sự của
nút bị xóa y)
• Báo hiệu con đường đi qua các nút có chứa nó sẽ ít
hơn những con đường khác 1 nút đen
• “dấu hiệu đen” đi ngược lên cây cho tới khi chiều
cao cây được đảm bảo.
• Nút chứa dấu hiệu đen, bản thân là:
– Nút đen nút đen kép
– Nút đỏ nút đỏ đen
• Là khái niệm trừu tượng, không cài đặt
CTDL2 – HIENLTH
HIENLTH, HCMUP 48
Quy ước
CTDL2 – HIENLTH
HIENLTH, HCMUP 49
Quy ước
pNode Null;
void main()
{
Null -> color = BLACK;
Null ->pParent= Null->pLeft=Null->pRight = NULL;
Null -> Key = 0;
}
CTDL2 – HIENLTH
HIENLTH, HCMUP 50
Phân tích
CTDL2 – HIENLTH
HIENLTH, HCMUP 51
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
CTDL2 – HIENLTH
HIENLTH, HCMUP 52
CODE
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)
return ; //Không tìm thấy
CTDL2 – HIENLTH
HIENLTH, HCMUP 53
CODE
CTDL2 – HIENLTH
HIENLTH, HCMUP 54
CODE
//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;
CTDL2 – HIENLTH
HIENLTH, HCMUP 56
CODE
//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;
CTDL2 – HIENLTH
HIENLTH, HCMUP 57
Cân bằng lại cây sau khi xoá một nút đen
CTDL2 – HIENLTH
HIENLTH, HCMUP 58
TH1: x đỏ hoặc gốc
• Nút x chứa “dấu hiệu đen” là nút đỏ
(nút đỏ - đen) hay nút gốc.
Xử lý:
• Tô màu nút đỏ đen sang màu đen.
• Loại bỏ dấu hiệu đen và kết thúc
CTDL2 – HIENLTH
HIENLTH, HCMUP 59
TH2: x đen kép, w và 2 con w đều đen
• Đổi màu nút anh em w sang đỏ
• Đổi màu P đen (bất kể P trước đó màu đỏ
hay màu đen)
• Di chuyển “dấu hiệu đen” lên trên 1 cấp
(theo hướng gốc của cây)
CTDL2 – HIENLTH
HIENLTH, HCMUP 60
TH2: x đen kép, w và 2 con w đều đen
B B
x w Đổi màu
w sang đỏ
A D D
A
α β α
C E β
C E
δ γ ε η δ γ ε η
B B
x w Đổi màu
w sang đỏ
A D A D
α β α β
C E C E
δ γ ε η δ γ ε η
CTDL2 – HIENLTH
HIENLTH, HCMUP 61
TH3: x đen kép, w đỏ, 2 con w đen, p đen
• Đảo màu nút p và w
• Thực hiện phép quay tại w (theo hướng
đưa w lên, p xuống w làm ông của x)
• Dấu hiệu đen vẫn chỉ vào nút x ban đầu
p w
CTDL2 – HIENLTH
HIENLTH, HCMUP 62
TH3: w đỏ
D
B
w Left Rotate
E
x B
D Đổi màu
A
ε η
x
α β C E
A w
mới
C
δ γ ε η α β δ γ
CTDL2 – HIENLTH
HIENLTH, HCMUP 63
TH4: x đen kép, w đen, 1 trong 2 con w đỏ
Gọi z là nút con của w có màu đỏ.
(w có ít nhất một con đỏ gọi là z)
Có 2 trường hợp xảy ra:
• 4a) z là cháu nội
• 4b) z là cháu ngoại
Xử lý:
• 4a) chuyển sang 4b) nhờ phép quay và đổi
màu
• 4b) được xử lý bằng phép quay và đổi màu
CTDL2 – HIENLTH
HIENLTH, HCMUP 64
TH4a: w đen con trái w màu đỏ
Đỏ/đen
BB
B
Quay phải tại W w mới
x w x A
C
D Đổi màu
δ
A
z mới
z
β
D
α β E
α
γ
C
E
δ γ ε η
ε η
CTDL2 – HIENLTH
HIENLTH, HCMUP 65
Xử lý
• 4a) chuyển sang 4b):
– Đổi màu Z và W
– Quay tại Z (theo hướng đưa z lên, w xuống)
• Xử lý 4b)
– Quay tại W (theo hướng đưa W lên, P xuống)
– Đảo màu P, W
– Z đổi theo màu P
– Mất dấu hiệu đen
CTDL2 – HIENLTH
HIENLTH, HCMUP 66
TH4b: w đen con phải w màu đỏ
Đỏ/đen
D
p B
Quay trái tại cha của x
x w D Đổi màu B E
A
ε η
α β C E z A C
δ γ ε η γ
α β δ
CTDL2 – HIENLTH
HIENLTH, HCMUP 67
Bài tập áp dụng
Cho cây đỏ đen như sau:
50
25 60
10 30
55 65
CTDL2 – HIENLTH
HIENLTH, HCMUP 68
Cây 2-3-4
CTDL2 – HIENLTH
HIENLTH, HCMUP 69
Cây 2-3-4
Node không phải là lá:
• Một node với một mục dữ liệu thì luôn
luôn có 2 con.
• Một node với hai mục dữ liệu thì luôn
luôn có 3 con.
• Một node với ba mục dữ liệu thì luôn
luôn có 4 con.
Đối với mọi node với số con là k và số
mục dữ liệu là d, thì : k = d + 1
CTDL2 – HIENLTH
HIENLTH, HCMUP 70
Các loại nút
CTDL2 – HIENLTH
HIENLTH, HCMUP 71
Các trường hợp của cây 2-3-4
CTDL2 – HIENLTH
HIENLTH, HCMUP 72
Các trường hợp của cây 2-3-4
2 - 3 - 4 tree
CTDL2 – HIENLTH
HIENLTH, HCMUP 73
Các trường hợp của cây 2-3-4
CTDL2 – HIENLTH
HIENLTH, HCMUP 74
Cấu trúc một nút
struct Node
{
char key[3];
int type; // 2 , 3, 4 – Node
Node* next[4];
};
CTDL2 – HIENLTH
HIENLTH, HCMUP 75
Tổ chức cây 2-3-4
• Trong cây 2-3-4, các nút lá đều nằm trên
cùng một mức. Các node ở mức trên thường
không đầy đủ, nghĩa là chúng có thể chứa
chỉ 1 hoặc 2 mục dữ liệu thay vì 3 mục.
• Lưu ý rằng cây 2-3-4 là cây cân bằng. Nó
vẫn giữ được sự cân bằng khi thêm vào các
phần tử có thứ tự (tăng dần hoặc giảm dần).
CTDL2 – HIENLTH
HIENLTH, HCMUP 76
Cách chèn nút
CTDL2 – HIENLTH
HIENLTH, HCMUP 77
Thêm nút
• Theo nguyên lý Top – Down (đi từ trên
xuống), gặp nút đầy thì tách rồi mới chèn.
• Dữ liệu thêm luôn được chèn vào node lá.
• Nếu node thêm vào chưa đầy thêm vào
bình thường.
• Node đầy dữ liệu (có 3 mục dữ liệu) thì tách.
Ta có 2 trường hợp:
– Tách node gốc
– Tách node không phải là gốc
CTDL2 – HIENLTH
HIENLTH, HCMUP 78
Tách nút gốc
• Node gốc đầy tách trước, chèn sau
• Giả sử node gốc có 3 mục dữ liệu A, B, C (đã được
sắp thứ tự). Quá trình tách:
– Node mới được tạo ra để trở thành gốc mới và là cha của
node được tách.
– Node mới thứ hai được tạo ra để trở thành anh em với
node được tách.
– Mục dữ liệu C được dịch đưa sang node anh em mới.
– Mục dữ liệu B được dịch đưa sang node gốc mới.
– Mục dữ liệu A vẫn không đổi.
– Hai node con bên phải nhất của node được phân chia bị
hủy kết nối khỏi nó và kết nối đến node mới bên phải.
CTDL2 – HIENLTH
HIENLTH, HCMUP 79
Ví dụ về tách node gốc
CTDL2 – HIENLTH
HIENLTH, HCMUP 80
Ví dụ Tách nút
CTDL2 – HIENLTH
HIENLTH, HCMUP 81
Ví dụ Tách nút
CTDL2 – HIENLTH
HIENLTH, HCMUP 82
Ví dụ về chèn nút
CTDL2 – HIENLTH
HIENLTH, HCMUP 83
Ví dụ về xóa node
• Khóa k nằm trong nút lá u và u có nhiều hơn
một khóa: giải phóng khóa k khỏi u .
CTDL2 – HIENLTH
HIENLTH, HCMUP 84
Ví dụ về xóa node
• Khóa k nằm trong nút lá u và u chỉ có một khóa và
tồn tại nút anh em v của u có nhiều hơn một khóa
thì bằng phép dịch chuyển dần có thể dịch chuyển
một khóa của v đến u khiến u trở thành 3-nút và
quay về trường hợp 1.
CTDL2 – HIENLTH
HIENLTH, HCMUP 85
Ví dụ về xóa node
• Khóa k nằm trong nút lá u và u chỉ có một khóa và
tất cả các nút anh em của u chỉ có một khóa thì
bằng phép gộp u với nút anh em kề nó sẽ khiến u
trở thành 3-nút và quay về trường hợp 1.
CTDL2 – HIENLTH
HIENLTH, HCMUP 86
Ví dụ về xóa node
• Khóa k nằm trong nút trong u: Khi đó tìm khóa tiền nhiệm
hoặc khóa kế vị của k (khóa này luôn nằm trong nút lá).
Thay k bởi khóa đó, và giải phóng khóa đó tkhỏi nút chứa
nó (quay về trường hợp 1). Tuy việc dùng khóa tiền nhiệm
hay kế vị đều được, nhưng nên chọn khóa nào trong chúng
nằm trong nút có hai khóa trở lên, nếu cả hai đều nằm
trong các 2-nút thì chọn khóa nào cũng được.
CTDL2 – HIENLTH
HIENLTH, HCMUP 87
Đánh giá
CTDL2 – HIENLTH
HIENLTH, HCMUP 88
Biến đổi cây 2-3-4 sang cây đỏ đen
• Biến đổi bất kỳ 2-node ở cây 2-3-4 sang
node đen ở cây đỏ-đen.
CTDL2 – HIENLTH
HIENLTH, HCMUP 89
Biến đổi cây 2-3-4 sang cây đỏ đen
• Biến đổi bất kỳ 3-node sang node con C (với
hai con của chính nó) và node cha P (với các
node con C và node con khác). C được tô
màu đỏ và P được tô màu đen
CTDL2 – HIENLTH
HIENLTH, HCMUP 92