Thiết Kế & Đánh Giá Thuật Toán Cây Tìm Kiếm Nhị Phân

TS. Lê Nguyên Khôi Trường Đại Học Công Nghệ - ĐHQGHN

Nội Dung

(cid:1) Cây tìm kiếm nhị phân (TKNP) (cid:1) Dựng cây TKNP (cid:1) Cây TKNP cân bằng

(cid:1) Cây Đỏ - Đen (cid:1) Cây AVL (cid:1) Cây Treap

1

Định Nghĩa

(cid:1) Cây TKNP:

(cid:1) cây nhị phân

(cid:1) lưu khóa ở đỉnh trong (cid:1) lá rỗng

(cid:1) thỏa mãn tính chất:

(cid:1)(cid:2)(cid:3) (cid:4) ≤ (cid:1)(cid:2)(cid:3) (cid:6) ≤ (cid:1)(cid:2)(cid:3) (cid:7)

(cid:1) (cid:4) trong cây con trái của (cid:6) (cid:1) (cid:7) trong cây con phải của (cid:6)

(cid:6)

(cid:7)

(cid:4)

6

9 2

2

1 4 8

Thao Tác Chính

(cid:1) Cây TKNP thực hiện các tao thác chính

(cid:1) Truy vấn: không thay đổi cấu trúc cây TKNP

(cid:1) Tìm kiếm (SEARCH) (cid:1) Nhỏ nhất (MINIMUM) (cid:1) Lớn nhất (MAXIMUM) (cid:1) Trước (PREDECESSOR) (cid:1) Sau (SUCCESSOR)

(cid:1) Sửa đổi: thay đổi cấu trúc cây TKNP

(cid:1) Chèn (INSERT) (cid:1) Xóa (DELETE)

3

Tính Chất

(cid:1) (cid:4) trong cây con trái của (cid:6), (cid:7) trong cây con phải của (cid:6)

(cid:1)(cid:2)(cid:3) (cid:4) ≤ (cid:1)(cid:2)(cid:3) (cid:6) ≤ (cid:1)(cid:2)(cid:3) (cid:7)

(cid:1) Duyệt cây TKNP theo thứ tự trong, thăm các khóa theo

thứ tự tăng dần

(cid:1) Sử dụng cây TKNP cho

(cid:1) cài đặt từ điển

(cid:1) Cây thứ tự bộ phận (heap)

(cid:1) là cây tìm kiếm (cid:1) là cây nhị phân (cid:1) không phải cây TKNP (cid:1) dùng quản lý hàng đợi ưu tiên

4

Độ Phức Tạp Thời Gian

(cid:1) ℎ đô cao của cây (cid:1) (cid:9) độ lớn của cây (số đỉnh trong) (cid:1) Thời gian (cid:10)(ℎ), với các thao tác chính

(cid:1) Cây TKNP đầy đủ ℎ = log (cid:9) (cid:1) Cây TKNP là một xích (cid:9) nút ℎ = (cid:9)

6 6

9 9 2

5

10 1 4 8 8

Truy Vấn – Tìm Kiếm Tree-Search((cid:17),(cid:18)) 1

if (cid:17) = NIL or (cid:18) = (cid:17). (cid:18)(cid:23)(cid:24)

2

3

return (cid:17) if (cid:18) < (cid:17). (cid:18)(cid:23)(cid:24)

4

5

return Tree-Search((cid:17). (cid:26)(cid:23)(cid:27)(cid:28),(cid:18)) else return Tree-Search((cid:17). (cid:29)(cid:30)(cid:31)ℎ(cid:28),(cid:18))

6

9 2

(cid:18) = 4: 6 (cid:18) = 4: 6 → 2 → 4 (cid:18) = 7: 6 → 9 → 8 → NIL

6

1 4 8

Truy Vấn – Tìm Kiếm

Iterative-Tree-Search((cid:17),(cid:18)) while (cid:17) ≠ NIL and (cid:18) ≠ (cid:17). (cid:18)(cid:23)(cid:24) 1

2

3

4

if (cid:18) < (cid:17). (cid:18)(cid:23)(cid:24) (cid:17) ← (cid:17). (cid:26)(cid:23)(cid:27)(cid:28) else (cid:17) ← (cid:17). (cid:29)(cid:30)(cid:31)ℎ(cid:28)

5

return (cid:17)

6

9 2

Tìm (cid:18) = 4: 6 Tìm (cid:18) = 4: 6 → 2 → 4 Tìm (cid:18) = 7: 6 → 9 → 8 → NIL

7

1 4 8

Truy Vấn – Nhỏ/Lớn Nhất

Tree-Minimum((cid:17)) 1

while (cid:17). (cid:26)(cid:23)(cid:27)(cid:28) ≠ NIL

(cid:17) ← (cid:17). (cid:26)(cid:23)(cid:27)(cid:28)

6

2 3

9

return (cid:17) Nhỏ nhất: 6 → 2 → 1

2

1 4 8

Tree-Maximum((cid:17)) 1

while (cid:17). (cid:29)(cid:30)(cid:31)ℎ(cid:28) ≠ NIL

(cid:17) ← (cid:17). (cid:29)(cid:30)(cid:31)ℎ(cid:28)

2 3

return (cid:17) Lớn nhất: 6 → 9

8

Truy Vấn – Trước

Tree-Predecessor((cid:17)) 1

if (cid:17). (cid:26)(cid:23)(cid:27)(cid:28) ≠ NIL

2

return Tree-Maximum((cid:17). (cid:26)(cid:23)(cid:27)(cid:28))

3

4

(cid:24) = (cid:17). +,(cid:29)(cid:23)(cid:9)(cid:28) while (cid:24) ≠ NIL and (cid:17) = (cid:24). (cid:26)(cid:23)(cid:27)(cid:28)

5

6

(cid:17) = (cid:24) (cid:24) = (cid:24). +,(cid:29)(cid:23)(cid:9)(cid:28)

6

7

return (cid:24)

9 2

Trước: (cid:18) = 6: 6 → 2 → 4 Trước: (cid:18) = 8: 8 → 9 → 6

9

1 4 8

Truy Vấn – Sau

Tree-Succesor((cid:17)) if (cid:17). (cid:29)(cid:30)(cid:31)ℎ(cid:28) ≠ NIL 1

2

return Tree-Minimum((cid:17). (cid:29)(cid:30)(cid:31)ℎ(cid:28))

3

4

(cid:24) = (cid:17). +,(cid:29)(cid:23)(cid:9)(cid:28) while (cid:24) ≠ NIL and (cid:17) = (cid:24). (cid:29)(cid:30)(cid:31)ℎ(cid:28)

5

6

(cid:17) = (cid:24) (cid:24) = (cid:24). +,(cid:29)(cid:23)(cid:9)(cid:28)

6

7

return (cid:24)

9 2

Sau: (cid:18) = 6: 6 → 9 → 8 Sau: (cid:18) = 4: 4 → 2 → 6

10

1 4 8

Sửa Đổi – Chèn

6

9 2

1 4 8

if .. (cid:18)(cid:23)(cid:24) < (cid:17). (cid:18)(cid:23)(cid:24) (cid:17) = (cid:17). (cid:26)(cid:23)(cid:27)(cid:28) else (cid:17) = (cid:17). (cid:29)(cid:30)(cid:31)ℎ(cid:28)

7

.. +,(cid:29)(cid:23)(cid:9)(cid:28) = (cid:24) if (cid:24) = NIL

-. (cid:29)//(cid:28) = .

elseif .. (cid:18)(cid:23)(cid:24) < (cid:24). (cid:18)(cid:23)(cid:24)

Tree-Insert(-,.) 1 (cid:24) = NIL 2 (cid:17) = -. (cid:29)//(cid:28) 3 while (cid:17) ≠ NIL 4 (cid:24) = (cid:17) 5 6 7 8 9 10 11 12 13

(cid:24). (cid:26)(cid:23)(cid:27)(cid:28) = . else (cid:24). (cid:29)(cid:30)(cid:31)ℎ(cid:28) = .

11

Sửa Đổi – Xóa

(cid:1) Xóa nút . khỏi cây - cây, 3 trường hợp

(cid:1) . không có con

(cid:1) xóa .

(cid:1) . chỉ có 1 con trái hoặc phải

(cid:1) chuyển con đó lên thay . (cid:1) . có cả con trái và phải

(cid:1) chuyển lớn nhất cây con trái hoặc nhỏ nhất cây

con phải (.′) lên thay .

(cid:1) xóa .′

(cid:1) Lưu ý: khi xóa . nên giảm độ cao của cây -

nếu có thể

12

Dựng Cây TKNP

(cid:1) Các thao tác chính trong thời gian (cid:10)(ℎ)

(cid:1) Dựng cây TKNP có độ cao (ℎ) càng nhỏ càng tốt

(cid:1) Dựng cây TKNP:

(cid:1) Chèn liên tục khóa vào cây, bắt đầu từ cây rỗng (cid:1) Tại mỗi nút, cây con trái và phải cân bằng

(cid:1) Chọn khóa (cid:18) nào cho nút . (cid:1) Vần đề tương tự như chọn phần tử chốt trong phân

hoạch của thuật toán Sắp Xếp Nhanh (cid:1) Chọn ngẫu nhiên khóa (cid:18) chèn vào cây

(cid:1) Độ cao trung bình ℎ = 1(log (cid:9))

13

Vấn Đề Khác (cid:1) Cần sửa Tree-Insert để xử lý khóa trùng nhau trong cây TKNP

(cid:1) Cách 1: chọn ngẫu nhiên cây

con trái/phải

if .. (cid:18)(cid:23)(cid:24) < (cid:17). (cid:18)(cid:23)(cid:24) (cid:17) = (cid:17). (cid:26)(cid:23)(cid:27)(cid:28) else (cid:17) = (cid:17). (cid:29)(cid:30)(cid:31)ℎ(cid:28)

(cid:1) Cách 2: dựa vào (cid:27)(cid:26),(cid:31) để chọn cây con trái/phải

(cid:1) Cách 3: sử dụng danh sách

.. +,(cid:29)(cid:23)(cid:9)(cid:28) = (cid:24) if (cid:24) = NIL

-. (cid:29)//(cid:28) = .

để lưu khóa trùng

elseif .. (cid:18)(cid:23)(cid:24) < (cid:24). (cid:18)(cid:23)(cid:24)

Tree-Insert(-,.) 1 (cid:24) = NIL 2 (cid:17) = -. (cid:29)//(cid:28) 3 while (cid:17) ≠ NIL 4 (cid:24) = (cid:17) 5 6 7 8 9 10 11 12 13

(cid:24). (cid:26)(cid:23)(cid:27)(cid:28) = . else (cid:24). (cid:29)(cid:30)(cid:31)ℎ(cid:28) = .

14

Cây TKNP Cân Bằng

(cid:1) Độ cao của cây TKNP cần nhỏ để các thao tác

chính thực hiện nhanh

(cid:1) Nếu cây TKNP “cân bằng” thực hiện các thao

tác trong 1(log (cid:9))

(cid:1) Tính chất “cân bằng” có thể bị phá vỡ với thao

tác sửa đổi (Chèn/Xóa) (cid:1) Sửa lại cấu trúc cây thông qua phép xoay

(cid:1) Hai loại cây TKNP “cân bằng”

(cid:1) Cây Đỏ - Đen (cid:1) Cây AVL

15

Cây Đỏ - Đen

(cid:1) Mỗi nút cần thêm 1-bit màu (cid:1) Tính chất

(cid:1) 1. Mỗi nút là đỏ hoặc đen (cid:1) 2. Gốc và lá (NIL) đen (cid:1) 3. Nếu một nút đỏ, thì con của nó đen (cid:1) 4. Mọi đường đi từ một nút đến các lá con có

cùng số lượng nút đen

(cid:1) 5. Không đường đi nào dài hơn gấp đôi

đường đi nào

(cid:1) Độ cao của cây Đỏ - Đen với (cid:9) nút

ℎ ≤ 2 log((cid:9) + 1)

16

Cây Đỏ - Đen – Ví Dụ

17

Cây Đỏ - Đen – Thao Tác

(cid:1) Các thao tác chèn và xóa có thể làm thay

đổi tính chất của cây (cid:1) Do chính các thao tác này (cid:1) Đổi màu các nút (cid:1) Cấu trúc lại các kết nối nút

(cid:1) Phép xoay: đảm bảo thứ tự trong của khóa (cid:1) Phép thực hiện trong thời gian 3(1)

18

Cây AVL

(cid:1) Georgy Adelson-Velsky & Evgenil Landis

đề xuất năm 1962

(cid:1) Độ cao 2 cây của của một nút khác nhau

nhiều nhất 1

(cid:1) Thời gian 3(log (cid:9)) cho các thao tác trong cả 2 trường hợp trung bình & xấu nhất

(cid:1) Cân bằng xây bằng phép xoay

19

Cây Treap

(cid:1) Dựng cây TKNP ngẫu nhiên (slide 13) sẽ

được cây tương đối cân bằng

(cid:1) Tuy nhiên nếu dữ liệu được cung cấp lần lượt, khóa sẽ không lựa chọn ngẫu nhiên

(cid:1) Cây Treap cung cấp giải pháp

(cid:1) Là sự kết hợp của cây TKNP và cây thứ tự

bộ phận (min-heap)

(cid:1) Khóa (cid:18)(cid:23)(cid:24) thỏa mãn cây TKNP (cid:1) Ưu tiên +(cid:29)(cid:30)/(cid:29)(cid:30)(cid:28)(cid:24) thỏa mãn cây min-heap

20

Cây TKNP Cân Bằng – Phép Xoay

(cid:1) Xem Mục 13.2 tr.312

21