Upload
itnoi
View
342
Download
4
Embed Size (px)
Citation preview
BỘ GIÁO DỤC VÀ ĐÀO TẠO
TRƯỜNG ĐẠI HỌC SƯ PHẠM TP.HCM Khoa Toán – Tin học
-------���-------
Slide bài giảng
CẤU TRÚC DỮ LIỆU 2
Giảng viên: Lương Trần Hy Hiến Email: [email protected]
TP.HCM – 12/2008
Đại Học Sư Phạm Tp. Hồ Chí MinhĐại Học Sư Phạm Tp. Hồ Chí Minh
CẤU TRÚC DỮ LI ỆU 2 CẤU TRÚC DỮ LI ỆU 2
Giới thi ệu về môn học
Thông tin giảng viên
•• LƯƠNG TRẦN HY HIẾNLƯƠNG TRẦN HY HIẾN• Bộ Môn Tin Học• Khoa Toán – Tin học• Phone: 0949 790 7750949 790 775• Phone: 0949 790 7750949 790 775• Email: [email protected]• Tài liệu:
http://sites.google.com/a/hcmup.edu.vn/hienlthhttp://sites.google.com/a/hcmup.edu.vn/hienlth
2
Thông tin môn học
• CẤU TRÚC DỮ LIỆU 2• Số đvht: 4(CQ) – 3(CT)• Điều kiện tiên quyết:
– Cấu trúc dữ liệu 1– Cấu trúc dữ liệu 1
– Đã học môn “Lập trình C++”
– Kiến thức cơ bản về lập trình
3
Mục tiêu
• Nhằm giúp sinh viên tiếp cận các cấu trúc dữ liệu cao cấp.
• Hiểu được tầm quan trọng của giải thuật và cách tổ chức chương trình và khai thác các dữ liệu phức tạp.dữ liệu phức tạp.
• Giúp sinh viên củng cố và phát triển kỹ năng phân tích và lập trình ở mức độ cao.
4
Đề cương môn học: CTDL2CTDL2
• Chương 1: Sắp xếp ngoại
• Chương 2: Bảng băm (Hash Table)
• Chương 3: B – Cây (B-Tree)
• Chương 4: Cây Đỏ Đen (Red-Black Tree)
5
Đánh giá kết quả học tập
• Thi lý thuyết : 70%
• Thi thực hành: 30%
• Bài thực hành hàng tuần: Kết quảkhông tính vào điểm tổng kết, tuynhiên nếu không thực hiện tốt sẽ bị trừnhiên nếu không thực hiện tốt sẽ bị trừ10% nội dung thi thực hành.
6
Đề tài môn học
• Xây dựng chương trình mô tả cây đỏđen, B-cây, cây 2-3-4 trong đó mô tảchi tiết CTDL đã dùng, các thao tác liênquan tới cây.
• Tìm hiểu R-Tree, RBTree, B+ Tree, B++• Tìm hiểu R-Tree, RBTree, B+ Tree, B++Tree, KD-Tree, SBB-Tree
• Tìm hiểu các giải thuật nén RLE,Huffman, LZ77, LZ78
• Tìm hiểu mã hóa dữ liệu với DES, AES,RSA
7
Tài li ệu tham khảo
• Slide bài giảng của giảng viên
• Algorithms, Robert Sedgewick.
• Algorithms + Data Structures = Program,
N.Wirth.
• Các tài liệu tham khảo trên Internet
8
Đại Học Sư Phạm Tp. Hồ Chí MinhĐại Học Sư Phạm Tp. Hồ Chí Minh
CẤU TRÚC DỮ LI ỆU 2 CẤU TRÚC DỮ LI ỆU 2
Chương 01: SẮP XẾP NGOẠI
Đề cương môn học: CTDL2CTDL2
• Chương 1: Sắp xếp ngoại• Chương 2: Bảng băm (Hash Table)• Chương 3: Cây 2-3-4, B – cây• Chương 4:Cây Đỏ Đen (Red Black Tree)
22CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
Giới thi ệu
• Mục tiêu:– Bài toán kinh điển: Sắp xếp và tìm kiếm– Đặc trưng của SX trên file: Bài toán trộn
– TT tìm kiếm cơ bản: Tuần tự, nhị phân– TT sắp xếp: Trộn trực tiếp, trộn tự nhiên, trộn n-
33CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
– TT sắp xếp: Trộn trực tiếp, trộn tự nhiên, trộn n-đường cân bằng, trộn đa pha
– Đánh giá thuật toán
• Các nội dung chính:– Thuật toán và cài đặt các phương pháp sắp xếp
Chương 1: SẮP XẾP NGOẠI
• Phương pháp trộn Run• Phương pháp trộn tự nhiên• Phương pháp trộn đa lối cân bằng• Phương pháp trộn đa pha
44CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
• Phương pháp trộn đa pha
Các PP sắp xếp – Vấn đề???
Vì sao phải xây dựng thuật toán sắp xếp trên file?
• Thao tác cơ bản trong SX là hoán vị• Thực hiện hoán vị trên cùng 1 file � Tần
suất thao tác lên trên 1 vùng đĩa quá lớn
55CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
suất thao tác lên trên 1 vùng đĩa quá lớn� Không an toàn.
• SX ngoại không thích hợp với hoán vị � Sử dụng phương pháp trộn.
Bài toán trộn
• Cho trước 2 (hay nhiều) dãy đã sắp thứ tự:A[1], A[2], A[3], …, A[N]
B[1], B[2], B[3], …, B[M]
• Kết hợp các dãy đã cho thành một dãy mới C được sắp.
66CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
được sắp.
Thuật toán trộn 1 – Trộn từng phần tửint nCurrA = 1;int nCurrB = 1;A[N+1] = MAX_VALUE; // phần tử lính canhB[M+1] = MAX_VALUE; // phần tử lính canhfor (int nCurrC=1; nCurrC <= N+M; nCurrC++)
if (A[nCurrA] < B[nCurrB]) {C[nCurrC] = A[nCurrA];
77CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
C[nCurrC] = A[nCurrA];nCurrA++;
}else {
C[nCurrC] = B[nCurrB];nCurrB++;
}
T.toán trộn 2 – Trộn dãy phần tử được sắpint nCurrA = 1;int nCurrB = 1;while (nCurrA <= N && nCurrB <= M){
if (A[nCurrA] < B[nCurrB]) C[nCurrC] = A[nCurrA];
elseC[nCurrC] = B[nCurrB];
nCurrC++;
88CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
nCurrC++;}// Xét phần tử còn lại của dãy Afor ( ; nCurrA <= N; nCurrA++) {
C[nCurrC] = A[nCurrA];nCurrC++;
}// Xét phần tử còn lại của dãy Bfor ( ; nCurrB <= M; nCurrB++) {
C[nCurrC] = B[nCurrB];nCurrC++;
}
1. Phương pháp trộn trực tiếp
• Khái niệm:– Run là một dãy liên tiếp các phần tử được sắp
thứ tự.Ví dụ: 2 4 7 12 55 là một Run.
– Chiều dài Run chính là số phần tử trong Run.
99CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
– Chiều dài Run chính là số phần tử trong Run.Chẳng hạn Run ở ví dụ trên có chiều dài là 5.
1. Phương pháp trộn trực tiếp
• Giải thuật:– Giải thuật sắp xếp tập tin bằng phương pháp
trộn Run có thể tóm lược như sau:Input: f0 là tập tin cần sắp thứ tựOuput: f0 là tập tin đã được sắp thứ tự
1010CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
Ouput: f0 là tập tin đã được sắp thứ tựGọi f1, f2 là 2 tập tin trộn.Trong đó f0, f1, f2 có thể là các tập tin văn bản
thường (text file) hay các tập tin nhị phân.
1. Phương pháp trộn trực tiếp
• Bước 1:– Giả sử các phần tử trên f0 là:
24 12 67 33 58 42 11 34 29 31– Khởi tạo f1, f2 rỗng.– Thực hiện phân bố m=1 phần tử từ f0 lần lượt
1111CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
– Thực hiện phân bố m=1 phần tử từ f0 lần lượt vào f1, f2:f1: 24 67 58 11 29f2: 12 33 42 34 31
– Trộn f1,f2 vào f0f0: 12 24 33 67 42 58 11 34 29 31
1. Phương pháp trộn trực tiếp
• Bước 2:– Phân bố m=2 *m = 2 phần tử từ f0 vào f1, f2
f0: 12 24 33 67 42 58 11 34 29 31f1: 12 24 42 58 29 31f2: 33 67 11 34
1212CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
f2: 33 67 11 34– Trộn f1, f2 thành f0:
f0: 12 24 33 67 11 34 42 58 29 31
1. Phương pháp trộn trực tiếp
• Bước 3:– Tương tự bước 2, phân bố m= 2 * m = 4 phần
tử từ f0 vào f1, f2f0: 12 24 33 67 11 34 42 58 29 31f1: 12 24 33 67 29 31
1313CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
f1: 12 24 33 67 29 31 f2: 11 34 42 58
– Trộn f1, f2 thành f0:f0: 11 12 24 33 34 42 58 67 29 31
1. Phương pháp trộn trực tiếp
• Bước 4: Phân bố m=2 * m = 8 phần tử lần lượt từ f0 vào f1, f2.f1: 11 12 24 33 34 42 58 67f2: 29 31– Trộn f1, f2 thành f0:
1414CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
– Trộn f1, f2 thành f0:f0: 11 12 24 29 31 33 34 42 58 67
• Bước 5: Lặp lại tương tự các bước trên cho tới khi chiều dài m của run cần phân bố lớn hơn chiều dài n của f0 thì dừng.
Cài đặt thuật toán
m = 1while (m < số phần tử của f0){
Chia[Distribute] m phần tử của f0 lần lượt
1515CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
Chia[Distribute] m phần tử của f0 lần lượt cho f1, f2
Trộn[Merge] f1, f2 lần lượt vào f0
M = M * 2
}
Đánh giá
• Đánh giá:– Cần ít nhất N không gian trống trên đĩa để hoạt động.– Số bước log2N (vì mỗi lần xử lý 1 dãy tăng gấp 2)– Mỗi bước:
• Distribute: Copy N lần• Merge: Copy N lần, so sánh N/2 lần
1616CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
• Merge: Copy N lần, so sánh N/2 lần
– Tổng cộng:• Copy: 2N * log2N• So sánh: N/2 * log2N
• Hạn chế:– Không tận dụng được dữ liệu đã được sắp bộ phận– Độ dài dãy con xử lý ở bước k <= 2k
2. Phương pháp trộn tự nhiên
Giải thuật:
• Trong phương pháp trộn ở mục 1, giải thuậtchưa tận dụng được chiều dài cực đại củacác Run trước khi phân bố � chưa tối ưu.
• Đặc điểm của PP trộn tự nhiên là tận dụng
1717CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
• Đặc điểm của PP trộn tự nhiên là tận dụngchiều dài “tự nhiên” của các Run ban đầu;nghĩa là thực hiện việc trộn các Run có độdài cực đại với nhau cho tới khi dãy chỉ còn1 Run duy nhất � dãy đã được sắp.
2. Phương pháp trộn tự nhiên
Giải thuật:Trong khi số Run của F0 > 1
Phân bố F0 vào F1, F2 theo các Run tự nhiên.Trộn các Run của F1, F2 vào F0.
Hết trong khido {
1818CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
do {- [Distribute] Chia xoay vòng dữ liệu của file F0 cho
F1 và F2, mỗi lần 1 run cho đến khi file F0 hếtnDemRunF0 = 0;
- [Merge] Trộn từng cặp run của F1 và F2 tạo thành run mới trên F0
} while (nDemRunF0 > 1);
2. Phương pháp trộn tự nhiên
• Ví dụ: F0: 1 2 9 8 7 6 5• Bước 1:
– F1: 1 2 9 7 5
– F2: 8 6
1919CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
– F0: 1 2 8 9 6 7 5
• Bước 2:– F1: 1 2 8 9 5
– F2: 6 7
– F0: 1 2 6 7 8 9 5
2. Phương pháp trộn tự nhiên
• Ví dụ(tt)• Bước 3:F0: 1 2 6 7 8 9 5
– F1: 1 2 6 7 8 9
– F2: 5
2020CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
– F0: 1 2 5 6 7 8 9
• Bước 4: Dừng vì F0 chỉ có 1 Run.
3. Phương pháp trộn đa lối cân bằng
• Thuật toán sắp xếp ngoài cần 2 giai đoạn: Phân phối và trộn.– Giai đoạn nào làm thay đổi thứ tự?– Chi phí cho giai đoạn phân phối?
• Rút ra kết luận:
2121CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
• Rút ra kết luận:– Thay vì thực hiện 2 giai đoạn, ta chỉ cần thực
hiện 01 giai đoạn trộn.• Tiết kiệm ½ chi phí Copy.• Cần số lượng file trung gian gấp đôi.
3. Phương pháp trộn đa lối cân bằng
• Chi phí sắp xếp ngoài tỉ lệ với số bước thực hiện:– Nếu mỗi bước cần N thao tác copy– Nếu dùng 2 file trung gian cần log2N bước � cần N *
log2N thao tác copy.– Để giảm số bước � Phân bố số Run nhiều hơn 2 file
trung gian.– Nếu dùng n file trung gian: cần log N bước � cần N *
2222CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
– Nếu dùng n file trung gian: cần lognN bước � cần N *
lognN thao tác copy.
• Rút ra kết luận:– Dùng nhiều file trung gian để giảm số bước.– Tiết kiệm thao tác copy bằng cách thực hiện 1 giai đoạn– Sử dụng 2*n file trung gian:
• n file nguồn• n file đích
3. Phương pháp trộn đa lối cân bằng
Thuật toán:• B1: Gọi tập nguồn S = {f1, f2, …, fn}
Gọi tập đích D = {g1, g2, …, gn}Chia xoay vòng dữ liệu của file F0 cho các file thuộc
tập nguồn, mỗi lần 1 Run cho tới khi F0 hết.• B2: Trộn từng bộ Run của các file thuộc tập nguồn
2323CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
• B2: Trộn từng bộ Run của các file thuộc tập nguồn S, tạo thành Run mới, mỗi lần ghi lên các file thuộc tập đích D.
• B3: Nếu (số Run trên các file của D > 1) thì:– Hoán vị vai trò tập nguồn (S) và tập đích (D).– Quay lại B2
Ngược lại kết thúc thuật toán.
3. Phương pháp trộn đa lối cân bằngVí dụ:• fInput: U Q N M K I H F D C B, N=3// Phân phối (lần 1)f1: U M H Cf2: Q K F Bf3: N I D// Trộn (lần 1)g1: N Q U B C
2424CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
g1: N Q U B Cg2: I K Mg3: D F H// Trộn (lần 2)f1: D F H I K M N Q Uf2: B Cf3: NULL// Trộn (lần 3)g1: B C D F H I K M N Q Ug2: NULLg3: NULL
3. Phương pháp trộn đa lối cân bằng• Các ký hiệu:
– fInput: file dữ liệu gốc cần sắp xếp– N: số phần tử trên file fInput– n: số file trung gian trên mỗi tập nguồn/đích– S: tập các file nguồn– D: tập các file đích– Sdd: tập các file nguồn đang còn run dở dang– Str: tập các file nguồn chưa hết (!EOF), còn có thể tham gia vào quá
2525CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
– Str: tập các file nguồn chưa hết (!EOF), còn có thể tham gia vào quá trình trộn
– “Lượt”: là 1 quá trình trộn run từ nguồn đ đích, một “luợt” kết thúc khi mỗi file đích (trong tập D) nhận được 1 run
– Drun: tập các file đích đã nhận được run trong “lượt” hiện hành• Suy diễn:
– S –Str: tập các file nguồn đã hết (EOF) – Str –Sdd: tập các file nguồn chưa hết (!EOF), nhưng đã kết thúc run
hiện tại– D – Drun: tập các file đích chưa nhận được run trong “lượt” hiện hành
3. Phương pháp trộn đa lối cân bằng
�Thuật toán chi tiết:[Bước 1] S = {f1, f2, … , fn}
D = {g1, g2, … , gn}// Chia xoay vòng dữ liệu của fInput cho các
file thuộc tập nguồn Si = 1;while (!feof(fInput)) {
2626CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
while (!feof(fInput)) {Copy_1_Run(fInput, fi);i = (i % n) + 1;
}Str = S;Drun = {};nDemRun = 0;
3. Phương pháp trộn đa lối cân bằng[Bước 2]a. Sdd = Strb. Gọi dhh ∈ D –Drun là file đích hiện hành (sẽ được nhận run)c. Đọc các phần tử xfi, fi ∈ Sddd. Gọi xf0 = MIN { xfi, fi ∈ Sdd}e. Copy xf0 lên dhhf. Nếu (file f0 hết) thì {
Str = Str – {f0}S = S – {f0}
2727CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
Sdd = Sdd – {f0}Nếu (Str == {}) thì { // Xong quá trình trộn N đ D
nDemRun++;Goto [Bước 3]
}ngược lại Nếu (Sdd <> {}) thì Goto [Bước 2.d]
ngược lại { // Sdd=={}: hết bộ run hiện hànhnDemRun++;Drun = Drun + {dhh};Nếu (Drun==D) thì Drun= {}; // Xong 1 “lượt”Goto [Bước 2.a]
}
3. Phương pháp trộn đa lối cân bằngngược lại { // File f0 chưa hết
Nếu (!EOR(f0)) thì {Đọc phần tử kế xf0 từ file f0;Goto [Bước 2.d]
}ngược lại { // Hết run hiện hành trên f0
Sdd = Sdd – {f0}
2828CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
Sdd = Sdd – {f0}Nếu (Sdd <> {}) thì Goto [Bước 2.d]ngược lại { // Sdd=={}: hết bộ run hiện hànhnDemRun++;Drun = Drun + {dhh};Nếu (Drun==D) thì Drun= {}; // Xong 1 “lượt”Goto [Bước 2.a]
}} // end of file f0 chưa hết
3. Phương pháp trộn đa lối cân bằng
[Bước 3]Nếu (nDemRun == 1) thì Kết thúc thuật toánngược lại {
Nếu (nDemRun < n) thì Str = Drun; // Không đủ n runngược lại Str = D;
2929CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
ngược lại Str = D;Drun = {};nDemRun = 0;“Hoán vị tập S, D”Goto [Bước 2]
}
Tr ộn đa lối cân bằng• Ví dụ: Cho dãy số sau
3 5 2 7 12 8 4 15 20 1 2 8 23 7 21 27
• Nhập :f0 :3 5 2 7 12 8 4 15 20 1 2 8 237 21 27
3030CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
• Xuất :f0: 1 2 2 3 4 5 7 7 8 8 12 15 20 21 23 27
Các bước tiến hành : chọn 6 file
3 5 2 7 12 8 4 15 20 1 2 8 23 7 21 27
Bước 0: đặt nh = 3Bước 1: Phân phối các run luân phiên vào f[1], f[2], f[3]
3131CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
f1: 3 5 4 15 20f2: 2 7 12 1 2 8 23f3: 8 7 21 27
Các bước tiến hành : chọn 6 fileBước 2:
-Tr ộn các run của f[1], f[2], f[3] và luân phiên phân phối vào các file g[1], g[2], g[3]g1: 2 3 5 7 8 12g2: 1 2 4 7 8 15 20 21 23 27g3:
3232CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
g3: - Do số run sau khi trộn >1 nên tiếp tục trộn run từ g[1], g[2], g[3] vào ngược trở lại f[1], f[2], f[3]f1: 1 2 2 3 4 5 7 7 8 8 12 15 20 21 23 27f2:f3: - Do số run tr ộn = 1 nên kết thúc thuật toán
Bước 1
3 5 2 7 12 8 4 15 20 1 23 78 21 2723 5 2 7 12 8 4 15 20 7 21 271 2382
f1
3333CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
f2
f3
Bước 2
3 5
2 7 12
8
4 15 20
7 21 27
1 2382
3 5
2 7 12
8
4 15 20
7 21 27
1 2382
f1
f2
f3
3434CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
57 123 2 8
g1
g2
g3
4 8 2015 21 271 2372
6 15 2018 21 271 2382
5 122 73g1
g3
g2
Bước 2
4 8 2015 21 271 2372
5 122 73
4 8 2015 21 271 2372
5 122 73
4 8 2015 21 271 2372
5 122 73
3535CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
1 2 2 3 4 5 7 15 21 277 1288f1
f2
f3
20 23
4. Phương pháp trộn đa pha
• Phương pháp trộn đa lối cân bằng các tập tinchưa được sử dụng một cách có hiệu quả bởivì trong cùng một lần duyệt thì phân nửa sốtập tin luôn luôn giữ vai trò trộn (nguồn) vàphân nửa số tập tin luôn luôn giữ vai trò
3636CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
phân nửa số tập tin luôn luôn giữ vai tròphân phối (đích) � Cải tiến: Thay đổi vai tròcủa các tập tin trong cùng một lần duyệt �phương pháp trộn đa pha.
4. Phương pháp trộn đa phaTa xét ví dụ sau với 3 tập tin f1, f2, f3• Bước 1: Phân phối luân phiên các run ban đầu của f0 vào
f1 và f2• Bước 2: Trộn các run của f1, f2 vào f3 . Giải thuật kết thúc
nếu f3 chỉ có một run• Bước 3: Chép nửa run của f3 vào f1• Bước 4: Trộn các run của f1 và f3 vào f2. Giải thuật kết
3737CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
• Bước 4: Trộn các run của f1 và f3 vào f2. Giải thuật kết thúc nếu f2 chỉ có một run.
• Bước 5: Chép nửa số run của f2 vào f1. Lặp lại bước 2.Phương pháp này còn có nhược điểm là mất thời gian sao
chép nửa số run của tập tin này vào tập tin kia. Việc sao chép này có thể loại bỏ nếu ta bắt đầu với Fn run của tập tin f1 và fn-1 run của tập tin f2, với fn và fn-1 là các số liên tiếp trong dãy Fibonaci.
4. Phương pháp trộn đa pha
• Ví dụ: Trường hợp n = 7, tổng số run ban đầu là13 + 8 = 21 run
Pharse F1 F2 F3
0 1,1,1,1,1,1,1,1 1,1,1,1,1 Sort
1 1,1,1 2,2,2,2,2 Merge1
3838CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
1 1,1,1 2,2,2,2,2 Merge1
2 3,3,3 2,2 Merge2
3 5,5 3 Merge3
4 5 8 Merge4
5 13 Merge4
6 21 Merge6
4. Phương pháp trộn đa pha
• Phase 0: Phân phối các run ban đầu
• Phase 1: Trộn 8 run của f1 và f2 vào f3
• Phase 2: Trộn 5 run của f1 và f3 vào f2
• Phase 3: Trộn 3 run của f2 và f3 vào f1
3939CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
• Phase 3: Trộn 3 run của f2 và f3 vào f1
• Phase 4: Trộn 2 run của f1 và f2 vào f3
• Phase 5: Trộn 1 run của f1 và f3 vào f2
• Phase 6: Trộn 1 run của f2 và f3 vào f1
ÔN TẬPÔN TẬPXỬ LÝ TẬP TIN VỚI C++XỬ LÝ TẬP TIN VỚI C++XỬ LÝ TẬP TIN VỚI C++XỬ LÝ TẬP TIN VỚI C++
Cấu trúc
4141CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
Nội dung
1. Giới thiệu về tập tin2. ofstream
– output file stream– Lớp làm nhiệu vụ ghi dữ liệu ra file
3. ifstream
4242CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
3. ifstream – input file stream– Lớp làm nhiệm vụ đọc dữ liệu từ file
4. Một số thao tác khác với tập tin5. fstream
– file stream– Lớp làm cả nhiệm vụ đọc và ghi tập tin
1. C++ File I/O
4343CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
1. Giới thi ệu về tập tin
• Binary file được dùng để lưu trữ dữ liệudạng cấu trúc có kích thước cố định– Khi ghi biến cấu trúc lên file sẽ ghi 1 khối có
kích thước cố định,– Khi đọc từ file ra biến cấu trúc cũng đọc từ file
4444CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
– Khi đọc từ file ra biến cấu trúc cũng đọc từ filetheo từng khối có kích thước cố định.
• Muốn lập trình với file cần phải biết dạnglưu trữ cũng như ý nghĩa của dữ liệu trongfile.
1. Giới thi ệu về tập tin
• Input file : file có dữ liệu sẽ đượctruy cập để đưa vào biến
4545CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
• Output file: File sẽ chứa trị của biếnkhi trị của biến được ghi vào
2. ofstream
• Khai báo và mở tập tin để ghi dữ liệu– ofstream <tên biến>;
– ofstream <tên biến>(<tên file>);
– Ví dụ: ofstream fout;fout.open(“data.dat”);
hoặc ofstream fout(“data.dat”);
4646CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
hoặc ofstream fout(“data.dat”);
• Ghi dữ liệu chuẩn– Tương tự như cout
– <tên biến> <toán tử xuất (<<)>– Ví dụ: int a;
fout<<a;
2. ofstream
• Ghi dữ liệu dạng nhị phân– ostream& write(char* pch,int nCount);– ostream& write(unsigned char* puch,int nCount);– ostream& write(signed char* psch,int nCount);– Giải thích tham số
• pch,puch,psch: con trỏ đến mảng ký tự lưu dữ liệu.
4747CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
• pch,puch,psch: con trỏ đến mảng ký tự lưu dữ liệu.• nCount: số byte cần ghi
• Thường dùng để ghi toàn bộ một struct hoặc một đối tượng ra file
• Đóng tập tin: sử dụng phương thức close();
2. ofstream
• Ví dụGhi dữ liệu của 5 phần tử số nguyên liên tiếp ra file dạng nhị phân
---------------------------------------------------------
int a[10];
4848CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
int a[10];a[0]=65;a[1]=66;a[2]=97;a[3]=99;a[4]=67;ofstream fout(“data.dat”);int n=5;fout.write((char*)a,n*sizeof(*a));fout.close();
3. ifstream• Khai báo và mở tập tin để đọc dữ liệu
– ifstream <tên biến>;
– ifstream <tên biến>(<tên file>);
– Ví dụ: ifstream fin;fin.open(“data.dat”);
hoặc ifstream fin(“data.dat”);
4949CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
hoặc ifstream fin(“data.dat”);
• Đọc dữ liệu chuẩn– Tương tự như cin
– <tên biến> <toán tử nhập (>>)>– Ví dụ: int a;
fin>>a;
3. ifstream
• Đọc dữ liệu dạng nhị phân– istream& read(char* pch, int nCount);– istream& read(unsigned char* puch, int nCount);– istream& read(signed char* psch, int nCount);
• Giải thích tham số– pch,puch,psch: con trỏ đến mảng ký tự lưu dữ
5050CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
– pch,puch,psch: con trỏ đến mảng ký tự lưu dữ liệu.
– nCount: số byte lớn nhất cần đọc• Thường dùng để đọc một struct hoặc một
đối tượng từ file• Đóng tập tin: sử dụng phương thức close();
3. ifstream
• Ví dụĐọc dữ liệu của 5 phần tử số nguyên liên tiếp đã ghi dạng nhị phân
-----------------------------------------------int a[10];
5151CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
int a[10];
ifstream fin(“data.dat”);
int n=5;
fin.read((char*)a,n*sizeof(*a));
fin.close();
4. Một số thao tác khác với tập tin
• Lấy vị trí hiện tại của con trỏ tập tin– Khi đọc
• Dùng hàm tellg();
• Ví dụ: long pos=fin.tellg();
– Khi ghi
5252CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
– Khi ghi• Dùng hàm tellp();
• Ví dụ: long pos=fout.tellp();
4. Một số thao tác khác với tập tin
• Di chuyển con trỏ đến một vị trí trong tập tin– Khi đọc
• Dùng hàm seekg(long sobyte, ios::xx vtbd);• Ví dụ: fin.seekg(0,ios::beg); //về đầu tập tin
– Khi ghi
5353CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
– Khi ghi• Dùng hàm seekp(long sobyte, ios::xx vtbd);• Ví dụ: fout.seekp(0,ios::end); //đến cuối tập tin
– Hằng số• ios::beg: di chuyển từ đầu tập tin• ios::cur: di chuyển từ vị trí hiện tại của con trỏ• ios::end: di chuyển từ cuối tập tin
4. Một số thao tác khác với tập tin
long SizeOf(char *fileName){
long end,begin;ifstream myfile(fileName);begin = myfile.tellg();
5454CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
begin = myfile.tellg();myfile.seekg(0, ios::end);end = myfile.tellg();myfile.close();return end-begin;
}
Tính kích th ước Tính kích th ước của tập tincủa tập tin
5. fstream
• Sử dụng đối tượng của lớp này có thể vừa đọc vừa ghi dữ liệu trong cùng một tập tin
• is_open(): Trả về true nếu đang mở, falsenếu không mở.
• Mở tập tin vừa đọc vừa ghi dạng nhị phân
5555CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
• Mở tập tin vừa đọc vừa ghi dạng nhị phânfstream f;f.open(“data.dat”,ios::in|ios::out|ios::binary);ios::in, ios::out, ios::app, ios::nocreate, …
Làm việc với file bằng CLàm việc với file bằng C
56
Khai báo mở tập tin để đọc/ghi dữ liệu
– Khai báo biến con trỏ tệp
FILE* <tên file>;
– Mở tệp
File * fopen(const char *<tên file>, const char * <kiểu truy cập>);
5757CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
* <kiểu truy cập>);
– Ví dụ:
FILE *f;f = fopen(“D:\\data.txt”,”r”); //mở tập tin để đọc dữ liệu.
f = fopen(“D:\\data.txt”,”w”); //mở tập tin để ghi dữ liệu.
Một số kiểu truy cập
Kiểu truy cập Ý nghĩa
“r” Mở một tập tin đã có để đọc theo kiểu VB
“w” Mở một tập tin mới để ghi theo kiểu VB
“a” Mở một tập tin mới để ghi bổ sung theo kiểu VB
5858CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
“a” Mở một tập tin mới để ghi bổ sung theo kiểu VB
“rb” Mở một tập tin đã có để đọc theo kiểu nhị phân
“wb” Mở một tập tin mới để ghi theo kiểu nhị phân
“ab” Mở một tập tin mới để ghi bổ sung theo kiểu nhị phân
Lưu ý: Cần làm sạch vùng đệm trước khi chuyển từ đọc sang ghi hoặc từ ghi sang đọc.
Một số hàm khác
• Đóng fileint fclose(FILE * f);
• Đóng các file đang mởint fcloseall(void);
• Làm sạch vùng đệm
5959CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
• Làm sạch vùng đệmint fflush(FILE* f);
• Kiểm tra cuối fileint feof(FILE *f) //trả về giá trị khác 0 nếu
gặp cuối tệp, ngược lại trả về 0.
Các hàm nhập xuất ký tự
• Ghi ký tự lên file
int fputc(int ch, FILE *f)
Hàm ghi lên file f một ký tự có mã bằng
m = ch % 256
6060CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
m = ch % 256
• Đọc ký tự từ file
int fgetc(int ch, FILE *f)
Các hàm nhập xuất theo kiểu văn bản• Ghi dữ liệu theo khuôn dạng lên file
int fprintf(FILE* f, const char * dk,… )• Đọc dữ liệu từ file theo khuôn dạng
int fscanf(FILE* f, const char * dk,… )• Ghi một chuỗi ký tự lên file
int fputs(const char* s, FILE *f)
6161CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
int fputs(const char* s, FILE *f)• Đọc một dãy ký tự từ file
char fgets(const char* s, int n, FILE *f)Việc đọc kết thúc khi:
- Hoặc đã đọc n-1 ký tự- Hoặc gặp dấu xuống dòng- Hoặc kết thúc tệp.
Ví dụ - hàm fprintf
Chương trình tạo ra tệp văn bản text gồm 3 dòng với nội dung:
Dong 1Dong 2Dong 3
6262CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
Dong 3-----------------------------------------------
FILE *f;f =fopen(“D:\\text.txt”,”w”);for(int i=0; i<2; i++)
fprintf(f,”Dong%2d\n”,i);fclose(f);
Ví dụ - hàm fscanf
Giả sử có một dãy số nguyên ghi trên tệp array.sl, giữa 2 số có ít nhất 1 khoảng trống.
-----------------------------------------------…int c;while(!feof(f))
6363CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
while(!feof(f)){
fscanf(f, “%d”, &c);printf(“%3d”,c);
}…
Ví dụ - hàm fputs
Chương trình nhập một dòng ký tự từ bàn phím và ghi lên tệp “dongVB”
----------------------------------------------char s[256];FILE *f;f = fopen(“D:\\dongVB.txt”,”w”);
6464CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
f = fopen(“D:\\dongVB.txt”,”w”);printf(“Nhap dong van ban: “);gets(s);fputs(d,f);fclose(f);
Ví dụ - hàm fgets
Chương trình đọc các dòng ký tự trên tệp “dongVB” và in ra màn hình
----------------------------------------------…
int i=0; char d[256];while(!feof())
6565CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
while(!feof()){
i++;fgets(d, 256, f);printf(“Dong %d: %s”,i,d);
}
…
Các hàm nhập xuất theo kiểu nhị phân
• Ghi một số nguyên (2byte) lên fileint putw(int n, FILE *f)• Đọc một số nguyên (2byte) lên fileint getw(FILE *f)• Ghi một số mẫu tin lên file
6666CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
int fwrite(void *ptr, int size, int n, FILE *f)• Đọc một số mẫu tin từ fileint fread(void *ptr, int size, int n, FILE *f)
ptr: con trỏ trỏ tới vùng nhớ chứa dữ liệu đọc đượcsize: kích thước mẫu tin theo byten: số mẫu tin cần đọcf: con trỏ tệp
Câu hỏi và thảo luận
6767CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
Đại Học Sư Phạm Tp. Hồ Chí MinhĐại Học Sư Phạm Tp. Hồ Chí Minh
CẤU TRÚC DỮ LI ỆU 2 CẤU TRÚC DỮ LI ỆU 2
Chương 02: BẢNG BĂM
Đề cương môn học: CTDL2CTDL2
• Chương 1: Sắp xếp ngoại
• Chương 2: Bảng băm (Hash Table)
• Chương 3: B – Cây (B-Tree)
• Chương 4: Cây Đỏ Đen (Red-Black Tree)
22CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
Nội dung
• Giới thiệu bài toán
• Hàm băm
• Các phương pháp xử lý đụng độ
• Phân tích phép băm
33CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
• Phân tích phép băm
ĐẶT VẤN ĐỀ
• Cho S là tập hợp n phần tử trong 1 cấu trúc dữ liệu được đặc trưng bởi 1 giá trị khóa
• Tìm 1 phần tử có hay không trong S– Tìm tuyến tính (O(n)), chưa được sắp xếp
– Tìm nhị phân (O(log n)), đã được sắp xếp
44CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
– Tìm nhị phân (O(log2n)), đã được sắp xếp
• Có hay chăng 1 thuật toán tìm kiếm với O(1)– Có, song ta phải tổ chức lại dữ liệu
– Dữ liệu được tổ chức lại là Bảng băm
Giới thi ệu về Bảng Băm
• Là CTDL trong đó các phần tử của nó được lưu trữsao cho việc tìm kiếm sẽ được thực hiện bằng cáchtruy xuất trực tiếp thông qua từ khóa.
• Bảng băm có M vị trí được đánh chỉ mục từ 0 đến M-1, M là kích thước của bảng băm.
• Các phương pháp băm:
55CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
• Các phương pháp băm:– PP kết nối trực tiếp
– PP kết nối hợp nhất
– PP dò tuyến tính
– PP dò bậc 2
– PP băm kép
Hàm băm
• Hàm băm: biến đổi khóa thành chỉ mục trên bảng băm– Khóa có thể là dạng số hay dạng chuỗi– Chỉ mục được tính từ 0..M-1, với M là số chỉ mục
của bảng băm
66CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
– Hàm băm thường dùng: key % Mkey % M, với M là độ lớn của bảng băm
• Hàm băm tốt phải thoả yêu cầu– Giảm thiểu xung đột– Phân bố đều trên M địa chỉ khác nhau của bảng
băm
Mô tả dữ liệu
• K: tập các khoá (set of keys)
• M: tập các địa chỉ (set of addresses).
• HF(k): hàm băm dùng để ánh xạ một khoá k từ tập các khoá K thành một địa chỉ tương ứng trong tập M. Thông thường HF(k) = k mod M
77CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
M. Thông thường HF(k) = k mod M
Ưu điểm bảng băm
• Dung hòa tốt giữa thời gian truy xuất và dung lượng bộ nhớ– Nếu ko giới hạn bộ nhớ: one-to-one, truy xuất
tức thì
– Nếu dung lượng bộ nhớ có giới hạn thì tổ chức
88CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
– Nếu dung lượng bộ nhớ có giới hạn thì tổ chức khóa cùng địa chỉ
• Bảng băm ứng dụng nhiều trong thực tế, thích hợp tổ chức dữ liệu có kích thước lớn và lưu trữ ngoài.
CÁCH XÂY D ỰNG BẢNG BĂM
– Dùng hàm băm để ánh xạ khóa K vào 1 vị trí trong bảng băm. Vị trí này như là 1 địa chỉ khi tìm kiếm.
– Bảng băm thường là mảng, danh sách liên
99CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
– Bảng băm thường là mảng, danh sách liên kết, file(danh sách đặc)
Ví dụ một bảng băm đơn giản
Khóa k sẽ được lưu trữ tại vị trí k mod M (M kích thước mảng)
0 1 2 3 4 5 6 7 8 9
1010CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
0 1 2 3 4 5 6 7 8 9
95
Thêm phần tử x = 95 vào mảng 95 mod 10 = 5
Ví dụ một bảng băm đơn giản
Với các giá trị: 31, 10, 14, 93, 82, 95,79,18, 27, 46
0 1 2 3 4 5 6 7 8 9
1111CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
0 1 2 3 4 5 6 7 8 9
10 31 82 93 14 95 46 27 18 79
Tìm ki ếm trên bảng băm
• Thao tác cơ bản nhất được cung cấp bởi Hashtable là “tìm kiếm”
• Chi phí tìm kiếm trung bình là O(1), không phụ thuộc vào số lượng phần tử của mảng
1212CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
phụ thuộc vào số lượng phần tử của mảng (Bảng)
• Chi phí tìm kiếm xấu nhất (ít gặp) có thể là O(n)
Các phép toán trên hàm băm
• Khởi tạo (Initialize)• Kiểm tra rỗng (Empty)• Lấy kích thước bảng băm (size)• Thêm 1 phần tử vào bảng băm (Insert)
1313CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
• Thêm 1 phần tử vào bảng băm (Insert)• Xóa 1 phần tử khỏi bảng băm (Remove)• Duyệt (Traverse)
Vấn đề nảy sinh
Giả sử thêm 55vào mảng
0 1 2 3 4 5 6 7 8 982 95 27
1414CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
82 95 27
+ 55phải lưu vào vị trí 5. Tuy nhiên vị trí này đã có chứa 95
k1 ≠ k2 mà f(k1) = f(k2) � Đụng độ=> Cần giải quyết đụng độ (xung đột)đụng độ (xung đột)
- Trong thực tế có nhiều trường hợp có nhiềuhơn 2 phần tử sẽ được “băm” vào cùng 1 vị trí
Vấn đề xung đột khi xử lý bảng băm
1515CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
- Hiển nhiên phần tử được “băm” đầu tiên sẽchiếm lĩnh vị trí đó, các phần tử sau cần phảiđược lưu vào các vị trí tr ống khác sao cho vấnđề truy xu ất và tìm ki ếm phải dễ dàng
a. Làm giảm xung đột
-Hàm băm cần thỏa mãn các điều kiện:�Xác xuất phân bố khoá là đều nhau�Dễ dàng tính toán thao tác�Ít xảy ra đụng độ
1616CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
�Ít xảy ra đụng độ
Thông thường, hàm băm sử dụng các số nguyên tố (vì xác suất ngẫu nhiên phân bố các số nguyên tố là đều nhất)
b. Giải quyết xung đột
Các phương pháp băm:�PP kết nối trực tiếp�PP kết nối hợp nhất�PP dò tuyến tính
1717CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
�PP dò tuyến tính�PP dò bậc 2�PP băm kép
i. Sử dụng DS liên kết (kết nối tr ực tiếp)
-Ý tưởng: “Các phần tử băm vào trùng vị trí k được nối vào danh sách nối kết” tại vị trí đó
0 1 2 3 4Hàm băm:
1818CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
0 1 2 3 421 18
Hàm băm:F(k) = k mod 5
Thêm 6, 16 6
16
*Phân tích
PP DSLK có nhiều khuyết điểm:- Khi có quá nhiều khoá vào cùng vị trí,
DSLK thì tại vị trí đó sẽ rất dài => Tăng chi phí tìm kiếm
1919CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
tìm kiếm- Các ô trống còn dư nhiều => lãng phí về
thời gian tìm kiếm và không gian lưu trữ
Cài đặt - Coding
- Sử dụng DSLK tại mỗi vị trí lưu trữ- Nếu xảy ra xung đột thì lưu vào cuối DS
tại vị trí trùng
2020CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
0 1 2 3 421 18
Hàm băm:F(k) = k mod 5
Thêm 6, 16 6
16
CÀI ĐẶT
• Khai báo cấu trúc dữ liệu• Khởi tạo bảng băm• Tạo 1 nút để thêm vào bảng băm• Xác định hàm băm• Thêm 1 nút vào bảng băm
2121CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
• Thêm 1 nút vào bảng băm• Xóa 1 phần tử trong bảng băm• Tìm 1 phần tử trong bảng băm.
Khai báo CTDL
const int M = 101; //Kích thước bảng bămstruct node{
int key;
2222CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
int key;node* next;
};typedef node* LINKLIST ;LINKLIST HashTable[M]; //bảng băm
Khởi tạo bảng bămvoid Init_HashTable(){
for (int i = 0 ; i< M; ++ i)HashTable[i] = NULL;
}
2323CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
}//Xác định hàm bămint Hash(int key){
return (key % M);}
Tạo 1 nút để thêm
//tạo nút có trường dữ liệu là x, hàm trả về địa chỉ của node mới tạo.
node* GetNode(int x){
node *pnew = new node;
2424CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
node *pnew = new node;pnew->key = x;pnew->next = NULL;return pnew;
}
Ki ểm tra bảng băm rỗng?
bool Empty(){
for(int b = 0; b < M; b++)if(HashTable[b] != NULL)
2525CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
if(HashTable[b] != NULL)return false;
return true;}
Hàm xuất bảng bămvoid PrintHT(){
node *p;for(int i=0;i<M;i++){
cout<<"Bucket "<<i<<": ";
2626CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
cout<<"Bucket "<<i<<": ";p = HashTable[i];while(p!=NULL){
cout<<“ � “<<p->key;p = p->next;
}cout<<endl;
}}
Thêm một khoá vào bảng băm//Chèn một khoá vào bảng bămvoid Insert(int k){
InsertTail_LINKLIST(HashTable[Hash(k)], k);}//Chèn cuối danh sáchvoid InsertTail_LINKLIST(LINKLIST &l, int k){
2727CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
{//Tạo nodenode *add = GetNode(k);if (l == NULL) l = add;else{
node * p = l;while (p->next != NULL) p = p->next;p->next = add;
}}
Xoá một khoá trong bảng băm
//Hàm xóa 1 phần tử có khóa keyvoid Delete(int key){
Delete_LINKLIST(HashTable[Hash(key)], key);}
2828CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
}
Xoá một khoá trong bảng bămvoid Delete_LINKLIST(LINKLIST &l, int key){
node *p = l, *q = NULL;if(p == NULL) //DS rong
cout<<endl<<"Khong tim thay - DS rong!"<<endl;else //tim thay{
2929CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
{if(p->key==key)//Nam dau danh sach{
l = p->next;delete p;cout<<endl<<"Da xoa!"<<endl;
}
Xoá một khoá trong bảng bămelse{
while((p != NULL)&&(p->key != key)){
q = p; p = p->next;}if(p != NULL) //tim thay{
3030CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
{q->next = p->next;delete p;cout<<endl<<"Da xoa!"<<endl<<endl;
}else
cout<<"KQ: Khong tim thay"<<endl;}
}}
Tìm một phần tử
// tim 1 phan tu co khoa =key trong bang bamnode* Search(int x){ int i = Hash(x);
node* p = HashTable[i];if(p != NULL){
3131CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
{while((p != NULL)&&(p->key != x))
p = p->next;}return p;
}
Hàm tạo menu chương trìnhvoid menu(){
puts("DEMO HASHTABLE dung DSLK");puts("1. Them 1 phan tu vao bang bam");puts("2. Xoa 1 phan tu trong bang bam");
3232CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
puts("2. Xoa 1 phan tu trong bang bam");puts("3. Tim 1 phan tu co khoa x");puts("4. Xuat Hash Table");puts("0. Ket thuc");
}
Chương trình chính
int main(){
int chon, x;Init_HashTalbe();//khoi tao bang bamdo
3333CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
do{ menu();
cout<<"Chon chuc nang: ";cin>>chon;cout<<endl;
Chương trình chínhswitch(chon){
case 1:do{
cout<<"Nhap khoa can them: "; cin>>x;if(x > 0) Insert(x);
3434CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
if(x > 0) Insert(x);}while(x > 0);break;
case 2:cout<<"Nhap khoa can xoa (key > 0): ";cin>>x;if(x > 0) Delete(x);break;
Chương trình chínhcase 3:
cout<<"Nhap khoa can tim (key > 0): ";cin>>x;if(x > 0){
if(Search(x) != NULL)cout<<"Tim thay “<<x;
else
3535CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
elsecout<<"Tim khong thay";
}break;
case 4: PrintHT(); break;}
}while(chon != 0);return 0;
}
ii. Sử dụng PP “kết nối hợp nhất”
-Ý tưởng: “Nếu có 1 khóa bị băm vào vị trí đã có phần tử thì nó sẽ được chèn vào ô trống phía cuối mảng”. (Dùng mảng có M phần tử)
0
3636CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
Hàm băm:F(k) = k mod 5Thêm
6, 16
0
1 21
2
3 18
4 6
16
iii. Sử dụng PP “Dò tuyến tính”
-Ý tưởng: “Nếu có 1 khóa bị băm vào vị trí đã có phần tử thì nó sẽ được chèn vào ô trống gần nhất” theo phía bên phải (hoặc trái)
0 1 2 3 4Hàm băm:
3737CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
0 1 2 3 421 18
Hàm băm:F(k) = k mod 5
Thêm 6, 16
6 16
f(key)=(f(key)+i) % M với f(key) là hàm băm chính của bảng băm.
*Phân tích
- PP này dễ thực hiện- Nếu có nhiều phần tử băm trùng nhau thì
đặc tính bảng băm bị mất đi- Trong trường hợp xấu nhất tìm kiếm trên
3838CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
- Trong trường hợp xấu nhất tìm kiếm trên bảng băm thành tìm kiếm tuyến tính trên mảng
Cài đặt
-Khi xảy ra đụng độ thì chèn vào vị trí trống gần nhất- Ví dụ: chèn dãy: 5 16 7 8 2 4 6 3 13 24 vào mãng băm có 11 vị trí
3939CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
vào mãng băm có 11 vị trí
0 1 2 3 4 5 6 7 8 9 10
24 2 3 4 5 16 7 8 6 13
code
const int M = 101; //Kich thuoc bảng băm
int HashTable[M]; //bảng băm
4040CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
Khởi tạo bảng băm
void Init_HashTalbe(){
for (int i = 0 ; i< M; ++ i)HashTalbe[i] = -1 ;
4141CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
HashTalbe[i] = -1 ;}
Ki ểm tra bảng băng rỗng?
bool Empty(){
for(int b = 0; b < M; b++)if(HashTable[i] != -1)
4242CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
if(HashTable[i] != -1)return false;
return true;}
Thêm một khoá vào bảng bămvoid Insert(int k){
//Xác định vị trí của khoá kint pos = Hash(key)//Kiểm tra đảm bảo vị trí pos là trốngwhile (HashTable[pos] != -1 )
4343CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
while (HashTable[pos] != -1 ){
pos = Hash (pos + 1);//Kiểm tra full
}
HashTable[pos] = key;}
Xoá một khoá trong bảng băm
int Delete(int key){
int pos = Hash(key); count = 1;while (HashTable[pos] != key){
pos = Hash(pos + 1 );count ++;
4444CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
count ++;if (count > M) break;
} if (count <= M){ HashTable[pos] = -1; return 1;}
return 0; //không tìm được khoá
}
iv. Sử dụng PP “Dò bậc hai”
0 1 2 3 4Hàm băm:
f(key)=(f(key) + i 2) % Mvới f(key) là hàm băm chính của bảng băm.
4545CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
0 1 2 3 421 18
Hàm băm:F(k) = k mod 5
Thêm 6, 16
616
iv. Sử dụng PP “Băm kép”
Ta sử dụng 2 hàm băm:f1(key)= key % Mf2(key)= (M–2) – key % (M-2)
4646CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
f2(key)= (M–2) – key % (M-2)
Cài đặt – Băm kép (Double Hashing)
-Dò tuyến tính: pos = (pos + 1) % M
4747CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
-Dò tuyến tính: pos = (pos + 1) % M- Băm kép: pos = (pos + u) % M
u = Hash2 (key)
code
const int M = 101; //Kich thuoc bảng băm
int HashTable[M]; //bảng băm
4848CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
Khởi tạo bảng băm
void Init_HashTalbe(){
for (int i = 0 ; i< M; ++ i)HashTalbe[i] = -1 ;
4949CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
HashTalbe[i] = -1 ;}
2 Hàm băm
int Hash(int key){
return key % M}
5050CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
int Hash2(int key){
return (M-2) – key % (M-2);}
Thêm một khoá vào bảng bămvoid Insert(int k){ //Xác định vị trí của khoá k
int pos = Hash(key)//Kiểm tra đảm bảo vị trí pos là trốngwhile (HashTable[pos] != -1 ){
int u = Hash2 (key);
5151CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
int u = Hash2 (key);pos = (pos + u ) % M;//Kiểm tra full
}
HashTable[pos] = key;}
Bài tập
Viết chương trình hiện thực từ điển Anh - Việt. Mỗi nút của bảng băm có khai báo các trường sau:– Trường word là khoá chứa một từ tiếng anh.– Trường mean là nghĩa tiếng Việt.– Trường next là con trỏ chỉ nút kế nếu bị xung đột.
Tập khoá là một chuỗi tiếng anh, tập địa chỉ có 26 chữ cái. Chọn hàm băm sau cho khoá bắt đầu bằng ký tự a được băm
5252CTDL2 – Lương Trần Hy HiếnLương Trần Hy Hiến
Chọn hàm băm sau cho khoá bắt đầu bằng ký tự a được băm vào địa chỉ 0, b băm vào địa chỉ 1,…, z băm vào địa chỉ 25. Chương trình có những chức năng như sau:1. Nhập vào một từ2. Xem từ điển theo ký tự đầu.3. Xem toàn bộ từ điển.4. Tra từ điển.5. Xoá một từ, xóa toàn bộ từ điển.
Đại Học Sư Phạm Tp. Hồ Chí MinhĐại Học Sư Phạm Tp. Hồ Chí Minh
CẤU TRÚC DỮ LI ỆU 2 CẤU TRÚC DỮ LI ỆU 2
Chương 03: B-Cây
Đề cương môn học: CTDL2CTDL2
• Chương 1: Sắp xếp ngoại• Chương 2: Bảng băm (Hash Table)• Chương 3: B – Cây (B-Tree)• Chương 4: Cây Đỏ Đen (Red-Black Tree)
22CTDL2 – HIENLTHHIENLTH, HCMUP
Nội dung
• Đặt vấn đề• B-Tree• Các phép biến đổi• Ứng dụng của B-Tree
33CTDL2 – HIENLTHHIENLTH, HCMUP
• Ứng dụng của B-Tree
Đặt vấn đề
• Cần lưu trữ số phần tử dữ liệu rất lớn
• Lưu trữ trên bộ nhớ ngoài
44CTDL2 – HIENLTHHIENLTH, HCMUP
• Tìm kiếm nhanh
Giải quyết
• Thao tác tìm kiếm trên cây tỉ lệ thuận với chiều cao của cây. Nếu cây có N nút thì.
– Chiều cao của cây nhị phân tìm kiếm cân bằng log2N = chi phí tìm kiếm.≤
55CTDL2 – HIENLTHHIENLTH, HCMUP
– Cây 2-3-4 (mỗi nút có nhiều nhất 4 khoá) -> chiều cao log4N.
– Chưa phù hợp khi lưu trữ và truy xuất trên đĩa
≤
Giải quyết
• Dùng 1 loại cây khác nhằm mục đích – Phân trang dữ liệu
• Tăng số nhánh của cây -> Giảm chiều cao của cây
• Gom nhóm dữ liệu thành những block-> giảm
66CTDL2 – HIENLTHHIENLTH, HCMUP
• Gom nhóm dữ liệu thành những block-> giảm số lần truy xuất trên đĩa
⇒Dùng B-Cây (1 loại cây nhiều nhánh) thích hợp với việc lưu trữ và truy xuất trên bộ nhớ ngoại - đĩa cứng
B-Tree
• Định nghĩa:B-Tree bậc n có các t/c:
– Mỗi nút có tối đa 2*n khóa– Mỗi nút (không là gốc) có ít nhất n nút
77CTDL2 – HIENLTHHIENLTH, HCMUP
– Mỗi nút hoặc là lá hoặc có m+1 nút con– Các khóa được sắp tăng dần từ trái sang phải– Các nút lá nằm cùng một mức
Ưu điểm B-Tree
• B-cây là dạng cây cân bằng, phù hợp với việc lưu trữ trên đĩa
• B-cây tiêu tốn số phép truy xuất đĩa tối thiểu cho các thao tác
88CTDL2 – HIENLTHHIENLTH, HCMUP
thiểu cho các thao tác
• Có thể quản lý số phần tử rất lớn
Chiều cao B-Tree
• N: Số khoá (key),
• m: Bậc của cây, m > 2 �cấp (m-1)/2
1≥N
99CTDL2 – HIENLTHHIENLTH, HCMUP
2
1log
+≤ Nh
m
Khai báo CTDL
struct NodeType{
int numtree;//số cây conint Key[Order];//mảng lưu các khóa của node
1010CTDL2 – HIENLTHHIENLTH, HCMUP
int Key[Order];//mảng lưu các khóa của nodeNodeType* Branch[Order+1];//con trỏ trỏ đến
node con
};typedef NodeType* NODEPTR;NODEPTR * Root;//con trỏ trỏ tới nút gốc
Các phép toán trên cây
• Tìm 1 phần tử có khóa bằng X trong cây
• Thêm 1 khoá vào vào B –Tree
• Xóa 1 khoá trong 1 nút
1111CTDL2 – HIENLTHHIENLTH, HCMUP
• Xóa 1 khoá trong 1 nút
Tìm ki ếm phần tử có khóa X trên cây
• Việc tìm kiếm được thực hiện tuần tự giống như trong cây nhị phân tìm kiếm:– Bắt đầu từ gốc.– Duyệt cây theo kiểu top-down.– Tại mỗi node so sánh khóa cần tìm với các
1212CTDL2 – HIENLTHHIENLTH, HCMUP
– Tại mỗi node so sánh khóa cần tìm với các giá trị khóa của node đó để tìm nhánh con cần duyệt tiếp theo.
• Có thể áp dụng phương pháp tìm kiếm nhị phân để tìm một khóa trong nội bộ một node.
Thêm 1 nút vào B-Tree
• Tính chất cây B (B-tree): một khối có ít nhất một nữa số khóa
• Thêm 1 nút có khóa X vào B-Tree– Thêm X vào 1 nút lá– Sau khi thêm, nếu nút lá đầy:
1313CTDL2 – HIENLTHHIENLTH, HCMUP
– Sau khi thêm, nếu nút lá đầy: • Tách nút lá ra làm đôi• Chuyển phần tử giữa lên nút cha và lan
truyền ngược về gốc.• Nếu gốc bị tách, cây được đặt ở mức sâu
hơn
Thêm 1 nút vào cây B-Tree
• Nếu số khóa lớn hơn 2n thì tách trang:– Đưa phần tử giữa lên trang cha– Tạo thêm trang mới– Chuyển dời một nửa phần tử sang trang mới– Tiếp tục lan truyền ở trang cha (nếu trang cha
1414CTDL2 – HIENLTHHIENLTH, HCMUP
– Tiếp tục lan truyền ở trang cha (nếu trang cha sau khi thêm > 2n phần tử thì thực hiện tách trang như trên).
Cây B (n = 1) – Chèn
• Chèn– Chèn 9– Node bị tràn,
phân tách nó– Đẩy node giữa (8)
1515CTDL2 – HIENLTHHIENLTH, HCMUP
– Đẩy node giữa (8)– Gốc bị tràn,
phân tách nó– Đẩy node giữa (6)– Node gốc mới hình thành– Chiều cao tăng 1
Ví dụ thao tác thêm (B-Tree: n = 1)
Thêm các nút: 1,2,3,4,5,6,7
1616CTDL2 – HIENLTHHIENLTH, HCMUP
Ví dụ thao tác thêm (B-Tree: n = 2)
• Cho B-tree rỗng. Lần lượt thêm giá trị các
khóa sau (theo thứ tự) vào B-tree: 1, 12, 8,
2, 25, 5, 14, 28, 17, 7, 52, 16, 48, 68, 3,
1717CTDL2 – HIENLTHHIENLTH, HCMUP
26, 29, 53, 55, 45.
• Cần xây dựng B-tree bậc 2.
Ví dụ thao tác thêm (B-Tree: n = 2)• Bốn phần tử đầu tiên
được đưa vào nút gốc• Nếu đưa phần tử thứ năm
vào nút gốc sẽ làm vi phạm điều kiện cây B-
1 2 8 12
1 2
8
12 25
1818CTDL2 – HIENLTHHIENLTH, HCMUP
phạm điều kiện cây B-tree.
• Do đó, khi thêm khóa 25, tách nút gốc thành 2 nút và đưa khóa ở giữa lên để tạo nút gốc mới.
1 2 12 25
Ví dụ thao tác thêm (B-Tree: n = 2)
Thêm các khóa 6, 14, 28 vào các nút lá:
1 2
8
12 146 25 28
Nút lá bên phải đã đầy (đã có 4 phần tử). Do đó, 8 17
1919CTDL2 – HIENLTHHIENLTH, HCMUP
(đã có 4 phần tử). Do đó, khi thêm khóa 17 vào nút lá bên phải sẽ làm nút lá bị “quá tải”. Lấy khóa ở giữa đưa lên nút cha (hiện tại là nút gốc) và phân chia nút hiện tại.
8 17
12 14 25 281 2 6
Ví dụ thao tác thêm (B-Tree: n = 2)
Thêm các khóa 7, 52, 16, 48 vào các nút lá
8 17
12 14 25 281 2 6 16 48 527
Thêm khóa 68 vào, cần tách nút lá ở bên phải, đưa 48 lên nút gốc
2020CTDL2 – HIENLTHHIENLTH, HCMUP
lên nút gốc
Thêm khóa 3 vào, cần tách nút lá ở bên trái, đưa khóa 3 lên nút gốc
3 8 17 48
52 6825 281 2 6 7 12 14 16
Ví dụ thao tác thêm (B-Tree: n = 2)
Thêm các khóa 26, 29, 53, 55vào các nút lá
3 8 17 48
52 53 55 6825 26 28 291 2 6 7 12 14 16
Thêm khóa 45vào, cần tách và đưa khóa 28
2121CTDL2 – HIENLTHHIENLTH, HCMUP
Thêm khóa 45vào, cần tách và đưa khóa 28lên nút gốc. Khi đó, nút gốc sẽ “quá tải” và cần tách tiếp.
25 26 28 29
17
3 8 28 48
1 2 6 7 12 14 16 52 53 55 6825 26 29 45
Xóa 1 phần tử trên B-Cây bậc n
• Khóa cần xóa trên trang lá � Xóa bình thường.
• Khóa cần hủy không trên trang lá:– Tìm phần tử thay thế: Trái nhất (hoặc phải nhất)
trên hai cây con cần tìm
2222CTDL2 – HIENLTHHIENLTH, HCMUP
trên hai cây con cần tìm– Thay thế cho nút cần xóa
• Sau khi xóa, trang bị thiếu (vi phạm đk B-Tree):– Hoặc chuyển dời phần tử từ trang thừa– Hoặc ghép với trang bên cạnh (trái/phải)
Ví dụ về xóa
• Giả sử đã xây dựng B-cây như sau:
9 20
37
28 3217
12
15 44
24
7 42 4822
2323CTDL2 – HIENLTHHIENLTH, HCMUP
• Xóa 48
9 20
37
28 3217
12
15 44
24
7 4222
Ví dụ về xóa
• Xóa 15:
9 20
37
28 3217
12
44
24
7 4222
2424CTDL2 – HIENLTHHIENLTH, HCMUP
• Xóa 44 (gộp trang)
9 20 3728 3217
12 24
7 4222
Ví dụ về xóa
• Xóa 7 (mượn trang phải)
• Xóa 24, ta đem khóa 22 lên thay thế. Khi đó 12 20 3728 32
17 24
9 4222
2525CTDL2 – HIENLTHHIENLTH, HCMUP
• Xóa 24, ta đem khóa 22 lên thay thế. Khi đó trang 20,22 chỉ còn 20 (phạm), ta phải đem khóa 22 trở lại trang 20,22. Mang 28 lên thêm
12 20 3732
17 28
9 4222
Ví dụ về xóa
• Xóa 20: Mượn trang phải 1 phần tử. Tức mang 32 lên cha, 28 xuống nút có 1 khóa là 22
17 32
2626CTDL2 – HIENLTHHIENLTH, HCMUP
9 22 3712 4228
Ví dụ xóa nút trong B-Tree (tt)
• Xóa 28:
9 22 3712
17
32 42
2727CTDL2 – HIENLTHHIENLTH, HCMUP
• Xóa 9
12 3717
22
32 42
Ví dụ xóa nút trong B-Tree (tt)
• Xóa 37
12 17
22
32 42
2828CTDL2 – HIENLTHHIENLTH, HCMUP
• Xóa 1712 22 32 42
B-tree: Cân bằng lại cây sau khi xóa
• Nếu một trong các nút anh em kế cận nút đang xét có số lượng khóa nhiều hơn số lượng tối thiểu– Đưa một khóa của nút anh em lên nút cha.– Đưa một khóa ở nút cha xuống nút đang xét.
• Nếu tất cả các nút anh em kế cận nút đang xét đều
2929CTDL2 – HIENLTHHIENLTH, HCMUP
• Nếu tất cả các nút anh em kế cận nút đang xét đều có số lượng khóa vừa đủ số lượng tối thiểu.– Chọn một nút anh em kế cận và hợp nhất nút anh
em này với nút đang xét và với khóa tương ứng ở nút cha.
– Nếu nút cha trở nên thiếu khóa, lặp lại quá trình này.
Trường hợp:Nút anh em kế cận còn đủ khóa để bổ sung
1212 2929
77 99 1515 2222 696956563131 4343
Delete 22 Đưa khóa từ nút cha xuốngĐưa khóa từ nút anh em kế cận lên
3030CTDL2 – HIENLTHHIENLTH, HCMUP
77 99 1515 2222 696956563131 4343
1212
292977 99 1515
3131
696956564343
Trường hợp:
1212 2929 5656
Hợp nhất
Nút đang xét và nút anh em kế cận đề cònquá ít khóa
3131CTDL2 – HIENLTHHIENLTH, HCMUP
77 99 1515 2222 6969 72723131 4343
Delete 72
Còn quá ít khóa
1212 2929
77 99 1515 2222 696956563131 4343
VD 2 – Xoá 1 khoá trong B-Tree cấp 1
• Ví dụ ta có cây như sau:
3232CTDL2 – HIENLTHHIENLTH, HCMUP
• Xoá nút 26 thì ta làm sao:
VD 2 – Xoá 1 khoá trong B-Tree (tt)
• Dùng 28 để thay thế
3333CTDL2 – HIENLTHHIENLTH, HCMUP
VD 2 – Xoá 1 khoá trong B-Tree (tt)
• Xoá khóa 22 dùng 24 thay thế, thiết nút lá
3434CTDL2 – HIENLTHHIENLTH, HCMUP
Xoá 1 nút trong B - Tree
3535CTDL2 – HIENLTHHIENLTH, HCMUP
VD 2 – Xoá 1 khoá trong B-Tree (tt)• Xoá khoá 18, 8 thay thế
3636CTDL2 – HIENLTHHIENLTH, HCMUP
VD 2 – Xoá 1 khoá trong B-Tree (tt)
3737CTDL2 – HIENLTHHIENLTH, HCMUP
Cây B trên đĩa
• Các khối đĩa– 512 - 8k bytes ∴100s of keys�Dùng tìm kiếm nhị phân cho các khối
• Tổng quát
3838CTDL2 – HIENLTHHIENLTH, HCMUP
• Tổng quát– O( log n )– Làm hợp với phần cứng !
• Thủ tục xóa tương tự (Deletion)– Tuy nhiên, phải hội nhập các khối (block) để bảo đảm
tính chất B-tree (ít nhất bằng nửa số lượng khóa)
Ví dụ
3939CTDL2 – HIENLTHHIENLTH, HCMUP
Ví dụ
4040CTDL2 – HIENLTHHIENLTH, HCMUP
Cây B(Block) (B-trees)
• Tất cả các lá nằm trên cùng một mức• Tất cả các node ngoại trừ gốc và các lá có:
– Ít nhất m/2 con– Nhiều nhất m con
• Cây B+ (B+ trees)
Mỗi node ch ứa ít nhấtmột nửa số lượng khóa
4141CTDL2 – HIENLTHHIENLTH, HCMUP
• Cây B+ (B+ trees)– Tất cả các khóa trong các node là giả– Chỉ các khóa trong các lá nhận giá trị thực “real”– Liên kết các lá
• Có khả năng duyệt hết danh sách theo thứ tự giữakhông cần thông qua các node cao hơn.
Cây B+
• Cây B+– Tất cả các khóa trong các node là giả– Chỉ các khóa trong các lá nhận giá trị thực “real”– Các bản ghi dữ liệu được giữ trong các vùng
riêng
4242CTDL2 – HIENLTHHIENLTH, HCMUP
riêng
Cây B+ -Duyệt theo thứ tự giữa
• Cây B+ (B+ trees)– Liên kết các lá
• Có khả năng duyệt hết danh sách theo thứ tự giữa không cần thông qua các node cao hơn.
4343CTDL2 – HIENLTHHIENLTH, HCMUP
Cây (B+) –Sử dụng
• Sử dụng - Cơ sở dữ liệu lớn– Đọc một khối đĩa chậm hơn nhiều so với đọc bộ nhớ ( ~ms vs ~ns )
– Đặt từng khối của các khóa vào trong một khối đĩa
Physical disc blocks
4444CTDL2 – HIENLTHHIENLTH, HCMUP
Đọc thêm
• Tài liệu tham khảo– http://en.wikipedia.org/wiki/B-tree– http://www.bluerwhite.org/btree/– http://www.nist.gov/dads/HTML/btr
4545CTDL2 – HIENLTHHIENLTH, HCMUP
– http://www.nist.gov/dads/HTML/btree.html
– http://www.nist.gov/dads/HTML/bstartree.html
Luyện tập
• Cho B-tree bậc 2 gồm các khóa sau (chèn vào theo thứ tự):3, 7, 9, 23, 45, 1, 5, 14, 25, 24, 13, 11, 8, 19, 4, 31, 35, 56
4646CTDL2 – HIENLTHHIENLTH, HCMUP
• Thêm khóa: 2, 6, 12, 0, 10, 11
• Xóa khóa: 4, 5, 7, 3, 14
Câu hỏi và thảo luận
4747CTDL2 – HIENLTHHIENLTH, HCMUP
Đại Học Sư Phạm Tp. Hồ Chí MinhĐại Học Sư Phạm Tp. Hồ Chí Minh
CẤU TRÚC DỮ LI ỆU 2 CẤU TRÚC DỮ LI ỆU 2
Chương 04: CÂY ĐỎ ĐEN
Ôn tập cây nhị phân
• Xem lại các kiến thức liên quan đến cây nhị phân [tìm kiếm [cân bằng]]]
• Độ cao của cây nhị phân tìm kiếm cân bằng N node là O(logN)
• Cây nhị phân cân bằng có chi phí thấp nhất.
22CTDL2 – HIENLTHHIENLTH, HCMUP
• Cây nhị phân cân bằng có chi phí thấp nhất.• Các loại cây tìm kiếm cân bằng:
– AVL Tree– Red – Black Tree– AA Tree– Splay Tree
a. Khái niệm cây đỏ đen
-Là cây nhị phân tìm kiếm-Đưa thêm yếu tố màu (RED, BLACK ) để làm cơ sở cho sự cân bằng.
33CTDL2 – HIENLTHHIENLTH, HCMUP
cơ sở cho sự cân bằng.
Các tính chất
1. Mọi nút chỉ có thể là đỏ (RED) hoặc đen(BLACK)
2. Nút gốc mang màuđen. Mọi nút lá (NIL)mangmàuđen.
44CTDL2 – HIENLTHHIENLTH, HCMUP
mangmàuđen.3. Nếu 1 nút làđỏ thì con của nó phải là đen
(nghĩa là không có 2 nútđỏ liên tiếp)4. Tất cả cácđường đi từ một nút đã cho tới các
lá chứamột số như nhaucác nútđen.
Ví dụ:
55CTDL2 – HIENLTHHIENLTH, HCMUP
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
66CTDL2 – HIENLTHHIENLTH, HCMUP
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 đỏ - đỏ.
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)
77CTDL2 – HIENLTHHIENLTH, HCMUP
• 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)
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)
88CTDL2 – HIENLTHHIENLTH, HCMUP
• Đị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)
b. Biểu diễn cây đỏ - đen
struct Node{
int Key; //Dữ liệuNode* pLeft, *pRight;int color; //RED - BLACKNode* pParent; //Trỏ đến nút cha
99CTDL2 – HIENLTHHIENLTH, HCMUP
Node* pParent; //Trỏ đến nút cha };
typedef Node* pNode;struct RBTree{
pNode root;};
c. Một số thao tác đơn giản (tự viết)
+ Tìm kiếm và duyệt cây (giống BST)+ Thêm node mới+ Xóa node
1010CTDL2 – HIENLTHHIENLTH, HCMUP
+ Khởi tạovoid Init (RBTree &t);
+ Kiểm tra r ỗng int isEmpty (RBTree t);
d. Xuất cây ra màn hình
void PrintTree (RBTree t){
if (isEmpty(t)){
1111CTDL2 – HIENLTHHIENLTH, HCMUP
cout<<“Cây rỗng”;return;
}Print(t.root, 0):
}
d. Xuất cây ra màn hình (tt)
void Print (pNode p, int level){
if (!p){
textcolor(BLACK);
1212CTDL2 – HIENLTHHIENLTH, HCMUP
textcolor(BLACK);for (int i = 0 ; i < level; ++ i){
cout<<“ “;cout<<“NULL “<<endl;
}
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
1313CTDL2 – HIENLTHHIENLTH, HCMUP
elsetextcolor (BLACK);cout<<p->Key;
Print(p->pLeft , level +1)}
}
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á KB2. Phát sinh 1 nút mới có khoá K, màu
1414CTDL2 – HIENLTHHIENLTH, HCMUP
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)
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
1515CTDL2 – HIENLTHHIENLTH, HCMUP
• 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
void RBTree_Insertion(RBTree &root, int key){
x = getNode(key,RED, NIL);BSTree_Insert(root, x);
1616CTDL2 – HIENLTHHIENLTH, HCMUP
BSTree_Insert(root, x);Insertion_Fixup(root, x);
}
Gọi:
• X: Con trỏ, trỏ đến nút vừa chèn vào
• P: Con trỏ, nút cha của nút trỏ bởi x
• U: Con trỏ, trỏ đến nút
gg
uu
1717CTDL2 – HIENLTHHIENLTH, HCMUP
• U: Con trỏ, trỏ đến nút anh em của nút trỏ bởi p
• G: Con trỏ, trỏ đến nút cha của nút trỏ bởi p
pp
xx xx
uu
Cháu ngo ại Cháu nội
Một số định nghĩa
X là một node cháu ngoạinếu nó nằm cùng bênU U
1818CTDL2 – HIENLTHHIENLTH, HCMUP
nếu nó nằm cùng bênnode cha P và P cùng bênnode cha G.Ngược lại, X gọi là nodecháu nội .
U U
UU
* Phép quay phải tại y
yy
γ
1919CTDL2 – HIENLTHHIENLTH, HCMUP
xx
α β
γ
Phép quay (như BST)
yy
γxx
Quay phải
2020CTDL2 – HIENLTHHIENLTH, HCMUP
γxx
α βyy
γα
β
Quay trái
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:
2121CTDL2 – HIENLTHHIENLTH, HCMUP
• 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)
Trường hợp 1
• P đen � Bình thường (dừng)
2222CTDL2 – HIENLTHHIENLTH, HCMUP
Trường hợp 2
• P đỏ, U đỏ � Đảo màu G, P, U
gg gg
2323CTDL2 – HIENLTHHIENLTH, HCMUP
gg
pp
xx
uu
gg
pp
xx
uu
X
P
G
U
G
X
2424CTDL2 – HIENLTHHIENLTH, HCMUP
X
P U
Case 2 – P, U is Red
Just Recolor and move up
Trường hợp 3
• P đỏ, U đen, x là cháu ngoại � Quay tại P; Đổi màu P, G
2525CTDL2 – HIENLTHHIENLTH, HCMUP
X
P
G
U
S P
2626CTDL2 – HIENLTHHIENLTH, HCMUP
X
X G
S U
Case 3 – Zig-Zig
Single Rotate P around G
Recolor P and G
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
2727CTDL2 – HIENLTHHIENLTH, HCMUP
Tương tự TH3
X
P
G
U
S X
2828CTDL2 – HIENLTHHIENLTH, HCMUP
S
P G
SU
Case 4 – Zig-Zag
Double RotateX around P; X around G
Recolor G and X
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
β
β
2929CTDL2 – HIENLTHHIENLTH, HCMUP
p->pLeft ->pParent = x;//cha là xp->pParent = x->pParent;// cha của x là cha của y
//nếu x là nút gốcif (x->pParent == NULL)
t.root = y; //gốc mới sẽ là yelse
β
Hàm quay trái (tt)
//trường hợp else => x không phải là gốc
//Nếu x là con trái của cha nóif (x == (x->pParent)->pLeft)
x->pParent->pLeft = yelse
3030CTDL2 – HIENLTHHIENLTH, HCMUP
elsex->pParent->pRight = y;
y->pLeft = x;x ->pParent = y;
}
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
5050“ông” x
3131CTDL2 – HIENLTHHIENLTH, HCMUP
25257575
8080
x
“cha” x“bác” x
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)
5050 “ông” x
3232CTDL2 – HIENLTHHIENLTH, HCMUP
8080
x
“cha” x“bác” x2525
7575
TH3: Bác x đều có màu đen x là con phải của cha x
Quay trái tại ôngcủa x đồng thời đổi màu cha của x và ôngcủa x
5050
7575
5050
3333CTDL2 – HIENLTHHIENLTH, HCMUP
8080
2525
7575
100100 x
2525
7575100100
x
8080
5050
25258080
3434CTDL2 – HIENLTHHIENLTH, HCMUP
7575100100
110110
105105
x
TH4: x là con trái, cha x là phảihoặc x là con phải, cha x là trái
Quay trái (phải) tại cha (không đổi màu)5050
25258080
3535CTDL2 – HIENLTHHIENLTH, HCMUP
2525
7575100100
105105
110110
TH.3
CODEvoid 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)
3636CTDL2 – HIENLTHHIENLTH, HCMUP
while (x!=t.root && x->pParent->color==RED){
//cha x là con trá của ông xif ( x -> p == x->pParent->pParent->pLeft){
//y là “bác” của xy = x->pParent->pParent->pRight;
}
CODE
if (y->color == RED){ //TH1x->pParent->Color = BLACK;y->color = BLACK;x->pParent -> pParent -> color = REDx = x->pParent -> pParent;
3737CTDL2 – HIENLTHHIENLTH, HCMUP
x = x->pParent -> pParent;}
CODEelseif (x== x->pParent->pRight){ //TH3
x = x->pParent;LeftRotate(t,x);
}
3838CTDL2 – HIENLTHHIENLTH, HCMUP
}//TH2 luôn xảy ra sau đóX->pParent ->color = BLACK;X->pParent->pParent->color = RED;RightRotae(t,x->pParent->pParent);}
CODE
else //TH: cha của x là con phải của “ông”x{
3939CTDL2 – HIENLTHHIENLTH, HCMUP
{//Làm tương tự như trên,đổi pRight<->pLeft
}t.root -> color = BLACK;
Red-Black Trees
Insertion example
11
2 14
4040CTDL2 – HIENLTHHIENLTH, HCMUP
151 7
5 8
4 Violation of rule( after 4 added to the tree)
Red-Black Trees
Insertion example
11
2 14
4141CTDL2 – HIENLTHHIENLTH, HCMUP
151 7
5 8
4 Case 1
Red-Black Trees
Insertion example
11
7 14
4242CTDL2 – HIENLTHHIENLTH, HCMUP
152 8
4
1 5
Case 2
Red-Black Trees
Insertion example
2
77
11
4343CTDL2 – HIENLTHHIENLTH, HCMUP
4
1 5 14
15
8
Case 3
4444CTDL2 – HIENLTHHIENLTH, HCMUP
4545CTDL2 – HIENLTHHIENLTH, HCMUP
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.
4646CTDL2 – HIENLTHHIENLTH, HCMUP
• 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.
Gọi:
• y: Con trỏ, trỏ đến nút bị xóa thật sự
• x: Con trỏ, trỏ đến nút concủa nút trỏ bởi y, sẽ thay thế nút y
pp
ww
4747CTDL2 – HIENLTHHIENLTH, HCMUP
nút 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 của nút trỏ bởi y
xx
wwyy
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
4848CTDL2 – HIENLTHHIENLTH, HCMUP
• “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
Quy ước
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
4949CTDL2 – HIENLTHHIENLTH, HCMUP
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) được gán bất kỳ
Quy ước
pNode Null;void main(){
Null -> color = BLACK;Null ->pParent= Null->pLeft=Null->pRight = NULL;
5050CTDL2 – HIENLTHHIENLTH, HCMUP
Null ->pParent= Null->pLeft=Null->pRight = NULL;Null -> Key = 0;
}
Phân tích
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
5151CTDL2 – HIENLTHHIENLTH, HCMUP
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)
5252CTDL2 – HIENLTHHIENLTH, HCMUP
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
CODEvoid 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)
5353CTDL2 – HIENLTHHIENLTH, HCMUP
if (z->key > k)z= z->pLeft;
elsez= z->pRight;
}if (z==Null)
return ; //Không tìm thấy
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
5454CTDL2 – HIENLTHHIENLTH, HCMUP
else//y chỉ có thể có 1 con y = SearchStandFor(z);
CODE//Tiến hành xoá ypNode x; // x là nút con của yif (y->pLeft != Null)
x=y->pLeft; else
5555CTDL2 – HIENLTHHIENLTH, HCMUP
elsex = y->pRight;
//cha của x là cha của y//Nếu x là Null vẫn không báo lỗix->pParent = y->pParent;
CODE
if (y->pParent == Null) //y là gốct.root = x;
elseif (y->Parent->pLeft ==y)
5656CTDL2 – HIENLTHHIENLTH, HCMUP
if (y->Parent->pLeft ==y)y->pParent->pLeft = x;
elsey->pParent->pRight =x;
CODE
//Kiểm tra cân bằngif (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
5757CTDL2 – HIENLTHHIENLTH, HCMUP
FIXUP(t,x); // cân bằng lại
//Xoá yy->pLeft = y->pRight = y->pParent=Null;Delete y;
Cân bằng lại cây sau khi xoá một nút đen
x: con trỏ, trỏ tới nút đang thiếu đenw: con trỏ, trỏ tới nút anh/em của xp: con trỏ, trỏ tới nút cha của x
5858CTDL2 – HIENLTHHIENLTH, HCMUP
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.
5959CTDL2 – HIENLTHHIENLTH, HCMUP
• Loại bỏ dấu hiệu đen và kết thúc
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)
6060CTDL2 – HIENLTHHIENLTH, HCMUP
(theo hướng gốc của cây)
TH2: x đen kép, w và 2 con w đều đenBB
AA
CC
x
EEβα
γδ ηε
w
DDAA
CC
DD
EEβ
γδ ηε
BB
α
Đổi màu w sang đỏ
6161CTDL2 – HIENLTHHIENLTH, HCMUP
γδ ηε γδ ηεBB
AA
CC
x
EEβα
γδ ηε
w
DD AA DD
β
γδ ηε
BB
αCC EE
Đổi màu w sang đỏ
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
6262CTDL2 – HIENLTHHIENLTH, HCMUP
p
x w
w
p
x
Trở về một trong các trường hợp trên.
TH3: w đỏ
BB
DDx
DD
EEBB
Left Rotate
Đổi màu
w
6363CTDL2 – HIENLTHHIENLTH, HCMUP
AA
CC
DDx
EEβα
γδ ηε
BB
βα
AA CC
γδ
ηεĐổi màu
x w mới
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
6464CTDL2 – HIENLTHHIENLTH, HCMUP
• 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
TH4a: w đen con trái w màu đỏ
DDx AA
Quay phải tại W
Đổi màuw xw mới
Đỏ/đen
BB
CC
BBBB
6565CTDL2 – HIENLTHHIENLTH, HCMUP
AADD
CC
x
EE
EEβα
γδ ηε
βα
AA
γ
ηε
Đổi màuw x
δDDz z mới
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)
6666CTDL2 – HIENLTHHIENLTH, HCMUP
– 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
TH4b: w đen con phải w màu đỏ
DDx
BB EE
Quay trái tại cha của x
Đổi màuw
Đỏ/đen
BBDDp
6767CTDL2 – HIENLTHHIENLTH, HCMUP
AADD
EE
xBB EE
CCβα
γδ ηεβα
AA
ηεĐổi màuw
CC
γδ
z
2525 6060
5050
Cho cây đỏ đen như sau:
Bài tập áp dụng
6868CTDL2 – HIENLTHHIENLTH, HCMUP
5555 65651010 3030
Lần lượt xóa các nút sau: 55, 50.
Cây 2-3-4
+ Cây 2-3-4là câynhiều nhánh mà mỗi nodecủa nó có thể có đến bốn node con và ba mục dữ liệu.
6969CTDL2 – HIENLTHHIENLTH, HCMUP
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.
7070CTDL2 – HIENLTHHIENLTH, HCMUP
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
Các loại nút
7171CTDL2 – HIENLTHHIENLTH, HCMUP
2 – nodeMột mục dữ liệu2 node con.
3 – nodeHai mục dữ liệu3 node con.
4 – nodeBa mục dữ liệu4 node con.
Các trường hợp của cây 2-3-4
7272CTDL2 – HIENLTHHIENLTH, HCMUP
Các trường hợp của cây 2-3-4
7373CTDL2 – HIENLTHHIENLTH, HCMUP
2 - 3 - 4 tree
Các trường hợp của cây 2-3-4
7474CTDL2 – HIENLTHHIENLTH, HCMUP
Cấu trúc một nút
struct Node{
char key[3];
7575CTDL2 – HIENLTHHIENLTH, HCMUP
char key[3];int type; // 2 , 3, 4 – NodeNode* next[4];
};
Tổ chức cây 2-3-4
• Trong cây 2-3-4, các nút lá đều nằm trêncùng một mức. Các node ở mức trên thườngkhông đầy đủ, nghĩa là chúng có thể chứachỉ 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ó
7676CTDL2 – HIENLTHHIENLTH, HCMUP
• 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ácphần tử có thứ tự (tăng dần hoặc giảm dần).
Cách chèn nút
+ Bottom – up: Mở rộng cây về phía gốc,tách từ dưới lên, tràn node => tách+ Top – Down: đi từ trên xuống, gặp nútđầy thì tách,rồi tìm vị trí thíchhợp để chèn
7777CTDL2 – HIENLTHHIENLTH, HCMUP
đầy thì tách,rồi tìm vị trí thíchhợp để chèn
Ví dụ: (xem demo trên web)
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.
7878CTDL2 – HIENLTHHIENLTH, HCMUP
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
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
7979CTDL2 – HIENLTHHIENLTH, HCMUP
– 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.
Ví dụ về tách node gốc
8080CTDL2 – HIENLTHHIENLTH, HCMUP
Ví dụ Tách nút
8181CTDL2 – HIENLTHHIENLTH, HCMUP
Ví dụ Tách nút
8282CTDL2 – HIENLTHHIENLTH, HCMUP
Ví dụ về chèn nút
8383CTDL2 – HIENLTHHIENLTH, HCMUP
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 .
8484CTDL2 – HIENLTHHIENLTH, HCMUP
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.
8585CTDL2 – HIENLTHHIENLTH, HCMUP
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.
8686CTDL2 – HIENLTHHIENLTH, HCMUP
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
8787CTDL2 – HIENLTHHIENLTH, HCMUP
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.
Đánh giá
+ Cây cân bằng+ Chi phí tìm kiếm là O(log(n))
8888CTDL2 – HIENLTHHIENLTH, HCMUP
+ Chi phí tìm kiếm là O(log(n))
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.
8989CTDL2 – HIENLTHHIENLTH, HCMUP
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
9090CTDL2 – HIENLTHHIENLTH, HCMUP
Node cha: đen
Node con: đỏ
Biến đổi cây 2-3-4 sang cây đỏ đen
• Biến đổi bất kỳ 4-node sang node cha P và cả hai node con C1, C2 màu đỏ.
9191CTDL2 – HIENLTHHIENLTH, HCMUP
Node cha: đen
Node con: đỏ
Câu hỏi và thảo luận
9292CTDL2 – HIENLTHHIENLTH, HCMUP