Ch−ơng 4 B-cõy
B. Phần thực hành
Ghi chỳ. Để trỏnh sự nhầm lẫn mà khụng phải giải thớch quỏ dài, chỳng tôi quy −ớc cách viết nh−
sau:
- Tờn tệp dữ liệu sẽ đ−ỵc viết bằng 2 cỏch: cỏch thứ nhất là đợc đúng trong nháy kép, ví dơ "ZZ.DAT", "VUTB.DAT",... khi đú ta hiểu đõy là cỏc tờn tệp mà khi dựng cỏc cụng cụ thao tác tƯp nh− My Computer hay NC ta sẽ nhỡn thấy trờn đĩa cứng. Cỏch thứ 2 là khụng đúng trong nháy kép, ví dơ tƯp tepẠ Lỳc này ta hiểu là tờn tệp chớnh là giỏ trị của biến chuỗ Vớ dụ nếu biến chuỗi tepA cú giỏ trị là "THTXT" chẳng hạn thỡ khi viết tƯp tepA ta sẽ hiĨu là tệp "THTXT". Tuy nhiờn đối với tệp ch−ơng trỡnh vớ dụ 11SXF.CPP chỳng tụi không dùng quy ớc này vỡ khụng cú sự nhập nhằng.
- Vỡ hàm th−ờng có nhiều tham số, nếu viết đầy đủ sẽ quỏ dài, nếu chỉ viết hai dấu () sau tờn hàm thỡ cú thể hiểu nhầm là hàm khụng cú tham số. Do đú chỳng tụi quy −ớc khi viết
tờn hàm mà khụng cú gỡ phớa sau, vớ dụ SplitFile thỡ cú nghĩa ta chỉ núi đến tờn hàm, cũn phần tham số thỡ phải tham khảo chơng trỡnh mới biết đ−ỵc.
- Nếu bạn đợc yờu cầu viết lại một đoạn chơng trỡnh nào đú thỡ bạn phải hiểu rõ ch−ơng trỡnh mỡnh viết. Nếu chỉ viết mà khụng hiểu gỡ thỡ coi nh− khụng đợc tớnh điểm.
- Nếu viƯc viết lại ch−ơng trỡnh là quỏ khú đối với bạn thỡ bạn cần phải hiểu đợc những phần ch−ơng trỡnh mà bài ra yờu cầ Nếu hiểu đ−ợc thỡ bạn cú thể đạt điểm trung bỡnh.
Ch−ơng 1. Sắp xếp ngoại
1.1. Ch−ơng trỡnh 11SXF.CPP cài đặt thuật toỏn trộn trực tiếp để sắp xếp tệp nhị phõn chứa cỏc số thực. Ch−ơng trỡnh này cú một số hàm, trong đú 3 hàm quan trọng nhất là SplitFile, MergeFile và SortFilẹ Trong hàm main có thể thấy là tệp cần đợc sắp xếp cú tờn là "ZZ.DAT". Tệp này đ−ỵc tạo ra khi gọi hàm CreateFil Cú thể dựng hàm ViewFile để liệt kờ cỏc số thực đỵc l−u trữ trong tƯp bất kỳ. Khi chạy hàm CreateFile ta cú 2 khả năng lựa chọn: hc nhập trực tiếp trờn bàn phớm hoặc chỉ cần nhập số phần tử rồi mỏy sẽ dựng hàm tạo số ngẫu nhiờn cú sẵn trong C để tạo ra cỏc số thực và đ−a vào tƯp. Hàm SortFile sẽ lấy đầu vào là tệp "ZZ.DAT", sau đú tạo ra 2 tệp trung gian là "VUTB.DAT" và "VUTC.DAT" để chứa cỏc run đợc phõn bổ từ "ZZ.DAT". Tại b−ớc khởi đầu p đ−ợc gỏn giỏ trị 1, sau đú vũng lặp sau đ−ỵc thực hiƯn chừng nào p cũn nhỏ hơn n:
B1. Hàm SplitFile đ−ỵc gọi để phõn bổ cỏc run độ dài p từ "ZZ.DAT" sang "VUTB.DAT" và "VUTC.DAT", phơng phỏp trộn trực tiếp coi tệp ban đầu cú n phần tử gồm n run độ dài 1. Điều này luụn luụn đỳng.
B2. Hàm MergeFile đ−ỵc gọi để trộn cỏc run độ dài p từ "VUTB.DAT" và "VUTC.DAT" thành cỏc run độ dài 2p trong "ZZ.DAT". Mỗi lần trộn ta thấy độ dài run tăng gấp đụi (trừ run cuối cùng), do đó ta đỈt p = 2*p. Nếu p ≥ n thì kết thỳc, nếu khụng thỡ quay lại B1. Bạn hÃy thực hiện cỏc cụng việc sau (ở nhà và ở giờ thực hành):
Đọc toàn bộ chơng trỡnh để hiĨu đ−ợc chức năng, input và output của cỏc hàm, ý nghĩa cỏc lệnh. Bạn hÃy dựng chức năng "Save as..." để l−u tƯp 11SXF.CPP thành tƯp BAI11.CPP và thử sửa đổi chơng trỡnh này theo gỵi ý sau:
b. Hàm
void SplitFile(char *tepA,char *tepB, char *tepC, int p)
cú đầu vào (input) là tệp tepA chứa cỏc run độ dài p (trừ run cuối cùng có thể có ít hơn). Hàm này sẽ tạo ra cỏc tệp nhị phõn cú tờn là tepB và tepC, sau đú lần lợt phõn bổ cỏc run độ dài p trờn tepA sang cỏc tệp tepB và tepC cho đến khi hết run trờn
Bạn hÃy xúa hàm SplitFile rồi viết lại mà khụng sử dụng tài liệu hc ch−ơng trỡnh mẫu, sao cho ch−ơng trỡnh này chạy đợc và cho kết quả đúng.
c. Hàm
void MergeFile(char *tepB,char *tepC, char *tepA, int p)
cú đầu vào là cỏc tệp tepB và tepC chứa cỏc run độ dài p (trừ run cuối ). Hàm này sẽ tạo mới tệp nhị phõn tepA, sau đú lần lợt trộn từng cặp run độ dài p trờn tepB và tepC thành cỏc run cú độ dài 2p và đa sang tƯp tepA cho đến khi hết run trờn tepB và tepC.
Bạn hÃy xúa hàm MergeFile rồi viết lại mà khụng sử dụng tài liệu hoặc ch−ơng trình mẫu, sao cho ch−ơng trỡnh này chạy đợc và cho kết quả đỳng.
d. Hàm
http://www.ebook.edụvn
Cấu trỳc dữ liệu 2 - Cõu hỏi lý thuyết và cỏc bài thực hành chuẩn bị cho thi hết mụn
97 cú đầu vào là tệp TenTep th−ờng ch−a đ−ợc sắp xếp. Trong thõn hàm hai tệp trung gian là "VUTB.DAT" và "VUTC.DAT" đ−ợc tạo ra và sử dụng nh− các tƯp trung gian. Tht toỏn trộn run trực tiếp đợc ỏp dụng và cho kết quả là tệp TenTep đợc sắp xếp.
Bạn hÃy xúa hàm SortFile rồi viết lại mà khụng sử dụng tài liƯu hc ch−ơng trỡnh mẫu, sao cho ch−ơng trỡnh này chạy đợc và cho kết quả đỳng.
1.2. Chơng trỡnh 12SXF.CPP cài đặt thuật toỏn trộn run tự nhiờn để sắp xếp tệp nhị phõn chứa các số thực. Ch−ơng trỡnh này cú một số hàm, trong đú 3 hàm quan trọng nhất là SplitFile, MergeFile và SortFilẹ Ngoài ra hàm EoR cũng đợc khai bỏ Hàm này cho kết quả true nếu con trỏ tệp đang khảo sỏt đà ở cuối tệp hoặc ở sau phần tử cuối cựng của run. Nếu con trỏ tệp ở vị trớ đầu tệp hoặc ch−a ở phía sau phần tử cuối của run thỡ hàm này nhận giỏ trị fals Trong hàm main cú thể thấy là tệp cần đợc sắp xếp cú tờn là "ZZ.DAT". Hàm SortFile sẽ lấy đầu vào là tệp "ZZ.DAT", sau đú tạo ra 2 tệp trung gian là "VUTB.DAT" và "VUTC.DAT" để chứa cỏc run đ−ợc phõn bổ từ "ZZ.DAT". Cỏc b−ớc lỈp sau đ−ợc thực hiện để trộn tệp "ZZ.DAT".
B1. Hàm SplitFile đợc gọi để phõn bổ cỏc run tự hiờn từ "ZZ.DAT" sang "VUTB.DAT" và "VUTC.DAT".
B2. Hàm MergeFile đợc gọi để trộn cỏc run tự nhiờn từ "VUTB.DAT" và "VUTC.DAT" thành cỏc run độ dài lớn hơn trong "ZZ.DAT". Mỗi lần trộn ta thấy số cỏc run giảm đi khoảng một nưạ Nếu sau khi trộn tepA chỉ chứa một run (có nghĩa là tệp đà đợc sắp xếp), thỡ ta kết thỳc thuật toỏn, nếu khụng thỡ quay lại B1.
Bạn hãy thực hiện cỏc cụng việc sau (ở nhà và ở giờ thực hành):
Đọc toàn bộ ch−ơng trỡnh để hiểu đợc chức năng, input và output của cỏc hàm, ý nghĩa cỏc lệnh. Bạn hÃy dựng chức năng "Save as..." đĨ l−u tƯp 12SXF.CPP thành tƯp BAI12.CPP và thử sửa đổi ch−ơng trỡnh này theo gợi ý sau:
b. Hàm
void SplitFile(char *tepA,char *tepB, char *tepC)
có đầu vào (input) là tệp tepA chứa cỏc run tự nhiờn. Hàm này sẽ tạo ra cỏc tệp nhị phõn cú tờn là tepB và tepC, sau đú lần lợt phõn bổ cỏc run trờn tepA sang cỏc tệp tepB và tepC cho đến khi hết run trờn
Bạn hÃy xúa hàm SplitFile rồi viết lại mà khụng sử dụng tài liệu hoặc ch−ơng trình mẫu, sao cho ch−ơng trỡnh này chạy đợc và cho kết quả đỳng.
c. Hàm
void MergeFile(char *tepB,char *tepC, char *tepA)
cú đầu vào là cỏc tệp tepB và tepC chứa cỏc run tự nhiờn. Hàm này sẽ tạo mới tệp nhị phõn tepA, sau đú lần lợt trộn từng cặp run trờn tepB và tepC thành cỏc run dài hơn và đ−a sang tệp tepA cho đến khi hết run trờn tepB và tepC.
Bạn hãy xóa hàm MergeFile rồi viết lại mà khụng sử dụng tài liệu hoặc chơng trỡnh mẫu, sao cho ch−ơng trỡnh này chạy đợc và cho kết quả đỳng.
d. Hàm
void SortFile(char *TenTep)
cú đầu vào là tệp TenTep th−ờng ch−a đ−ợc sắp xếp. Trong thõn hàm hai tệp trung gian là "VUTB.DAT" và "VUTC.DAT" đợc tạo ra và sử dụng nh− các tƯp trung gian. Tht toỏn trộn run tự nhiờn đợc ỏp dụng và cho kết quả là tệp TenTep đợc sắp xếp.
Bạn hãy xóa hàm SortFile rồi viết lại mà khụng sử dụng tài liệu hoặc chơng trỡnh mẫu, sao cho ch−ơng trỡnh này chạy đợc và cho kết quả đỳng.
1.3. Ch−ơng trình 13SXF.CPP cài đặt thuật toỏn trộn đa lối cõn bằng để sắp xếp tệp nhị phõn chứa các số thực. Chơng trỡnh này cú một số hàm, trong đú 3 hàm quan trọng nhất là SplitFile, MergeFile và SortFilẹ Trong hàm main có thĨ thấy là tệp cần đợc sắp xếp cú tờn là "ZZ.DAT". Hàm SortFile sẽ lấy đầu vào là tệp "ZZ.DAT", sau đú yờu cầu ng−ời sư dơng nhập vào số đ−ờng trộn. Nếu số đ−ờng trộn là n thỡ n tệp nguồn và n tệp đớch đ−ỵc tạo rạ Ví dơ nếu n = 4 thỡ cỏc tệp nguồn cú tờn là: ZZN0.DAT, ZZN1.DAT, ZZN2.DAT, ZZN3.DAT và cỏc tệp đớch cú tờn là ZZD0.DAT, ZZD1.DAT, ZZD2.DAT, ZZD3.DAT. (Chỳng tụi đặt tờn tệp bắt đầu bằng ZZ để cỏc tệp này khi hiển thị sẽ nằm ở cuối th− mơc; N là ngn, cũn D cú nghĩa là đớch). Cỏc b−ớc lỈp sau đ−ợc thực hiện để trộn tệp "ZZ.DAT".
B1. Hàm SplitFile đợc gọi để phõn bổ cỏc run tự hiờn từ "ZZ.DAT" sang n tệp nguồn.
B2. Hàm MergeFile đợc gọi để trộn từng bộ n run từ cỏc tệp nguồn thành từng run độ dài lớn hơn (bằng tổng độ dài của n run từ cỏc tệp nguồn thành phần), sau đú lần lợt phõn bổ cho cỏc tệp đớch. Run trộn đ−ỵc đầu tiờn sẽ đợc ghi vào tệp đớch TepDich[0], run thứ hai trộn đ−ỵc sẽ đ−ợc ghi vào TepDich[2],... cỳ nh− vậy cho đến khi hết cỏc run trờn tệp nguồn. Mỗi lần trộn ta thấy số cỏc run giảm đi khoảng n lần.
B3. Nếu sau khi trộn chỉ cú một tệp đớch (cú nghĩa là tệp TepDich[0] chỉ chứa một run), thì
ta kết thỳc thuật toỏn, nếu khụng thỡ quay lại B2.
Bạn hãy thực hiƯn cỏc cụng việc sau (ở nhà và ở giờ thực hành):
Đọc toàn bộ ch−ơng trỡnh để hiểu đợc chức năng, input và output của cỏc hàm, ý nghĩa cỏc lệnh. Bạn hÃy dựng chức năng "Save as..." đĨ l−u tƯp 13SXF.CPP thành tƯp BAI13.CPP và thử sửa đổi ch−ơng trỡnh này theo gợi ý sau:
b. Hàm
void SplitFile(char *tepA,char *TepNguon[], int &nWay)
cú đầu vào (input) là tệp tepA chứa cỏc run tự nhiờn. Hàm này sẽ tạo ra cỏc tệp nhị phõn cú tờn là TepNguon[0], TepNguon[1], ... ,TepNguon[nWay-1], sau đú lần lợt phõn bổ cỏc run trên tepA sang cỏc tệp nguồn cho đến khi hết run trờn Sau khi phõn bổ run thỡ rất có thĨ một số tƯp ngn cịn trống do số run ớt hơn số đ−ờng trộn. Ch−ơng trỡnh sẽ tớnh toỏn lại số đ−ờng trộn nWay dựa trên số tƯp nguồn thực tế.
Bạn hãy xúa hàm SplitFile rồi viết lại mà khụng sử dụng tài liệu hoặc chơng trỡnh mẫu, sao cho ch−ơng trỡnh này chạy đợc và cho kết quả đỳng.
c. Hàm
void MergeFile(char *TepNguon[],char *TepDich[], int &nWay)
cú đầu vào là các tƯp TepNguon[i], i = 0, 1, ..., nWay-1 chứa cỏc run tự nhiờn. Hàm này sẽ tạo cỏc tệp đớch TepDich[i], i = 0, 1, ..., nWay-1, sau đú lần l−ỵt trộn từng bộ n run trên cỏc tệp đớch (lần trộn cuối cựng cú thể khụng đủ n run) thành cỏc run dài hơn và đa sang các tệp đớch cho đến khi hết run trờn cỏc tƯp ngn.
Bạn hãy xúa hàm MergeFile rồi viết lại mà khụng sử dụng tài liệu hoặc chơng trỡnh mẫu, sao cho ch−ơng trỡnh này chạy đợc và cho kết quả đỳng.
d. Hàm
void SortFile(char *TenTep)
cú đầu vào là tệp TenTep th−ờng ch−a đ−ợc sắp xếp. Trong thõn hàm, ch−ơng trỡnh yờu cầu ng−ời sư dơng nhập số đ−ờng trộn, sau đú tạo ra cỏc tệp nguồn và cỏc tệp đớch nh− đã núi ở trờn. Tiếp theo cỏc run tự nhiờn trong tệp TenTep đợc phõn bổ cho các tƯp ngn. Tht toỏn trộn đa lối cõn bằng đợc ỏp dụng bằng cỏch sau mỗi lần trộn lại hoỏn đổi vai
http://www.ebook.edụvn
Cấu trúc dữ liƯu 2 - Cõu hỏi lý thuyết và cỏc bài thực hành chuẩn bị cho thi hết mụn
99 trũ của cỏc tệp nguồn và cỏc tệp đớch cho đến khi chỉ cũn một tệp đớch duy nhất thỡ kết thúc. ở b−ớc ci cùng tƯp đích TepDich[0] chứa một run duy nhất gồm tất cả cỏc phần tử trong tệp ban đầ Chơng trỡnh copy dữ liệu đà sắp xếp vào tệp TenTep, xúa cỏc tệp trung gian và kết thúc.
Bạn hÃy xúa hàm SortFile rồi viết lại mà khụng sử dụng tài liệu hoặc ch−ơng trình mẫu, sao cho ch−ơng trỡnh này chạy đợc và cho kết quả đỳng.
Ch−ơng 2. Bảng băm
2.1. Ch−ơng trỡnh 21HASHLK.CPP cài đặt bảng băm dựng danh sỏch liờn kết ngoài bằng ngụn ngữ lập trỡnh C++. Với mục đớch cài đặt bảng băm để cú thể dựng cho nhiỊu mơc đích, chúng tụi cài đặt bảng băm nh− một lớp (class) trong đú thành phần chớnh của lớp là một mảng động H mà mỗi phần tử của mảng H là một danh sỏch liờn kết. Bản thõn danh sỏch liờn kết lại là một kiểu lớp cú tờn là List đ−ợc khai bỏo trong tệp LIST_H.CPP. Thành phần chớnh của danh sỏch là một mảng động mà cỏc phần tử là cỏc số nguyờn. Để cú thể hiĨu đ−ỵc ch−ơng trỡnh 21HASHLK.CPP, bạn cần tỡm hiểu tệp LIST_H.CPP mà cỏc chức năng của nú cú thể hiểu đợc khi đọc ch−ơng trỡnh. Sau khi hiểu tệp này, bạn chạy thử chơng trỡnh DS-LK.CPP. Ch−ơng trỡnh này chốn (include) tệp LIST_H.CPP vào, sau đú chạy cỏc chức năng nh− nhập dữ liệu vào danh sỏch, tỡm kiếm trờn danh sách...
2.2. Ch−ơng trỡnh 21HASHLK.CPP cài đặt bảng băm với một số chức năng (theo ngụn ngữ C++ thỡ đú là các ph−ơng thức), trong đú quan trọng nhất là cỏc chức năng insert, search và travers Bạn hÃy tỡm hiểu chơng trỡnh, sau đú dựng chức năng "Save as..." để l−u tệp này thành tƯp BAI21.CPP, rồi thử sửa đổi tệp này theo cỏch sau:
ạ Hàm
void HashTab::insert(int x)
thực hiƯn viƯc chèn một khóa x vào bảng băm
Bạn hÃy xúa phần thõn hàm và viết lại sao cho ch−ơng trỡnh vẫn chạy đỳng. b. Hàm
int HashTab::search(int x)
thực hiƯn viƯc tìm khóa x trờn bảng băm. Nếu tỡm thấy thỡ trả về giỏ trị true, đồng thời đặt con trỏ pcurent trỏ vào địa chỉ nỳt tỡm thấ Nếu khụng tỡm thấy thỡ trả về giỏ trị fals Bạn hÃy xúa phần thõn hàm và viết lại sao cho ch−ơng trỡnh vẫn chạy đỳng.
c. Hàm
void HashTab::traverse()
thực hiện việc liệt kờ tất cả cỏc khúa trong bảng băm
Bạn hÃy xúa phần thõn hàm và viết lại sao cho ch−ơng trỡnh vẫn chạy đỳng.
2.3. Ch−ơng trình 23HASHTR.CPP cài đặt bảng băm với một số chức năng (theo ngụn ngữ C++ thỡ đú là cỏc ph−ơng thức), trong đú quan trọng nhất là cỏc chức năng insert, search và travers Bạn hãy tìm hiĨu ch−ơng trỡnh, sau đú dựng chức năng "Save as..." đĨ l−u tệp này thành tệp BAI23.CPP, rồi thử sửa đổi tệp này theo cỏch sau:
ạ Hàm
void HashTab::insert(int x)
thực hiƯn viƯc chèn một khóa x vào bảng băm
Bạn hÃy xúa phần thõn hàm và viết lại sao cho chơng trỡnh vẫn chạy đỳng. b. Hàm
int HashTab::search(int x)
thực hiƯn viƯc tìm khóa x trờn bảng băm. Nếu tỡm thấy thỡ trả về giỏ trị true, đồng thời đặt con trỏ pcurent trỏ vào địa chỉ nỳt tỡm thấ Nếu khụng tỡm thấy thỡ trả về giỏ trị fals Bạn hÃy xúa phần thõn hàm và viết lại sao cho ch−ơng trỡnh vẫn chạy đỳng.
c. Hàm
void HashTab::traverse()
thực hiện việc liệt kờ tất cả cỏc khúa trong bảng băm
Bạn hÃy xúa phần thõn hàm và viết lại sao cho ch−ơng trỡnh vẫn chạy đỳng.
Ch−ơng 3. Cõy đỏ đen
Ch−ơng trỡnh 31CAYAVL.CPP cài đặt cõy nhị phõn tỡm kiếm cõn bằng chiều ca Ch−ơng trỡnh này rất khú, nờn chỳng tụi chỉ yờu cầu bạn đọc và hiểu cỏc chức năng của chơng trỡnh. Tuy nhiờn để sự tỡm hiểu hiệu quả hơn bạn có thể l−u thành một tệp khỏc rồi thử viết lại từng đoạn nhỏ.
Ch−ơng 4. B - cõy
Ch−ơng trỡnh 41BTRECPP cài đặt B - câỵ Ch−ơng trỡnh này rất khú, nờn chỳng tụi chỉ yờu cầu bạn đọc và hiểu cỏc chức năng của chơng trỡnh. Tuy nhiờn để sự tỡm hiểu hiệu quả hơn bạn có thể l−u thành một tệp khỏc rồi thử viết lại từng đoạn nhỏ.