Bài giảng Cấu trúc dữ liệu và thuật toán - Phần 1: Giới thiệu về thuật toán - Chương 4, Phần 2: Tìm kiếm - Nguyễn Duy Hiệp

3/24/2011  
Chương 4.  
Tìm kiếm (tiếp)  
Cây tìm kiếm nhị phân cân bằng  
AVL Tree  
G. M. ADELSON‐VELSKII và E. M. LANDIS  
Tìm kiếm  
AVL tree  
Cây tìm kiếm nhị phân cân bằng – AVL tree:  
Là cây tìm kiếm nhị phân  
Chiều cao của cây con trái và cây con phải của gốc chênh nhau  
không quá 1  
Cây con trái và cây con phải cũng là các cây AVL  
Đặc điểm của cấu trúc cây tìm kiếm nhị phân  
Kiểu cấu trúc liên kết  
Thao tác tìm kiếm, thêm, xóa thực hiện dễ dàng  
Thời gian thực hiện các thao tác trong trường hợp tốt nhất  
ꢀꢁlog ꢂꢃ, tồi nhất ꢀꢁꢂꢃ  
12  
12  
12  
Trường hợp tồi khi cây bị suy biến  
Cây cân bằng cho thời gian thực hiện tốt nhất  
21  
9
21  
9
21  
Cải tiến cấu trúc cây tìm kiếm nhị phân để  
luôn thu được thời gian thực hiện tối ưu  
5
10  
15  
30  
1
3/24/2011  
AVL tree  
AVL tree  
Quản lý trạng thái cân bằng của cây  
Thêm các nút 3, 2, 1, 4, 5, 6, 7 vào cây AVL ban đầu rỗng  
Mỗi nút đưa thêm 1 thông tin là hệ số cân bằng (balance  
factor) có thể nhận 3 giá trị  
Xoay phải  
3
3
‐2  
3
2
Left_higher (hoặc ‐1)  
Equal_height (hoặc 0)  
Right_higher (hoặc +1)  
‐1  
2
2
1
3
12  
1
Thêm 3  
Thêm 2  
Vi phạm tính  
chất của cây  
AVL  
0
1
Hai thao tác làm thay đổi  
hệ số cân bằng của nút:  
Thêm nút  
9
21  
0
‐1  
Thêm 1  
15  
Xóa nút  
0
Xử lý bằng phép xoay nút  
AVL tree  
AVL tree  
2
Khai báo cấu trúc 1 nút cây AVL  
2
2
2
Xoay trái  
2
enum Balance_factor { left_higher, equal_height, right_higher };  
1
3
1
0
3
1
4
typedef struct AVLNode  
{
1
4
4
3
5
int data;  
Vi phạm  
Thêm 4  
Balance_factor balance;  
struct TreeNode *leftChild;  
struct TreeNode *rightChild;  
} AVLNODE;  
0
Thêm 5  
5
Xoay giữa nút vi phạm và nút con của nó  
2
3/24/2011  
AVL tree  
AVL tree  
Xoay phải  
Xoay trái  
K1  
K2  
Vi phạm  
2
K1  
2
4
K2  
X
Z
X
Y
Y
1
4
1
Z
5
2
Xoay trái  
3
5
1
3
6
1
K2  
K1  
K1  
6
K2  
0
Thêm 6  
X
Z
X
Y
Y
Z
AVL tree  
AVL tree  
Phép xoay đơn – single rotation:  
Dùng để điều chỉnh khi mà nút mới thêm vào trong  
trường hợp:  
4
4
Vi phạm  
5
2
(i) Cây con trái của nút con trái, hoặc  
6
2
(ii)Cây con phải của nút con phải của nút  
3
6
1
Thực hiện tại nút vi phạm đầu tiên trên đường từ vị trí  
mới thêm trở về gốc  
3
5
1
7
Xoay giữa nút vi phạm và nút con trái (xoay phải) – TH i)  
(hoặc con phải (xoay trái)– TH ii)  
7
Thêm 7  
Sau khi xoay các nút trở nên cân bằng  
3
3/24/2011  
AVL tree  
AVL tree  
Thực hiện thêm tiếp các khóa 16, 15, 14, 13, 12, 11, 10, 8, 9  
vào cây  
2
4
4
Vi phạm  
2
4
Nút vi phạm  
đầu tiên  
2
6
2
7
2
2
6
2
5
3
1
6
3
1
15  
‐1  
15  
3
5
2
1
7
‐2  
16  
1
7
16  
5
14  
16  
Vẫn vi phạm  
Thêm 16  
1
16  
‐1  
7
14  
Thêm 14  
15  
15  
0
Thêm 15  
0
AVL tree  
AVL tree  
K1  
K1  
4
4
K2  
K2  
X
X
6
6
2
2
K3  
Y
Z
Y
Z1’  
Z2’  
3
5
3
5
1
7
1
15  
K1  
K1  
Hai trường hợp áp  
dụng xoay kép  
2. Xoay trái  
16  
7
16  
K2  
K2  
X
1. Xoay phải  
15  
X
K3  
Thêm 15  
Y
Z
Y
Z1’  
Z2’  
4
3/24/2011  
AVL tree  
AVL tree  
K1  
K3  
2
2
4
7
K1  
K2  
1
K2  
1
2
7
4
15  
X
K3  
Z1’  
Z2’  
Y
X
Y
‐1  
6
1
3
15  
2
Z1’  
Z2’  
K1  
6
14  
16  
K3  
2
1
3
5
14  
16  
5
13  
K1  
K2  
K2  
1
13  
X
K3  
Thêm 13  
Y
X
Y
Z1’  
Z2’  
Z1’  
Z2’  
AVL tree  
AVL tree  
Phép xoay kép – double rotation:  
7
Dùng để điều chỉnh khi mà nút mới thêm vào trong  
trường hợp:  
(i) Cây con phải của nút con trái, hoặc  
4
15  
(ii)Cây con trái của nút con phải của nút  
2
Thực hiện tại nút vi phạm đầu tiên trên đường từ vị trí  
mới thêm trở về gốc  
6
14  
16  
Xoay giữa nút vi phạm, nút con, và nút cháu (con của nút  
con)  
1
3
5
13  
Xoay kép gồm 2 phép xoay trái và xoay phải  
Số nút trong quá trình thực hiện xoay là 3  
Thêm 12  
5
3/24/2011  
AVL tree  
AVL tree  
Thêm 11  
Thêm 8  
AVL tree  
AVL tree  
Thêm 10  
Thêm 9  
6
3/24/2011  
AVL tree  
AVL tree  
Mỗi phép xoay có 2 trường hợp, khi cài đặt sẽ phải có 4  
trường hợp  
Trái – trái (xoay đơn)  
void rotate_right(AVLNODE *&root)  
{
if(root==NULL || root‐>leftChild==NULL)  
//error, because it's impossible  
Phải – phải (xoay đơn)  
{
printf("It's must be a mistake when using this function!\n");  
Trái – phải (xoay kép)  
}
else  
{
Phải – trái (xoay kép)  
AVLNODE *pLeft = root‐>leftChild;  
root‐>leftChild = pLeft‐>rightChild;  
pLeft‐>rightChild = root;  
root = pLeft;  
Sau mỗi lần xoay, trạng thái cân bằng lại được xác lập lại  
tại nút vi phạm  
}
}
AVL tree  
AVL tree  
void left_balance(AVLNODE *&root)  
//balance function for insert in left subtree  
{
//2 single rotations  
void rotate_left(AVLNODE *&root)  
{
AVLNODE *pLeft = root‐>leftChild;  
if(pLeft‐>balance == equal_height)  
{
if(root==NULL || root‐>rightChild==NULL)  
//error, because it's impossible  
{
printf("It's must be a mistake when using this function!\n");  
}
else  
printf("It's must be a mistake when using this function!\n");  
}
else if(pLeft‐>balance == left_higher)  
//left‐left case (single rotation)  
{
{
AVLNODE *pRight = root‐>rightChild;  
root‐>rightChild = pRight‐>leftChild;  
pRight‐>leftChild = root;  
root = pRight;  
root‐>balance = equal_height;  
pLeft‐>balance = equal_height;  
rotate_right(root);  
}
else  
}
}
//left‐right case (double rotation:(1)rotate left,(2)rotate right)  
7
3/24/2011  
{
AVLNODE *pLeftRight = root‐>leftChild‐>rightChild;  
if(pLeftRight‐>balance == left_higher)  
{
AVL tree  
Xóa nút khỏi cây:  
Chuyển bài toán xóa nút đầy đủ thành xóa nút có nhiều nhất  
một con.  
Xóa nút có nhiều nhất một con bị xóa làm chiều cao của  
nhánh bị giảm  
pLeft‐>balance = equal_height;  
root‐>balance = right_higher;  
}
else if(pLeftRight‐>balance == equal_height)  
{
pLeft‐>balance = equal_height;  
root‐>balance = equal_height;  
}
else  
{
Căn cứ vào trạng thái cân bằng tại các nút từ nút bị xóa trên  
đường trở về gốc để cân bằng lại cây nếu cần (giống với khi  
thêm một nút mới vào cây)  
pLeft‐>balance = left_higher;  
root‐>balance = equal_height;  
}
pLeftRight‐>balance = equal_height;  
rotate_left(pLeft);  
root‐>leftChild = pLeft;  
rotate_right(root);  
}
}
AVL tree  
AVL tree  
Xóa nút khỏi cây:  
Nếu nút cần xóa là nút đầy đủ: chuyển về xóa nút có nhiều  
nhất 1 nút con  
Thay thế nút cần xóa bằng nút phải nhất trên cây con trái  
hoặc , nút trái nhất trên cây con phải  
Copy các thông số của nút thay thế giống với thông số của  
nút bị xóa thực sự  
Nếu nút bị xóa là nút có 1 con: thay thế nút đó bằng nút gốc  
của cây con  
Chiều cao cây không đổi  
Nếu nút bị xóa là nút lá: gỡ bỏ nút, gán con trỏ của nút cha  
nó bằng NULL  
Trường hợp 1: nút p đang ở trạng thái cân bằng (equal)  
Xóa một nút của cây con trái (hoặc phải) làm cây bị lệch nhưng  
chiều cao không đổi  
8
3/24/2011  
AVL tree  
AVL tree  
Trường hợp 3.1  
Chiều cao cây thay đổi  
Trường hợp 2: nút p đang ở trạng thái lệch trái hoặc phải  
Nút bị xóa là nút của nhánh cao hơn, sau khi xóa cây trở về trạng  
thái cân bằng và chiều cao của cây giảm  
Chiều cao cây không đổi  
AVL tree  
AVL tree  
Trường hợp 3: cây đang bị lệch và nút bị xóa nằm trên nhánh  
thấp hơn.  
Để cân bằng lại cây ta phải thực hiện các phép xoay.  
Căn cứ vào tình trạng cân bằng của nút con còn lại q của p mà  
ta chia thành các trường hợp nhỏ sau:  
Trường hợp 3.2: nút q bị lệch trái (nếu q là con phải của  
p) hoặc lệch phải (nếu q là con trái của p)  
Cân bằng p bằng cách thực hiện phép xoay đơn giữa q và p  
Sau khi xoay p trở về trạng thái cân bằng và chiều cao của p  
bị giảm đi  
Trường hợp 3.1: Nút q đang ở trạng thái cân bằng  
Thực hiện phép xoay đơn (xoay trái hoặc xoay phải)  
Sau khi xoay, p trở về trạng thái cân bằng  
9
3/24/2011  
AVL tree  
AVL tree  
Chiều cao cây thay đổi  
Chiều cao cây thay đổi  
AVL tree  
AVL tree  
Trường hợp 3.3: nút q bị lệch cùng phía với nhánh bị xóa.  
Nếu nhánh bị xóa là nhánh trái của p thì q bị lệch trái và  
ngược lại  
7
4
15  
Để tái cân bằng cho p ta phải thực hiện 2 phép xoay giữa nút  
con của q, nút q, và nút p  
Sau khi xoay, chiều cao của cây giảm đi, p trở về trạng thái cân  
bằng  
2
6
14  
16  
1
3
13  
Xóa một trong các nút 4, 7, 15 trên cây AVL  
10  
3/24/2011  
Cấy trúc tự điều chỉnh  
Trong nhiều bài toán chúng ta cần một cấu trúc xử lý hiệu  
quả với những truy cập có số lượng lớn trên các bản ghi  
mới đưa vào.  
Ví dụ: bài toán quản lý thông tin bệnh nhân tại bệnh viện  
Bệnh nhân ra khỏi bệnh viện thì có số lần truy cập thông tin ít  
hơn  
Question  
Bệnh nhân mới vào viện thì sẽ có số lượng truy cập thông tin  
thường xuyên  
Ta cần cấu trúc mà có thể tự điều chỉnh để đưa những bản ghi  
mới thêm vào ở gần gốc để cho việc truy cập thường xuyên dễ  
dàng.  
Cây splay  
Splay tree  
Là cây tìm kiếm nhị phân  
Mỗi khi truy cập vào một nút trên cây (thêm, hoặc xóa) thì nút  
mới truy nhập sẽ được tự động chuyển thành gốc của cây mới  
Các nút được truy cập thường xuyên sẽ ở gần gốc  
Các nút ít được truy cập sẽ bị đẩy xa dần gốc  
Splay tree  
Cấu trúc tự điều chỉnh  
Để dịch chuyển các nút ta dùng các phép xoay giống với trong  
AVL tree  
Các nút nằm trên đường đi từ gốc đến nút mới truy cập sẽ chịu  
ảnh hưởng của các phép xoay  
11  
3/24/2011  
Cây splay  
Cây splay  
Nhắc lại về các phép xoay  
Trường hợp chỉ dùng phép xoay đơn để điều chỉnh nút  
Xoay đơn – single rotation:  
Nút cha xuống thấp 1 mức và nút con lên 1 mức  
25  
9
21  
6
25  
‐2  
3
2
15  
9
4
21  
18  
‐1  
2
1
3
6
18  
15  
0
1
4
Cây splay  
Cây splay  
Xoay kép – double rotation:  
gồm 2 phép xoay đơn liên tiếp.  
Nút tăng lên 1 mức, còn các nút còn lại lên hoặc giảm xuống  
nhiều nhất 1 mức  
Nhận xét:  
Nút mới truy cập (nút 9) được chuyển thành nút gốc của cây  
mới  
Tuy nhiên nút 18 lại bị đẩu xuống vị trí của nút 9 trước  
Như vậy:  
7
Truy cập tới 1 nút sẽ đẩy các nút khác xuống sâu hơn.  
Tốc độ của nút bị truy cập được cải thiện nhưng không cải  
thiện tốc độ truy cập của các nút khác trên đường truy cập  
15  
16  
Thời gian truy cập với ꢄ nút liên tiếp vẫn là ꢀꢁꢄ ∗ ꢂꢃ  
7
16  
Ý tưởng dùng chỉ phép xoay đơn để biến đổi cây là không đủ  
tốt  
15  
12  
3/24/2011  
Cây splay  
Cây splay  
Ý tưởng mới:  
Tại mỗi bước ta di chuyển nút liền 2 mức  
Xét các nút trên đường đi từ gốc đến nút mới truy nhập  
Nếu ta di chuyển trái (từ gốc xuống), ta gọi là Zig  
Ngược lại, di chuyển phải ta gọi là Zag  
T1  
T4  
21  
21  
21  
21  
21  
21  
T2  
T3  
T3  
T4  
T1  
T2  
15  
15  
15  
27  
27  
27  
Trường hợp Zig‐Zig  
Zag  
Zig  
6
17  
Zig‐Zag  
23  
Zag‐Zig  
34  
Zag‐Zag  
Zig‐Zig  
Cây splay  
Cây splay  
Dịch chuyển:  
Nếu nút đang xét nằm ở mức sâu hơn hoặc bằng 2 ta dịch chuyển  
2 mức mỗi lần  
Nếu nút ở mức 1: ta chỉ dịch chuyển 1 mức (trường hợp Zig hoặc  
Zag)  
T4  
T1  
T4  
T2  
T3  
T3  
T1  
T3  
T1  
T2  
Trường hợp Zag‐Zig  
T1  
T2  
T2  
T3  
Trường hợp Zig  
13  
3/24/2011  
Cây splay  
Cây splay  
Chú ý: trường hợp Zig‐Zig (hoặc Zag‐Zag) khác hoàn toàn với  
trường hợp dùng hai phép xoay đơn liên tiếp  
Nhận xét về cây splay:  
Cây không cân bằng (thường bị lệch)  
Các thao tác có thời gian thực hiện khác nhau từ O(1) tới O(n)  
Thời gian thực hiện trung bình của một thao tác trong một  
chuỗi thao tác là ꢀꢁlog ꢂꢃ  
Thực hiện giống như cây AVL nhưng không cần quản lý thông  
tin về trạng thái cân bằng của các nút  
T1  
T4  
T4  
T3  
Nếu dùng 2 phép xoay đơn  
T2  
T1  
T2  
T3  
Cây splay  
Thực hiện splay tại nút 23  
45  
21  
73  
15  
37  
6
35  
40  
Cây 2‐3  
25  
23  
27  
14  
3/24/2011  
Cây 2‐3  
Cây 2‐3  
Đảm bảo cây luôn luôn cân bằng  
Chi phí thực hiện các thao tác luôn là ꢀꢁlog ꢂꢃ  
Nút trong có 3 con – nút 3  
Nút chứa 2 phần tử  
Có 3 nút con  
Cây 2‐3:  
Mỗi nút trong có 2 tới 3 nút con  
Nút lá có 1 tới 2 giá trị  
p
q
x < p  
x >q  
Dữ liệu được lưu trên nút lá hoặc nút trong  
ĐÂY KHÔNG PHẢI CÂY NHỊ PHÂN  
Trạng thái cân bằng của cây được duy trì dễ dàng hơn so với  
p< x <q  
Giá trị khóa  
tìm kiếm  
nhỏ hơn p  
Giá trị khóa  
tìm kiếm  
lớn hơn q  
Giá trị khóa  
tìm kiếm  
lớn hơn p  
nhỏ hơn q  
cây AVL  
Cây 2‐3  
Cây 2‐3  
Nút trong có 2 con – nút 2  
Nút chứa 1 phần tử  
Có 2 nút con  
34 57  
p
24  
37 45  
42  
59 67  
x < p  
x > p  
12  
27 32  
35  
47 52  
Giá trị khóa  
tìm kiếm  
Giá trị khóa  
tìm kiếm  
nhỏ hơn p  
lớn hơn p  
15  
3/24/2011  
Cây 2‐3  
Cây 2‐3  
Định nghĩa cấu trúc 1 nút  
34 57  
struct TreeNode  
{
24  
37 45  
42  
59 67  
DATA_TYPE smallItem, largeItem;  
struct TreeNode *left, *middle, *right;  
struct TreeNode *parent; //to make your life easier  
}
12  
27 32  
35  
47 52  
Duyệt cây theo thứ tự giữa:  
12, 24, 27, 32, 34, 35, 37, 42, 45, 47, 52, 57, 59, 67  
Cây 2‐3  
Cây 2‐3  
Duyệt cây theo thứ tự giữa – in‐order traversal  
(1) Duyệt cây con trái  
(2) Xử lý nội dung khóa nhỏ hơn tại nút  
(3) Duyệt cây con giữa  
(4) Xử lý nội dung khóa lớn hơn tại nút  
(5) Duyệt cây con phải  
Tìm kiếm  
Nếu nút hiện tại rỗng không tìm thấy  
Nếu giá trị tìm kiếm k xuất hiện trên nút hiện tại tìm thấy  
Nếu k< giá trị khóa nhỏ hơn tìm tiếp tại cây con trái  
Nếu khóa nhỏ hơn< k< khóa lớn hơn tìm tại cây con giữa  
Ngược lại tìm tại cây con phải  
2
4
37 45  
3
5
1
16  
3/24/2011  
Cây 2‐3  
Cây 2‐3  
Thêm 29  
Thêm nút  
24  
24  
Phần tử mới được thêm vào tại nút lá của cây  
Nếu nút lá sau khi thêm có 3 phần tử ta phải thực hiện thao  
tác tách nút  
12  
27 32  
12  
27 29 32  
Khi tách nút, khóa giữa bị đẩy lên nút cha  
Tách nút tại nút lá có thể dẫn đến tách nút tại nút trong  
Tách nút  
24 29  
Tách nút:  
• Khóa ở giữa bị đẩy lên nút  
cha  
• Nút hiện tại bị tách thành 2  
12  
27  
32  
nút con  
Cây 2‐3  
Cây 2‐3  
34 57  
Thêm 19  
24  
24  
24  
37 45  
42  
59 67  
12  
27 32  
12 19  
27 32  
12  
27 32  
35  
47 52  
Không phải tách nút  
Thêm nút 50 ?  
17  
3/24/2011  
Cây 2‐3  
Cây 2‐3  
Thêm nút 50  
Thêm nút 50  
Vi phạm  
34 57  
34 45 57  
24  
37 45  
42  
59 67  
24  
37  
50  
59 67  
12  
27 32  
35  
47 50 52  
12  
27 32  
35  
42  
47  
52  
Vi phạm  
Cây 2‐3  
Cây 2‐3  
45  
Thêm nút 50  
Thêm nút 50  
34  
57  
34 57  
Vi phạm  
24  
37  
50  
59 67  
24  
37 45 50  
59 67  
12  
27 32  
35  
42  
47  
52  
12  
27 32  
35  
42  
47  
52  
Tách tại nút gốc  
18  
3/24/2011  
Cây 2‐3  
Cây 2‐3  
Xóa nút lá  
45  
Nếu nút lá sau khi xóa vẫn còn phần tử kết thúc  
Ngược lại ta phải dịch chuyển phần tử từ nút anh em  
của nó, hoặc từ nút cha của nó  
34  
57  
(i) Nếu nút anh em của nó có 2 phần tử thì dịch một phần  
tử sang nút hiện tại  
(ii) Nếu không thực hiện dịch được thì ta sẽ thực hiện kết  
hợp (điều này có thể dẫn đến giảm chiều cao của cây)  
24  
37  
50  
59 67  
12  
27 32  
35  
42  
47  
52  
Vẽ cây thu được sau khi thêm lần lượt các khóa  
5, 7, 29, 31, 70, 75 vào cây trên  
Cây 2‐3  
Cây 2‐3  
Xóa nút:  
Xóa 27 (trường hợp nút lá sau khi xóa vẫn còn phần tử)  
Nếu phần tử bị xóa ở trên nút trong:  
Phải chuyển phần tử đó về nút lá để xóa  
Thay thế bằng nút kế tiếp trong duyệt theo thứ tự giữa  
24  
24  
37 45  
42  
42 45  
37  
12  
27 32  
12  
32  
35  
47 52  
35  
47 52  
Xóa 37, ta thay bằng 42  
19  
3/24/2011  
Cây 2‐3  
Cây 2‐3  
Xóa 35 : trường hợp (i)  
Xóa 37: trường hợp (ii)  
42 47  
45  
47  
37 45  
42 47  
37  
52  
35  
42  
47 52  
37  
45  
52  
42 45  
52  
Cây 2‐3  
Cây 2‐3  
Xóa 52: trường hợp (ii)  
Xóa 12: trường hợp (ii)  
34  
42  
42 47  
24  
42 47  
45  
37  
45  
52  
37  
45 47  
12  
32  
37  
52  
20  
Tải về để xem bản đầy đủ
pdf 22 trang Thùy Anh 17360 Free
Bạn đang xem 20 trang mẫu của tài liệu "Bài giảng Cấu trúc dữ liệu và thuật toán - Phần 1: Giới thiệu về thuật toán - Chương 4, Phần 2: Tìm kiếm - Nguyễn Duy Hiệp", để tải tài liệu gốc về máy hãy click vào nút Download ở trên

File đính kèm:

  • pdfbai_giang_cau_truc_du_lieu_va_thuat_toan_phan_1_gioi_thieu_v.pdf