chương 7: cÂy (tree)
Post on 19-Jan-2016
19 Views
Preview:
DESCRIPTION
TRANSCRIPT
Chương 7: CÂY (Tree)
Chương 7: Cây (Tree)
Nội dung2
Cấu trúc cây (Tree) Cấu trúc cây nhị phân (Binary Tree) Cấu trúc cây nhị phân tìm kiếm (Binary Search Tree) Cấu trúc cây nhị phân tìm kiếm cân bằng (AVL Tree)
Chương 7: Cây (Tree)
Tree – Đinh nghia3
Cây là một tập gồm 1 hay nhiều nút T, trong đó có một nút đặc biệt được gọi là gốc, các nút còn lại được chia thành những tập rời nhau T1, T2 , ... , Tn theo quan hệ phân cấp trong đó Ti cũng là một cây
A tree is a set of one or more nodes T such that: i. there is a specially designated node called a root ii. The remaining nodes are partitioned into n disjointed set of nodes
T1, T2,…,Tn, each of which is a tree
Chương 7: Cây (Tree)
Tree – Ví dụ 4
Sơ đồ tổ chức của một công ty
Công ty ACông ty A
R&DR&D Kinh doanhKinh doanh Taøi vuïTaøi vuï Saûn xuaátSaûn xuaát
TVTV CDCD AmplierAmplierNoäi ñòaNoäi ñòa Quoác teáQuoác teá
Chaâu aâuChaâu aâu MyõMyõ Caùc Caùc nöôùcnöôùc
Chương 7: Cây (Tree)
Tree – Ví dụ
Cây thư mục
5
Chương 7: Cây (Tree)
Tree – Ví dụ
Có phai là cây không
Chương 7: Cây (Tree)
Tree – Ví dụ
Có phai là cây không
8
Không vì trong cấu trúc cây không tồn tại chu trình
Chương 7: Cây (Tree)
Tree - Một số khái niệm cơ bản
Bậc của một nút (Degree of a Node of a Tree): Là số cây con của nút đó. Nếu bậc của một nút bằng 0 thì nút đó
gọi là nút lá (leaf node) Bậc của một cây (Degree of a Tree):
Là bậc lớn nhất của các nút trong cây. Cây có bậc n thì gọi là cây n-phân
Nút gốc (Root node): Là nút không có nút cha
Nút lá (Leaf node): Là nút có bậc bằng 0
9
J
Z A
DRB
LFAKQ Lá
nút
gốcCạnh
Chương 7: Cây (Tree)
Tree - Một số khái niệm cơ bản10
Nút nhánh: Là nút có bậc khác 0 và không phai là gốc
Mức của một nút (Level of a Node): Mức (T0) = 0, với T0 là gốc
Gọi T1, T2, T3, ... , Tn là các cây con của T0:
Mức(T1) = Mức(T2) = ... = Mức(Tn) = Mức(T0) + 1We define the level of the node by taking the level of the root node as 0, and
incrementing it by 1 as we move from the root towards the subtrees.
Chiều cao của cây (độ sâu) (Height – Depth of a Tree): Là mức cao nhất của nút + 1 (mức cao nhất của 1 nút có trong cây)
t1 t2
t3
Chương 7: Cây (Tree)
Tree - Một số khái niệm cơ bản11
Nút trước, nút sau của 1 nút Nút T được gọi là nút trước của 1 nút (ancestor’s node) của
nút S nếu cây con có gốc là T chứa cây con có gốc là S. Khi đó S được gọi là nút sau của nút T (descendant’s node)
Chiều dài đường đi của 1 nút Chiều dài đường đi của 1 nút là số đỉnh (số nút) tính từ nút
gốc để đi đến nút đó. Chiều dài đường đi của nút gốc luôn =1, chiều dài đường đi
tới 1 nút bằng chiều dài đường đi tới nút cha của nó + 1
Chương 7: Cây (Tree)
Tree - Một số khái niệm cơ bản12
Chiều dài đường đi của 1 cây Chiều dài đường đi của 1 cây (path’s length of the tree) là
tổng tất ca các chiều dài đường đi của tất ca các nút trên cây (chiều dài đường đi trong internal path’s length).
Tính chiều dài đường đi ngoài (external path’s length) bằng cách mở rộng tất ca các nút của cây sao cho các nút của cây có cùng bậc (thêm vào các nút gia) với bậc của cây.
Rừng. Rừng (forest) là tập hợp các cây. Khi cây mất gốc rừng
Chương 7: Cây (Tree)
Tree – Ví dụ
- Leaf node?- Degree of a Nodes of a Tree?- Degree of a Tree?- Level of a Node?- Height – Depth of a Tree?
Chương 7: Cây (Tree)
Trắc nghiệm
The depth of a tree is the _______ of a treea) number of nodes on the tree
b) number of levels of a tree
c) number of branches
d) level Give the binary tree with root A. The root has left child B and
right child C. B has left child D and right child E. There are no other nodes in the tree. The height of the tree is _______.a) 0
b) 3
c) 1
d) 2
14
Chương 7: Cây (Tree)
Nội dung19
Cấu trúc cây (Tree) Cấu trúc cây nhị phân (Binary Tree) Cấu trúc cây nhị phân tìm kiếm (Binary Search Tree) Cấu trúc cây nhị phân tìm kiếm cân bằng (AVL Tree)
Chương 7: Cây (Tree)
Binary Tree – Đinh nghia20
Cây nhị phân là cây mà mỗi nút có tối đa 2 cây con (cây có bậc là 2)
Chương 7: Cây (Tree)
Binary Tree – Ví dụ21
Cây con trai
Cây con phai
Hinh anh môt cây nhị phân
Chương 7: Cây (Tree)
Binary Tree – Ví dụ
Cây lệch trái và cây lệch phai
Chương 7: Cây (Tree)
Binary Tree – Ví dụ
Cây nhị phân đầy đủ (A full binary tree)
Chương 7: Cây (Tree)
Binary Tree – Ứng dụng
Cây biểu thức: được dùng để biểu diễn một biểu thức toán học
24
Chương 7: Cây (Tree)
Binary Tree – Ví dụ
Cây quyết định: được dùng để hỗ trợ quá trình ra quyết định
25
Chương 7: Cây (Tree)
Binary Tree – Một số tính chất
Số nút nằm ở mức i ≤ 2i
Số nút lá ≤ 2h-1, với h là chiều cao của cây Số nút trong cây ≤ 2h-1, với h là chiều cao của cây Chiều cao của cây ≥ log2N, với N là số nút trong cây
26
Chương 7: Cây (Tree)
Trắc nghiệm
A binary tree is a tree in which each node references at most _____ node(s) 1 0 3 2
The maximum number of leaf-nodes in a binary tree of height 4 is: 2 4 6 8
What is the minimum height of a binary tree with 31 nodes? 4 7 5 3
If the depth of a binary tree is 3, then what is the maximum size of the tree? 3 4 6 8
27
Chương 7: Cây (Tree)
Binary Tree - Biểu diễn
In general, any binary tree can be represented using an array, but it leads to the waste of storage …
Chương 7: Cây (Tree)
Binary Tree - Biểu diễn29
Chương 7: Cây (Tree)
Binary Tree - Biểu diễn30
Chương 7: Cây (Tree)
Binary Tree - Biểu diễn31
Sử dụng cấu trúc để lưu trữ các thông tin của một nút gồm: Dữ liệu của nút Địa chỉ nút gốc của cây con trái Địa chỉ nút gốc của cây con phai
Khai báo cấu trúc cây nhị phân:
Để quan lý cây nhị phân chỉ cần quan lý địa chỉ nút gốc:
Tree root;
struct TNode{
DataType data; TNode *pLeft,
*pRight;};typedef TNode* Tree; //??
Chương 7: Cây (Tree)
Binary Tree – Khởi tạo cây
Khởi tạo cây rỗng:
void InitTree (Tree &t)
{
t = NULL;
}
33
Chương 7: Cây (Tree)
Binary Tree - Duyệt cây nhi phân 34
Có 3 kiểu duyệt chính có thể áp dụng trên cây nhị phân: Duyệt theo thứ tự trước - preorder (Node-Left-Right: NLR)
Duyệt theo thứ tự giữa - inorder (Left-Node-Right: LNR)
Duyệt theo thứ tự sau - postorder (Left-Right-Node: LRN) Tên của 3 kiểu duyệt này được đặt dựa trên trình tự của việc
thăm nút gốc so với việc thăm 2 cây con
Chương 7: Cây (Tree)
Binary Tree - Duyệt cây nhi phân NLR
35
A
B
D
H I
N
E
J K
O
C
F
L
P
G
M
AKết quả: B D H I N E J O K C F L P G M
Chương 7: Cây (Tree)
Binary Tree - Duyệt cây nhi phân
Duyệt theo thứ tự trước NLR (Node-Left-Right)
Kiểu duyệt này trước tiên thăm nút gốc sau đó thăm các nút của
cây con trái rồi đến cây con phai
Thủ tục duyệt có thể trình bày đơn gian như sau:
36
void NLR (Tree t){
if (t != NULL){
// Xư ly t tương ưng theo nhu câu
NLR(t->pLeft);NLR(t->pRight);
}}
Chương 7: Cây (Tree)
Cây nhị phân Duyệt theo thứ tự trước (Node-Left-Right)
Một ví dụ: đọc một quyển sách hay bài báo từ đầu đến cuối như minh họa trong hình bên dưới:
37
Chương 7: Cây (Tree)
Binary Tree - Duyệt cây nhi phân LNR
38
A
B
D
H I
N
E
J K
O
C
F
L
P
G
M
HKết quả: D N I B J O E K A F P L C M G
Chương 7: Cây (Tree)
Binary Tree - Duyệt cây nhi phân
Duyệt theo thứ tự giữa LNR (Left-Node-Right) Kiểu duyệt này trước tiên thăm các nút của cây con trái sau đó
thăm nút gốc rồi đến cây con phai
Thủ tục duyệt có thể trình bày đơn gian như sau:
39
void LNR(Tree t){
if (t != NULL){
LNR(t->pLeft);//Xư ly nut t theo nhu câu
LNR(t->pRight);}
}
Chương 7: Cây (Tree)
Cây nhị phân Duyệt theo thứ tự sau (Left-Right-Node)
Một ví dụ quen thuộc trong tin học về ứng dụng của duyệt theo thứ tự sau là việc xác định tồng kích thước của một thư mục trên đĩa
40
Chương 7: Cây (Tree)
Binary Tree - Duyệt cây nhi phân LRN
41
A
B
D
H I
N
E
J K
O
C
F
L
P
G
M
HKết quả: N I D O J K E B P L F M G C A
Chương 7: Cây (Tree)
Binary Tree - Duyệt cây nhi phân
Duyệt theo thứ tự sau LRN (Left-Right-Node) Kiểu duyệt này trước tiên thăm các nút của cây con trái sau đó
thăm đến cây con phai rồi cuối cùng mới thăm nút gốc
Thủ tục duyệt có thể trình bày đơn gian như sau:
42
void LRN(Tree t){
if (t != NULL){
LRN(t->pLeft);LRN(t->pRight);// Xư ly tương ưng t theo nhu câu
}}
Chương 7: Cây (Tree)
(3 + 1)3/(9 – 5 + 2) – (3(7 – 4) + 6) = –13
43
Tính toán giá trị của biểu thức dựa trên cây biểu thức: duyệt cây theo thứ tự giữa:
Binary Tree - Duyệt cây nhi phân LRN
Chương 7: Cây (Tree)
Binary Tree – Ứng dụng
Tính toán giá trị của biểu thức dựa trên cây biểu thức: duyệt cây theo thứ tự giữa:
44
Chương 7: Cây (Tree)
Trắc nghiệm
Give the binary tree with root A. The root has left child B and right child C. B has left child D and right child E. There are no other nodes in the tree.
Which of the following traversals yields ABCDE?
a) Inorder
b) Preorder
c) All of the others answers
d) None of the others answers
45
Chương 7: Cây (Tree)
Trắc nghiệm
The order in which the nodes of this tree would be visited by a post-order traversal is
46
a) GCMBEJQDFKY
b) BCDFEJKYQMG
c) GCBEDFMJKQY
d) BDFECKJYQMG
Chương 7: Cây (Tree)
Trắc nghiệm
The order in which the nodes of this tree would be visited by a pre-order traversal is
47
a) GCMBEJQDFKYb) BCDFEJKYQMGc) BCDEFGKJMYQd) GCBEDFMJKQY
Chương 7: Cây (Tree)
Cây nhị phân Biểu diễn cây tổng quát bằng cây nhị phân
Nhược điểm của các cấu trúc cây tổng quát: Bậc của các nút trên cây có thể dao động trong một biên độ
lớn việc biểu diễn gặp nhiều khó khăn và lãng phí. Việc xây dựng các thao tác trên cây tổng quát phức tạp hơn
trên cây nhị phân nhiều. Vì vậy, thường nếu không quá cần thiết phai sử dụng cây
tổng quát, người ta chuyển cây tổng quát thành cây nhị phân.
48
Chương 7: Cây (Tree)
Cây nhị phân Biểu diễn cây tổng quát bằng cây nhị phân
Ta có thể biến đổi một cây bất kỳ thành một cây nhị phân theo qui tắc sau: Giữ lại nút con trái nhất làm nút con trái. Các nút con còn lại chuyển thành nút con phai. Như vậy, trong cây nhị phân mới, con trái thể hiện quan hệ
cha con và con phai thể hiện quan hệ anh em trong cây tổng quát ban đầu.
49
Chương 7: Cây (Tree)
Cây nhị phân Biểu diễn cây tổng quát bằng cây nhị phân
Gia sử có cây tổng quát như hình bên dưới:
50
A
B C D
E F G H I J
Cây nhị phân tương ứng sẽ như sau: A
B
C
D
E
F
G
H
I
J
Chương 7: Cây (Tree)
Một cách biểu diễn cây nhi phân khác
51
Đôi khi, khi định nghĩa cây nhị phân, người ta quan tâm đến ca quan hệ 2 chiều cha con chứ không chỉ một chiều như định nghĩa ở phần trên.
Lúc đó, cấu trúc cây nhị phân có thể định nghĩa lại như sau: struct TNODE {DataType Key;TNODE* pParent;TNODE* pLeft;TNODE* pRight;
};typedef TNODE* TREE;
Chương 7: Cây (Tree)
Một số thao tác trên cây
Đếm số node Đếm số node lá Tính chiều cao ...
53
Chương 7: Cây (Tree)
Đếm số node
54
Chương 7: Cây (Tree)
Đếm số node
Thuật toán: Nếu Tree rỗng, Số node (Tree) = 0 Ngược lại, Số node (Tree) = 1 + Số node (Tree.Left) + Số node
(Tree.Right)
55
Chương 7: Cây (Tree)
Đếm số node lá
56
Chương 7: Cây (Tree)
Đếm số node lá
Thuật toán: Nếu Tree rỗng, Số nút lá (Tree) = 0 Nếu Tree là nút lá, Số nút lá (Tree) = 1 + Số nút lá (Tree.Left) +
Số nút lá (Tree.Right) Nếu Tree không là nút lá, Số nút lá (Tree) = Số nút lá
(Tree.Left) + Số nút lá (Tree.Right)
57
Chương 7: Cây (Tree)
Tính chiều cao
58
Chương 7: Cây (Tree)
Tính chiều cao
Thuật toán: Nếu Tree rỗng, Height(Tree) = 0 Ngược lại, Height(Tree) = 1 + max(Height(Tree.Left),
Height(Tree.Right))
59
Chương 7: Cây (Tree)
Nội dung60
Cấu trúc cây (Tree) Cấu trúc cây nhị phân (Binary Tree) Cấu trúc cây nhị phân tìm kiếm (Binary Search Tree) Cấu trúc cây nhị phân tìm kiếm cân bằng (AVL Tree)
Chương 7: Cây (Tree)
Binary Search Tree
Trong chương 6, chúng ta đã làm quen với một số cấu trúc dữ liệu động. Các cấu trúc này có sự mềm dẻo nhưng lại bị hạn chế trong việc tìm kiếm thông tin trên chúng (chỉ có thể tìm kiếm tuần tự)
Nhu cầu tìm kiếm là rất quan trọng. Vì lý do này, người ta đã đưa ra cấu trúc cây để thỏa mãn nhu cầu trên
Tuy nhiên, nếu chỉ với cấu trúc cây nhị phân đã định nghĩa ở trên, việc tìm kiếm còn rất mơ hồ
Cần có thêm một số ràng buộc để cấu trúc cây trở nên chặt chẽ, dễ dùng hơn
Một cấu trúc như vậy chính là cây nhị phân tìm kiếm
Chương 7: Cây (Tree)
Binary Search Tree - Đinh nghia
Cây nhị phân tìm kiếm (CNPTK) là cây nhị phân trong đó tại mỗi nút, khóa của nút đang xét lớn hơn khóa của tất ca các nút thuộc cây con trái và nhỏ hơn khóa của tất ca các nút thuộc cây con phai
Nhờ ràng buộc về khóa trên CNPTK, việc tìm kiếm trở nên có định hướng
Nếu số nút trên cây là N thì chi phí tìm kiếm trung bình chỉ khoang log2N
Trong thực tế, khi xét đến cây nhị phân chủ yếu người ta xét CNPTK
62
Chương 7: Cây (Tree)
Binary Search Tree – Ví dụ63
4444
1818 8888
1313 3737 5959 108108
1515 2323 4040 5555 7171
Chương 7: Cây (Tree)
64
Binary Search Tree – Ví dụ
Chương 7: Cây (Tree)
65
Binary Search Tree – Ví dụ
Chương 7: Cây (Tree)
Tạo cây nhị phân tìm kiếm
Caáu truùc Döõ lieäu - Caáu truùc caây
66
25
10
3
1 6
5
18
12 20
13
37
29
35
32
50
41
25 37 10 18 29 50 3 1 6 5 12 20 35 13 32 41
25 37 10 18 29 50 3 1 6 5 12 20 35 13 32 41
Chương 7: Cây (Tree)
Binary Search Tree – Biểu diễn67
Cấu trúc dữ liệu của CNPTK là cấu trúc dữ liệu biểu diễn cây nhị phân nói chung
Thao tác duyệt cây trên CNPTK hoàn toàn giống như trên cây nhị phân Chú ý: khi duyệt theo thứ tự giữa, trình tự các nút duyệt qua sẽ
cho ta một dãy các nút theo thứ tự tăng dần của khóa
struct TNode{
DataType data; TNode *pLeft,
*pRight;};typedef TNode* Tree; Tree Root ;
Chương 7: Cây (Tree)
Binary Search Tree – Duyệt cây68
25
10
3
1 6
5
18
12 20
13
37
29
35
32
50
41
Duyệt inorder: 1 3 5 6 10 12 13 18 20 25 29 32 35 37 41 50
Duyệt giữa (LNR) trên CNPTK
Chương 7: Cây (Tree)
Binary Search Tree – Duyệt cây69
25
10
3
1 6
5
18
12 20
13
37
29
35
32
50
41
Duyệt postorder: 1 5 6 3 13 12 20 18 10 32 35 29 41 50 37 25
Duyệt sau (LRN) trên CNPTK
Chương 7: Cây (Tree)
Binary Search Tree – Duyệt cây70
25
10
3
1 6
5
18
12 20
13
37
29
35
32
50
41
Duyệt preorder: 25 10 3 1 6 5 18 12 13 20 37 29 35 32 50 41
Duyệt trước (NLR) trên CNPTK
Chương 7: Cây (Tree)
Binary Search Tree – Tìm kiếm71
25
10
3
1 6
5
18
12 20
13
37
29
35
32
50
41
Tìm kiếm 13
Khác nhauGiống nhauNode gốc nhỏ hơnNode gốc lớn hơn
Tim thấySố node duyệt: 5
Tim kiếm trên CNPTK
Chương 7: Cây (Tree)
Binary Search Tree – Tìm kiếm72
25
10
3
1 6
5
18
12 20
13
37
29
35
32
50
41
Tìm kiếm 14
Khác nhauNode gốc nhỏ hơnNode gốc lớn hơn
Không tim thấySố node duyệt: 5
Tim kiếm trên CNPTK
Chương 7: Cây (Tree)
Binary Search Tree – Tìm kiếm
Tìm một phần tử x trong CNPTK (dùng đệ quy):
73
TNode* searchNode(Tree T, DataType X){
if (T){
if(T->data ==X)return T;
if(T->data >X)return searchNode(T->pLeft,
X);return searchNode(T->pRight, X);
}return NULL;
}
Chương 7: Cây (Tree)
Binary Search Tree – Tìm kiếm
Tìm một phần tử x trong CNPTK (dùng vòng lặp):
74
TNode* searchNode(Tree T, DataType x){
TNode *p = T;while (p != NULL){
if(x == p->data) return p;else if(x < p->data) p = p-
>pLeft;else p = p->pRight;
}return NULL;
}
Chương 7: Cây (Tree)
Binary Search Tree – Tìm kiếm75
Nhận xét: Số lần so sánh tối đa phai thực hiện để tìm phần tử X là h,
với h là chiều cao của cây Như vậy thao tác tìm kiếm trên CNPTK có n nút tốn chi
phí trung bình khoang O(log2n)
Chương 7: Cây (Tree)
Tìm một phần tử x trong cây
76
44
18 88
13 37 59 108
15 23 40 55 71
Tìm X=5544 < X
88 > X
59 > X
Chương 7: Cây (Tree)
Binary Search Tree – Thêm77
Việc thêm một phần tử X vào cây phai bao đam điều kiện ràng buộc của CNPTK
Ta có thể thêm vào nhiều chỗ khác nhau trên cây, nhưng nếu thêm vào một nút ngoài sẽ là tiện lợi nhất do ta có thể thực hiện quá trình tương tự thao tác tìm kiếm
Khi chấm dứt quá trình tìm kiếm cũng chính là lúc tìm được chỗ cần thêm
Cách thực hiện: Tìm vị trí thêm (???) Thực hiện thêm (???)
Chương 7: Cây (Tree)
Binary Search Tree – Thêm
Thêm một phần tử vào cây:
78
int insertNode (Tree &T, DataType X){if (T) {
if (T->data == X) return 0; if (T->data > X)
return insertNode(T->pLeft, X); else
return insertNode(T->pRight, X);}
T = new TNode;if (T == NULL) { cout<<“Khong du bo nho”; return -1; }T->data = X;T->pLeft = T->pRight = NULL;return 1; }
–1 : khi không đủ bộ nhớ0 : khi nút đã có1 : khi thêm thành công
Chương 7: Cây (Tree)
Thêm một phần tử x vào cây
79
44
18 88
13 37 59 108
15 23 40 55 71
Theâm X=50
44 < X
88 > X
59 > X
50
55 > X
Chương 7: Cây (Tree)
80
6
4
1
2 5 7
3
Binary Search Tree – Thêm
Ví dụ tạo cây với dãy:
4, 6, 1, 2, 5, 7, 3
Chương 7: Cây (Tree)
Binary Search Tree – Thêm81
30
12 49
51
17
22
56
70
68
65
Ví dụ tạo cây với dãy::
30, 12, 17, 49, 22, 65, 51, 56, 70, 68
Chương 7: Cây (Tree)
Trắc nghiệm
The following items are inserted into a binary search tree: 3,6,5,2,4,7,1.
Which node is the deepest?
a) 1
b) 7
c) 3
d) 4
82
Chương 7: Cây (Tree)
Bài tập
Viết các hàm: Đếm số nút trên cây: CountNode Đếm số nút lá: CountLeaf Đếm số nút trong: CountInnerNode Xác định độ sâu/chiều cao của cây Tìm giá trị nhỏ nhất/lớn nhất trên cây Tính tổng các giá trị trên cây Đếm số nút có giá trị bằng x Xuất các số nguyên tố trên cây
83
Chương 7: Cây (Tree)
Binary Search Tree – Hủy một phần tử có khóa X
84
Việc hủy một phần tử X ra khỏi cây phai bao đam điều kiện ràng buộc của CNPTK
Có 3 trường hợp khi hủy nút X có thể xay ra: X là nút lá X chỉ có 1 con (trái hoặc phai) X có đủ ca 2 con
Chương 7: Cây (Tree)
Binary Search Tree – Hủy một phần tử có khóa X
85
Trường hợp 1: X là nút lá Chỉ đơn gian hủy X vì nó không móc nối đến phần tử nào khác
44
18 88
13 37 59 108
15 23 40 55 71
Hủy X=40
Chương 7: Cây (Tree)
23
Binary Search Tree – Hủy một phần tử có khóa X
Trường hợp 2: X chỉ có 1 con (trái hoặc phải) Trước khi hủy X ta móc nối cha của X với con duy nhất của nó
86
44
18 88
13 37 59 108
15 23 55 71
Hủy X=37
Chương 7: Cây (Tree)
Binary Search Tree – Hủy một phần tử có khóa X
Trường hợp 3: X có đủ 2 con: Không thể hủy trực tiếp do X có đủ 2 con Hủy gián tiếp:
Thay vì hủy X, ta sẽ tìm một phần tử thế mạng Y. Phần tử
này có tối đa một con
Thông tin lưu tại Y sẽ được chuyển lên lưu tại X
Sau đó, nút bị hủy thật sự sẽ là Y giống như 2 trường hợp
đầu Vấn đề: chọn Y sao cho khi lưu Y vào vị trí của X, cây vẫn
là CNPTK
87
Chương 7: Cây (Tree)
Binary Search Tree – Hủy một phần tử có khóa X
Cách chọn phần tử thế mạng:
Phần tử nhỏ nhất (trái nhất) trên cây con phải (của nút muốn
xóa)
Phần tử lớn nhất (phai nhất) trên cây con trái (của nút muốn
xóa)
Việc chọn lựa phần tử nào là phần tử thế mạng phụ thuộc vào ý thích của người lập trình
Ở đây, ta sẽ chọn phần tử nhỏ nhất trên cây con phải làm phần tử thế mạng
88
Chương 7: Cây (Tree)
Binary Search Tree – Hủy một phần tử có khóa X
Trường hợp 3: X có đủ 2 con: Khi hủy phần tử X=18 ra khỏi cây:
89
4444
8888
1313 3737 5959 108108
4040 5555 7171
Hủy X=18
3030
2323
1818X
Chọn phần tử nhỏ nhất trên cây con phải phần tử 23 là phần tử thế mạng
2323
Chương 7: Cây (Tree)
Binary Search Tree – Hủy một phần tử có khóa X
90
Xóa 51
Chương 7: Cây (Tree)
Binary Search Tree – Hủy một phần tử có khóa X
91
Xóa 83
Chương 7: Cây (Tree)
Binary Search Tree – Hủy một phần tử có khóa X
92
Xóa 36
Chương 7: Cây (Tree)
Binary Search Tree – Hủy một phần tử có khóa X
93
Xóa nút gốc:
Chương 7: Cây (Tree)
Binary Search Tree – Hủy một phần tử có khóa X
94
Xóa nút gốc: 42 là thế mạng
Chương 7: Cây (Tree)
Binary Search Tree – Hủy một phần tử có khóa X
95
Kết qua xóa:
Chương 7: Cây (Tree)
Binary Search Tree – Hủy một phần tử có khóa X
96
Xóa gốc 42
Chương 7: Cây (Tree)
Binary Search Tree – Hủy một phần tử có khóa X
Xóa gốc 42 45 thế mạng
97
Chương 7: Cây (Tree)
Binary Search Tree – Hủy một phần tử có khóa X
98
Kết qua xóa:
Chương 7: Cây (Tree)
Binary Search Tree – Hủy một phần tử có khóa X
Các hàm dùng để hủy 1 phần tử:
Hàm delNode tra về giá trị 1, 0 khi hủy thành công hoặc không
có X trong cây:
int delNode (Tree &T, DataType X)
Hàm searchStandFor tìm phần tử thế mạng q và gán dữ liệu của
q cho nút muốn xóa p
void searchStandFor(Tree &p, Tree &q)
99
Chương 7: Cây (Tree)
100
Binary Search Tree – Hủy một phần tử có khóa X
Hủy một nútint delNode(Tree &T, DataType X)
{
if (T == NULL) return 0;
if (T->data > X) return delNode(T->pLeft, X);
if (T->data < X) return delNode(T->pRight, X);
TNode* p = T;
if (T->pLeft == NULL) T = T->pRight;
else if (T->pRight == NULL) T = T->pLeft;
else // T có đủ 2 con
searchStandFor(p, T->pRight);
delete p;
}
Chương 7: Cây (Tree)
Binary Search Tree – Hủy một phần tử có khóa X
Tìm phần tử thế mạng (nhỏ nhất trên cây con phải):
101
void searchStandFor(Tree &p, Tree &q){
if (q->pLeft != NULL)searchStandFor (p, q->pLeft);
else{
p->data = q->data; p = q; q = q->pRight;}
}
Chương 7: Cây (Tree)
Binary Search Tree – Hủy toàn bộ cây
Việc toàn bộ cây có thể được thực hiện thông qua thao tác duyệt cây theo thứ tự sau. Nghĩa là ta sẽ hủy cây con trái, cây con phai rồi mới hủy nút gốc
102
void removeTree(Tree &T){
if (T){
removeTree(T->pLeft); removeTree(T->pRight); delete(T);
}}
Chương 7: Cây (Tree)
Binary Search Tree103
Nhận xét: Tất ca các thao tác searchNode, insertNode, delNode đều
có độ phức tạp trung bình O(h), với h là chiều cao của cây Trong trong trường hợp tốt nhất, CNPTK có n nút sẽ có
độ cao h = log2(n). Chi phí tìm kiếm khi đó sẽ tương
đương tìm kiếm nhị phân trên mang có thứ tự Trong trường hợp xấu nhất, cây có thể bị suy biến thành 1
danh sách liên kết (khi mà mỗi nút đều chỉ có 1 con trừ nút lá). Lúc đó các thao tác trên sẽ có độ phức tạp O(n)
Vì vậy cần có cai tiến cấu trúc của CNPTK để đạt được chi phí cho các thao tác là log2(n)
Chương 7: Cây (Tree)
Đánh giá tìm kiếm104
Chương 7: Cây (Tree)
Đánh giá tìm kiếm105
1, 2, 3, 4, 51
2
3
4
5
Chương 7: Cây (Tree)
Bài tập
Viết các hàm: Đếm số nút có đúng 1 con Đếm số nút có đúng 2 con Đếm số nguyên tố trên cây Tính tổng các nút có đúng 1 con Tính tổng các nút có đúng 2 con Tính tổng các số chẵn Nhập x, tìm giá trị nhỏ nhất trên cây mà lớn hơn x Xuất số nguyên tố nhỏ nhất trên cây Nhập x, tìm x trên cây, nếu tìm thấy x thì cho biết x có bao
nhiêu con Xóa 1 nút
106
Chương 7: Cây (Tree)
Nội dung107
Cấu trúc cây (Tree) Cấu trúc cây nhị phân (Binary Tree) Cấu trúc cây nhị phân tìm kiếm (Binary Search Tree) Cấu trúc cây nhị phân tìm kiếm cân bằng (AVL Tree)
Chương 7: Cây (Tree)
Giới thiệu AVL Tree
Phương pháp chèn trên CNPTK có thể có những biến dạng mất cân đối nghiêm trọng Chi phí cho việc tìm kiếm trong trường hợp xấu nhất đạt tới n VD: 1 triệu nút ⇒ chi phí tìm kiếm = 1.000.000 nút
Nếu có một cây tìm kiếm nhị phân cân bằng hoàn toàn, chi phí cho việc tìm kiếm chỉ xấp xỉ log2n VD: 1 triệu nút ⇒ chi phí tìm kiếm = log21.000.000 ≈ 20 nút
G.M. Adelson-Velsky và E.M. Landis đã đề xuất một tiêu chuẩn cân bằng (sau này gọi là cân bằng AVL) Cây AVL có chiều cao O(log2(n))
108
Chương 7: Cây (Tree)
AVL Tree - Đinh nghia109
Cây nhị phân tìm kiếm cân bằng (AVL) là cây mà tại mỗi nút độ cao của cây con trái và của cây con phai chênh lệch không quá một 44
23 88
13 37 59 108
15 30 40 55 71
Chương 7: Cây (Tree)
AVL Tree
Chỉ số cân bằng của một nút: Định nghĩa: Chỉ số cân bằng của một nút là hiệu của chiều cao
cây con phai và cây con trái của nó Đối với một cây cân bằng, chỉ số cân bằng (CSCB) của mỗi nút
chỉ có thể mang một trong ba giá trị sau đây: CSCB(p) = 0 Độ cao cây phai (p) = Độ cao cây trái (p) CSCB(p) = 1 Độ cao cây phai (p) > Độ cao cây trái (p) CSCB(p) = -1 Độ cao cây phai (p) < Độ cao cây trái (p)
110
Chương 7: Cây (Tree)
Ví dụ - Chỉ số cân bằng của nút
•What is the balance factor for each node in this AVL tree?•Is this an AVL tree?
1
-1
0
0 0
0
-1
-1
1 0
1
0
0
10
40
30 45
20 35
25
60
7
3 8
1 5
Chương 7: Cây (Tree)
AVL Tree – Ví dụ112
AVL Tree ? AVL Tree?
Chương 7: Cây (Tree)
AVL Tree – Ví dụ113
Chương 7: Cây (Tree)
AVL Tree – Biểu diễn114
#define RH 1 /* Cây con phải cao hơn */#define EH 0 /* Hai cây con bằng nhau */#define LH -1 /* Cây con trái cao hơn */
struct AVLNode{char balFactor; // Chỉ số cân bằngDataType data;AVLNode* pLeft;AVLNode* pRight;
};typedef AVLNode* AVLTree;
Chương 7: Cây (Tree)
AVL Tree – Biểu diễn115
Các thao tác đặc trưng của cây AVL: Thêm một phần tử vào cây AVL
Hủy một phần tử trên cây AVL
Cân bằng lại một cây vừa bị mất cân bằng (Rotation)
Trường hợp thêm một phần tử trên cây AVL được thực hiện giống như thêm trên CNPTK, tuy nhiên sau khi thêm phai cân bằng lại cây
Trường hợp hủy một phần tử trên cây AVL được thực hiện giống như hủy trên CNPTK và cũng phai cân bằng lại cây
Việc cân bằng lại một cây sẽ phai thực hiện sao cho chỉ anh hưởng tối thiểu đến cây nhằm giam thiểu chi phí cân bằng
Chương 7: Cây (Tree)
AVL Tree - Các trường hợp mất cân bằng
Ta sẽ không khao sát tính cân bằng của 1 cây nhị phân bất kỳ mà chỉ quan tâm đến các kha năng mất cân bằng xay ra khi chèn hoặc xóa một nút trên cây AVL
Các trường hợp mất cân bằng: Sau khi chèn (xóa) cây con trái lệch trái (left of left) Sau khi chèn (xóa) cây con trái lệch phai (right of left) Sau khi chèn (xóa) cây con phai lệch phai (right of right) Sau khi chèn (xóa) cây con phai lệch trái (left of right)
116
Chương 7: Cây (Tree)
Ví dụ: Các trường hợp mất cân bằng
Chương 7: Cây (Tree)
Ví dụ: Các trường hợp mất cân bằng
Chương 7: Cây (Tree)
AVL Tree - Các trường hợp mất cân bằng
Chèn nút vào cây AVL
1 và 4 là các anh đối xứng 2 và 3 là các anh đối xứng
1 2 3 4
Chương 7: Cây (Tree)
Cây AVL – Tái cân bằng
Trường hợp 1 được giai bởi phép quay:
Trường hợp 4 là quay một anh đối xứng
Chương 7: Cây (Tree)
Cây AVL – Tái cân bằng
Trường hợp 2 cần một phép quay kép (double)
Trường hợp 3 là phép quay anh đối xứng
Chương 7: Cây (Tree)
Ví dụ: Tái cân bằng126
1. left of left
Chương 7: Cây (Tree)
127
Ví dụ: Tái cân bằng
2. right of left
Chương 7: Cây (Tree)
128
Ví dụ: Tái cân bằng
3. right of right
Chương 7: Cây (Tree)
129
Ví dụ: Tái cân bằng
4. left of right
Chương 7: Cây (Tree)
AVL Tree - Cân bằng lại cây AVL130
void rotateLL(AVLTree &T) //quay đơn Left-Left{
AVLNode* T1 = T->pLeft;T->pLeft = T1->pRight;T1->pRight = T;switch(T1->balFactor) {case LH: T->balFactor = EH;
T1->balFactor = EH; break;
case EH: T->balFactor = LH; T1->balFactor = RH; break;
}T = T1;
}
Quay đơn Left-Left:
Chương 7: Cây (Tree)
AVL Tree - Cân bằng lại cây AVL131
Quay đơn Right-Right:void rotateRR (AVLTree &T) //quay đơn Right-Right{
AVLNode* T1 = T->pRight;T->pRight = T1->pLeft;T1->pLeft = T;switch(T1->balFactor) {case RH: T->balFactor = EH;
T1->balFactor= EH; break;
case EH: T->balFactor = RH; T1->balFactor= LH;
break;}T = T1;
}
Chương 7: Cây (Tree)
AVL Tree - Cân bằng lại cây AVL132
Quay kép Left-Right:
void rotateLR(AVLTree &T)//quay kép Left-Right{ AVLNode* T1 = T->pLeft;
AVLNode* T2 = T1->pRight;T->pLeft = T2->pRight;T2->pRight = T;T1->pRight = T2->pLeft;T2->pLeft = T1;switch(T2->balFactor) {
case LH: T->balFactor = RH; T1->balFactor = EH; break; case EH: T->balFactor = EH; T1->balFactor = EH; break;
case RH: T->balFactor = EH; T1->balFactor = LH; break;}T2->balFactor = EH;T = T2;
}
Chương 7: Cây (Tree)
AVL Tree - Cân bằng lại cây AVL133
Quay keùp Right-Left
void rotateRL(AVLTree &T) //quay kép Right-Left{ AVLNode* T1 = T->pRight;
AVLNode* T2 = T1->pLeft;T->pRight = T2->pLeft;T2->pLeft = T;T1->pLeft = T2->pRight;T2->pRight = T1;switch(T2->balFactor) {
case RH: T->balFactor = LH; T1->balFactor = EH; break; case EH: T->balFactor = EH; T1->balFactor = EH; break; case LH: T->balFactor = EH; T1->balFactor = RH; break;}T2->balFactor = EH;T = T2;
}
Chương 7: Cây (Tree)
AVL Tree - Cân bằng lại cây AVL134
Cân bằng khi cây bị lêch về bên trái:
int balanceLeft(AVLTree &T)//Cân bằng khi cây bị lêch về bên trái {
AVLNode* T1 = T->pLeft;
switch(T1->balFactor) {case LH: rotateLL(T); return 2;case EH: rotateLL(T); return 1;case RH: rotateLR(T); return 2;}return 0;
}
Chương 7: Cây (Tree)
AVL Tree - Cân bằng lại cây AVL135
Cân bằng khi cây bị lêch về bên phai
int balanceRight(AVLTree &T )//Cân bằng khi cây bị lêch về bên phải{
AVLNode* T1 = T->pRight;
switch(T1->balFactor) {case LH: rotateRL(T); return 2;case EH: rotateRR(T); return 1;case RH: rotateRR(T); return 2;}return 0;
}
Chương 7: Cây (Tree)
AVL Tree - Thêm một phần tử trên cây AVL
Việc thêm một phần tử vào cây AVL diễn ra tương tự như trên CNPTK
Sau khi thêm xong, nếu chiều cao của cây thay đổi, từ vị trí thêm vào, ta phai lần ngược lên gốc để kiểm tra xem có nút nào bị mất cân bằng không. Nếu có, ta phai cân bằng lại ở nút này
Việc cân bằng lại chỉ cần thực hiện 1 lần tại nơi mất cân bằng Hàm insertNode tra về giá trị –1, 0, 1 khi không đủ bộ nhớ, gặp
nút cũ hay thành công. Nếu sau khi thêm, chiều cao cây bị tăng, giá trị 2 sẽ được tra về
int insertNode(AVLTree &T, DataType X)
136
Chương 7: Cây (Tree)
AVL Tree - Thêm một phần tử trên cây AVL
int insertNode(AVLTree &T, DataType X)
{ int res;
if (T)
{ if (T->key == X) return 0; //đã có
if (T->key > X)
{ res = insertNode(T->pLeft, X);
if(res < 2) return res;
switch(T->balFactor)
{ case RH: T->balFactor = EH; return 1;
case EH: T->balFactor = LH; return 2;
case LH: balanceLeft(T); return 1;
}
}
......................................................
}
137
insertNode2
Chương 7: Cây (Tree)
AVL Tree - Thêm một phần tử trên cây AVL
int insertNode(AVLTree &T, DataType X)
{
......................................................
else // T->key < X
{ res = insertNode(T-> pRight, X);
if(res < 2) return res;
switch(T->balFactor)
{ case LH: T->balFactor = EH; return 1;
case EH: T->balFactor = RH; return 2;
case RH: balanceRight(T); return 1;
}
}
......................................................
}
138
insertNode3
Chương 7: Cây (Tree)
AVL Tree - Thêm một phần tử trên cây AVL
int insertNode(AVLTree &T, DataType X){......................................................T = new TNode;if(T == NULL) return -1; //thiếu bộ nhớT->key = X; T->balFactor = EH;T->pLeft = T->pRight = NULL;return 2; // thành công, chiều cao tăng
}
139
Chương 7: Cây (Tree)
AVL Tree - Hủy một phần tử trên cây AVL
Cũng giống như thao tác thêm một nút, việc hủy một phần tử X ra khỏi cây AVL thực hiện giống như trên CNPTK
Sau khi hủy, nếu tính cân bằng của cây bị vi phạm ta sẽ thực hiện việc cân bằng lại
Tuy nhiên việc cân bằng lại trong thao tác hủy sẽ phức tạp hơn nhiều do có thể xay ra phan ứng dây chuyền
Hàm delNode tra về giá trị 1, 0 khi hủy thành công hoặc không có X trong cây. Nếu sau khi hủy, chiều cao cây bị giam, giá trị 2 sẽ được tra về:
int delNode(AVLTree &T, DataType X)
140
Chương 7: Cây (Tree)
AVL Tree - Hủy một phần tử trên cây AVL
int delNode(AVLTree &T, DataType X)
{ int res;
if(T==NULL) return 0;
if(T->key > X)
{ res = delNode (T->pLeft, X);
if(res < 2) return res;
switch(T->balFactor)
{ case LH: T->balFactor = EH; return 2;
case EH: T->balFactor = RH; return 1;
case RH: return balanceRight(T);
}
} // if(T->key > X)
......................................................
}
141
delNode2
Chương 7: Cây (Tree)
AVL Tree - Hủy một phần tử trên cây AVL
int delNode(AVLTree &T, DataType X)
{
......................................................
if(T->key < X)
{ res = delNode (T->pRight, X);
if(res < 2) return res;
switch(T->balFactor)
{ case RH: T->balFactor = EH; return 2;
case EH: T->balFactor = LH; return 1;
case LH: return balanceLeft(T);
}
} // if(T->key < X)
......................................................
}
142
delNode3
Chương 7: Cây (Tree)
AVL Tree - Hủy một phần tử trên cây AVL
int delNode(AVLTree &T, DataType X)
{......................................................
else //T->key == X
{ AVLNode* p = T;
if(T->pLeft == NULL) { T = T->pRight; res = 2; }
else if(T->pRight == NULL) { T = T->pLeft; res = 2; }
else //T có đủ cả 2 con
{ res = searchStandFor(p,T->pRight);
if(res < 2) return res;
switch(T->balFactor)
{ case RH: T->balFactor = EH; return 2;
case EH: T->balFactor = LH; return 1;
case LH: return balanceLeft(T);
}
}
delete p; return res;
}
}
143
Chương 7: Cây (Tree)
AVL Tree - Hủy một phần tử trên cây AVL
int searchStandFor(AVLTree &p, AVLTree &q)
//Tìm phần tử thế mạng
{ int res;
if(q->pLeft)
{ res = searchStandFor(p, q->pLeft);
if(res < 2) return res;
switch(q->balFactor)
{ case LH: q->balFactor = EH; return 2;
case EH: q->balFactor = RH; return 1;
case RH: return balanceRight(T);
}
} else
{ p->key = q->key; p = q; q = q->pRight; return 2;
}
}
144
top related