- Sau khi đã tiến hμnh thủ tục hoá như trên, có thể viết ngay được chương trình chính trước khi thực hiện chi tiết các chương trình con.. Sơ đồ cấu trúc của chương trình gồm nhiều mức, g
Trang 11.5 Thủ tục hoá - Procedural abstraction
Các mô đun chương trình lμ các chương trình con trong một chương trình lớn hơn Thực hiện thiết kế theo mô đun cũng lμ sử dụng hμm vμ thủ tục
để xây dựng chương trình hay thủ tục hoá khi xây dựng chương trình
Phương pháp để lμm việc nμy lμ
- Xác định rõ chức năng của từng mô đun như một chương trình con,
nó sẽ lμm gì, chưa quan tâm lμm như thế nμo, không đi ngay vμo chi tiết Đây
lμ viêc phân chia biên giới giữa các chương trình con, đảm bảo tính độc lập tương đối của chúng với nhau
- Xây dựng khung lắp ghép các chương trình con thμnh chương trình chính Mỗi chương trình con lμ một mô đun riêng rẽ, giống như từng tấm bê tông để xây thμnh một toμ nhμ lắp ghép Để kiến trúc nên toμ nhμ cần bố trí các tấm bê tông đúng vị trí đã định Để xây dựng thμnh chương trình chính cần xác định đúng quan hệ của các mô đun chương trình con với nhau
- Xác định chất kết dính để liên kết các mô đun với nhau Nó giống như vôi vữa xi măng trong xây dựng nhμ cửa Cái kết dính các chương trình con với nhau lμ việc truyền tham số Đầu vμo của chương trình con nμy lμ
đầu ra của một chương trình con khác Cần hoạch định cách thức truyền dữ liệu giữa các chương trình Truyền thông qua danh sách tham số hay gián tiếp qua biến toμn cục, theo cách tham trị hay tham biến
- Sau khi đã tiến hμnh thủ tục hoá như trên, có thể viết ngay được
chương trình chính trước khi thực hiện chi tiết các chương trình con
2 Thiết kế chi tiết dần từng bước
2.1 Sơ đồ cấu trúc chương trình - structure chart
Theo phương pháp thiết kế top-down chi tiết dần từng bước ta cần lập
một sơ đồ cấu trúc của chương trình Sơ đồ cấu trúc của chương trình gồm nhiều mức, giống hình cây lật ngược mμ gốc cây lμ bμi toán ban đầu Sơ đồ cấu trúc sẽ phát triển dần xuống dưới, chia ra nhiều nhánh con, ứng với việc chi tiết dần mỗi bμi toán thμnh các bμi toán con nhỏ hơn Quá trình phân nhánh tiếp tục cho đến khi các bμi toán con đã đủ đơn giản
Trên hình vẽ, mỗi bμi toán con thực hiện một chức năng công việc xác
định, được thể hiện bằng một hình chữ nhật, có nhãn mô tả rõ chức năng lμm công việc gì Các đường nối xuống các hình chữ nhật mức dưới thể hiện quan
hệ “chứa”, nghĩa lμ bμi toán con đó, chức năng công việc đó, được phân rã thμnh các bμi toán nhỏ hơn thể hiện bởi các hình chữ nhật mức dưới Chiều ngược lại, đường nối từ hình chữ nhật ở mức dưới lên mức trên, thể hiện quan
hệ “được chứa trong” Trên các đường nối có thể có nhãn ghi rõ luồng dữ liệu trao đổi giữa hai chức năng công việc Sơ đồ cấu trúc phản ánh quan hệ giữa các bμi toán bộ phận với nhau
Trang 2Mức 0
Mức 1
Mức 2
Bμi toán ban đầu
Bμi toán 1.1
Bμi toán 2.1
Bμi toán 1.2
Mức 3
Hình 11.1: sơ đồ cấu trúc của một chương trình
Phương châm hμnh động khi thiết kế chương trình theo kiểu top-down
chi tiết dần từng bước lμ:
- Đi từ tổng thể đến bộ phận, từ khái quát đến chi tiết
- ở mỗi bước chỉ trả lời câu hỏi lμm gì, chưa vội đi vμo chi tiết lμm
như thế nμo Việc lμm như thế nμo sẽ rõ dần qua từng bước phân chia công
Đầu ra: mảng 2 chiều biểu diễn ma trận trong bộ nhớ được gán trị
2 Kiểm tra điều kiện nhân được
Đầu vμo: số hμng của A, số cột của B
Đầu ra: kết luận có thực hiện được phép nhân AB không
Trang 3Đầu ra: Hiển thị các phần tử của ma trận thμnh bảng chữ nhật, dóng thẳng hμng cột trên mμn hình
2.Kiểm tra nhân được
Hình 11.2: sơ đồ cấu trúc chương trình nhân ma trận sau khi chi tiết mức 1
Giả sử đã có 4 mô đun chương trình con thực hiện các chức năng trên,
với tên gọi tươmg ứng lμ NhapMaTran, KiemTraNhanDuoc, NhanMaTran
vμ InMaTran Chương trình chính sẽ chỉ gồm các lệnh gọi chương trình con
thực hiện tuần tự các công việc sau: nhập ma trận A; nhập ma trận B; kiểm tra điều kiện nhân được; nếu thoả mãn tính ma trận tích C = A.B vμ in ma trận C ra mμn hình
Ta có thể viết ngay phần mã lệnh của chương trình chính
Trang 4nếu đúng trả kết quả lμ True
3 Nhân hai ma trận A*B đặt vμo ma trận C
3.1 Gán số hμng của C bằng số hμng của A, số cột của C bằng số cột của B
3.2 Tính các phần tử của ma trận tích C theo công thức đã biết
- Tính các phần tử theo từng hμng, từ hμng thứ nhất cho đến hμng cuối
- In hμng tiếp theo vμ lặp lại cho đến khi hết mọi hμng
Sơ đồ cấu trúc của chương trình như sau
Đọc số hμng,
số cột
Đọc lần lượt từng hμng
Lấy số hμng , số cột
In ra lần lượt từng hμng
Tính lần lượt từng C ij
Tính số hμng, cột của
C
Chương trình nhân hai
ma trận
Nhập ma trận
Nhân hai ma trận
In ma trận
Kiểm tra nhân được
Hình 11.3: Sơ đồ cấu trúc chương trình nhân ma trận sau khi chi tiết mức 2
Chương trình chi tiết như sau
Trang 5var A,B,C: matrix;
Writeln(' Cho cac phan tu cua ma tran:');
for i:=1 to SoHang do
Trang 6Nhiều sự vật, hiện tượng có tính chất đặc biệt lμ nó đồng dạng với một
bộ phận của chính nó Một hình ảnh thường thấy lμ khi TV phát hình một phát thanh viên bên cạnh một mμn hình TV cũng đang có hình trực tiếp của chính buổi phát hình đó, ta sẽ có một chuỗi vô tận các mμn hình TV lồng nhau, chiếu cùng một khung hình
Khái niệm "cμnh cây" lμ một ví dụ khác Một cμnh con bẻ ra từ một cμnh cây cũng lμ một cμnh cây
Trong toán học có khái niệm giai thừa có thể được định nghĩa qua chính nó như sau
Những sự vật hiện tượng như trên được gọi lμ có tính đệ quy Nói một
cách khái quát tính đệ quy lμ tính chất "một bộ phận con bất kì đồng dạng với toμn thể", "có thể xây dựng nó từ một phần của chính nó"
Trang 7Đệ quy lμ một khái niệm mạnh Nó cho phép diễn đạt ngắn gọn chính xác cái vô hạn qua các "công thức" hữu hạn
3.2 Thuật giải đệ quy
3.2.1
3.2.2
Định nghĩa
Một thủ tục lμ đệ quy nếu trong thủ tục có lời gọi đến chính nó
Nếu việc giải bμi toán T thực hiện bằng việc giải bμi toán T’ có dạng hoμn toμn giống T thì đây lμ một thuật giải đệ quy
Nếu ta viết thủ tục thực hiện thuật giải nμy thì bên trong nó lại chứa chính một thủ tục tương tự, nghĩa lμ có một lời gọi đến chính nó hay một lời gọi đệ quy
Liệu một thủ tục như thế có luẩn quẩn không, có kết thúc được không? Câu trả lời lμ không, vì T’ không phải giống hệt T mμ T’ đồng dạng với T, nhưng có “quy mô” bé hơn Do đó hy vọng rằng sau khi lặp lại nhiều lần gọi
đệ quy thì "quy mô" của bμi toán cần giải sẽ giảm đến mức thủ tục có thể chấm dứt
Ta xét một ví dụ gần với thực tế đời sống hơn Đó lμ việc tìm kiếm số
điện thoại của một ngươì trong sổ điện thoại hay tra cứu giải nghĩa của một
từ trong tự điển Trình tự tiến hμnh công việc nμy thường lμ như sau
- Mở ước chừng ở giữa, chia tự điển lμm 2 phần
- Nếu từ thuộc phần đầu, lặp lại việc lμm với phần đầu
- Nếu từ thuộc phần sau, lặp lại việc lμm với phần sau
Trang 8- Lặp lại việc lμm trên cho đến khi tìm thấy từ cần tra hoặc kết luận
được lμ không có từ đó trong từ điển
Mô hình hóa thao tác tìm kiếm trên thμnh thuật giải sau
Procedure TimKiem (D: TuDien; w: MotTu);
3.3 Thiết kế giải thuật đệ quy
3.3.1 Hai đặc điểm của thuật giải đệ quy
1- Sau mỗi lần gọi đệ quy thì kích thước của bμi toán giảm đi
2- Có một trường hợp suy biến: khi bμi toán đã đủ đơn giản thì có ngay lời giải trực tiếp, không phải gọi đệ quy nữa
Dựa vμo hai đặc điểm trên, để thiết kế một thuật giải đệ quy cần phân tích bμi toán vμ thực hiện các bước sau
- Xác định rõ kích thước của bμi toán phụ thuộc vμo cái gì ?
- Phân tích đưa bμi toán về một hoặc một vμi bμi toán đồng dạng
nhưng có kích thước nhỏ hơn
- Khi nμo thì có trường hợp suy biến Lời giải trực tiếp cho trường hợp nμy
Ví dụ, nếu bμi toán xuất phát có kích thước lμ n:
- Giả sử bμi toán với kích thước nhỏ hơn hay bằng n-1 đã giải được thì lời giải bμi toán với kích thước n có tìm được hay không ?
- khi n=0 hay n=1 thì lời giải trực tiếp lμ gì ?
Trang 93.3.2
4.1.1
4.1.2
4.1.3
Khuôn mẫu viết thuật giải đệ quy
Khuôn mẫu chung của một thủ tục đệ quy lμ
If trường hợp suy biến Then cho lời giải trực tiếp
4 Một số ví dụ về thuật giải đệ quy
4.1 Bài toán tháp Hà nội
Phát biểu bμi toán
Truyền thuyết kể rằng tại một ngôi chùa ở Hμ nội có 3 cọc bằng kim cương vμ 64 chiếc đĩa bằng vμng, đường kính khác nhau, có lỗ tròn ở giữa
Đầu tiên 64 đĩa nμy xếp nằm trên một cọc, to nằm dưới, bé nằm trên Để tu tâm, rèn luyện tính nhẫn nại, hμng ngμy các nhμ sư niệm kinh Phật vμ di chuyển các đĩa từ cọc nμy sang cọc khác Quy tắc di chuyển lμ mỗi lần chỉ chuyển được một đĩa ở trên cùng vμ không được đặt đĩa to hơn lên trên đĩa bé hơn
Bμi toán: chuyển toμn bộ 64 đĩa từ cọc x (= xuất phát) ban đầu sang một cọc mới lμ d (=đích) Trong quá trình di chuyển có thể xếp tạm lên một cọc còn lại tg lμm trung gian
Phân tích
Kích thước của bμi toán lμ số đĩa n = 64
Giả sử đã biết cách giải bμi toán với n nhỏ hơn: chuyển n-1 đĩa theo
đúng các quy tắc nêu trên, từ một cọc ban đầu sang một cọc khác, dùng cọc
còn lại lμm trung gian Thế thì có thể giải bμi toán với n đĩa như sau:
- Chuyển n-1 đĩa từ x sang tg lấy d lμm trung gian
- Chuyển nốt 1 đĩa từ x sang d
- Chuyển n-1 đĩa từ tg sang d lấy x lμm trung gian
- Trường hợp suy biến: n = 1 Lúc nμy có ngay lời giải trực tiếp
Chuyển một đĩa từ x sang d
Viết thủ tục đệ quy
Tham số đầu vμo:
Trang 10- Tham số 1: số đĩa
- Tham số 2: cọc đĩa xuất phát
- Tham số 3: cọc đích
- Tham số 4: cọc lμm trung gian
Tham số đầu ra: không có
Theo đúng khuôn mẫu viết thủ tục đệ quy, thủ tục Hanoi bắt đầu với
trường hợp suy biến, khi chỉ có 1 đĩa Trường hợp số đĩa nhiều hơn 1, bμi toán được phân rã ra như đã trình bμy ở trên Hai lời gọi đệ quy được thực
hiện để giải 2 bμi toán nhỏ hơn với n-1 đĩa Lưu ý thứ tự của các tham số đầu vμo thứ 2, thứ 3, thứ 4 lμ rất quan trọng vì nó tương ứng với vai trò lμ cọc đĩa
xuất phát, cọc đích, cọc trung gian trong thao tác chuyển đĩa
procedure hanoi(n: integer ; x,d,tg: char);
Phát biểu bμi toán
Có một tờ giấy kẻ ô lưới vuông Một số vết mực loang trên tờ giấy Cần tính diện tích của từng vết loang Coi diện tích lμ số ô dính mực Nếu gọi những ô dính mực gọi lμ ô đen, những ô không dính mực lμ ô trắng thì bμi toán trở thμnh đếm cụm số ô đen liên thông chứa một ô đã chọn
Bμi toán nμy có nhiều ứng dụng trong xử lí ảnh
Phân tích
Có thể đề xuất một thuật giải đệ quy như sau Diện tích của vết mực
giả sử lμ n ô Nếu ta đã biết cách đếm số ô đen của mọi vết có diện tích nhỏ hơn hay bằng n -1 thì hoμn toμn giải quyết được bμi toán bằng cách: xuất
phát từ một ô đen trong vùng; đếm 1; đánh dấu ô đã chọn thμnh ô trắng; chọn một ô kề nó; đếm cụm ô đen liên thông với ô nμy Việc nμy lμm được
theo giả thiết vì vết đen nμy có diện tích bằng n-1
Lưu ý rằng một ô bất kì có 8 ô kề nó nên trong hμm Dem_O_Den
phải có 8 lời gọi đệ quy Không có ô đen nμo bị đếm quá một lần, vì sau khi
đếm thì ta đánh dấu nó thμnh ô trắng
Trang 11Trường hợp suy biến: không còn ô kề nμo lμ ô đen nữa Ô đang xét lμ
Tham số đầu vμo:
- Tham số 1: Luoi lμ một mảng hai chiều mμ mỗi phần tử của nó chỉ nhận hai giá trị Den hoặc Trang
- Tham số 2: x toạ độ x của ô xuất phát
- Tham số 3: y toạ độ y của ô xuất phát
Tham số đầu ra: tên hμm chứa kết quả đếm
const MaxX = 10; MaxY = 10;
type MangBit = array[1 MaxX,1 MaxY] of (Den,Trang);
Trang 12end;
end;
BEGIN
Writeln(' Cho mang 10 x 10 so 0/1 theo tung hang ');
for i:=1 to MaxX do
Để kiểm tra hoạt động của hμm vừa xây dựng ta dùng mảng 10 x 10 số
0/1 nhập từ bμn phím theo từng hμng, mỗi lần một hμng 10 số 0 hoặc 1 Số 0 ứng với ô trắng, số 1 ứng với ô đen
Có thể chọn ô xuất phát lμ bất cứ ô nμo, miễn lμ thuộc vết mực cần tính diện tích
Nếu nhập đúng dữ liệu vμo như hình vẽ trên thì chương trình phải cho
két quả tính đúng diện tích lμ 16 của vết mực chứa ô (1,2)
một trong hai dãy con có chứa khoá x Trường hợp suy biến lμ dãy chỉ còn
một phần tử, có ngay kết quả trực tiếp
Viết hμm đệ quy
Tham số đầu vμo:
- Tham số 1: chỉ số đầu mút trái của dãy con đang xét l
- Tham số 2: chỉ số đầu mút phải r của dãy con đang xét
Trang 13- Tham số 3: giá trị khoá x cần tìm
- Tham số 4: mảng a chứa các khoá
Tham số đầu ra: tên hμm, chứa kết quả tìm thấy hay không
Theo đúng khuôn mẫu chung của một tủ tục đệ quy, hμm
TimKiemNhiPhan bắt đầu bằng trường hợp suy biến, khi dãy khoá chỉ gồm
Nội dung cụ thể của thuật toán có thể mô tả như sau:
- Chọn một phần tử x nμo đó trong dãy lμm phần tử chốt
- Tiến dần từ trái sang phải cho đến khi gặp a[i] > x;
- Tiến dần từ phải sang trái cho đến khi gặp a[j] < x;
- Đổi chỗ a[i] cho a[j]
- Đi tiếp từ cả hai phía cho đến khi gặp nhau thì kết thúc một bước Một bước tiến hμnh như trên gọi lμ một lần phân đoạn Sau một bước -
một lần phân đoạn - thì phần tử chốt x sẽ ở đúng vị trí của nó Mảng được
Trang 14chia lμm hai phần, nửa trái gồm toμn các phần tử < x, nửa phải gồm toμn các phần tử > x Điều nμy giải thích tại sao lại gọi phần tử x lμ chốt
Như vậy dãy ban đầu đã được phân rã thμnh hai dãy con, bμi toán ban
đầu được phan rã thμnh hai bμi toán con đồng dạng Sử dụng thủ tục đệ quy ở
đây lμ một điều tự nhiên Trường hợp suy biến lμ dãy con chỉ còn một phần
tử
4.4.2 Viết thủ tục đệ quy
Tham số đầu vμo
- Tham số 1: chỉ số đầu mút trái của dãy con đang xét l
- Tham số 2: chỉ số đầu mút phải r của dãy con đang xét
Tham số đầu ra: không có Kết quả thủ tục phân đoạn lμm thay đổi vị trí của các phần tử của một mảng lμ biến toμn cục nên không cần đưa vμo danh sách tham số
procedure PhanDoan (l,r: integer);
var x,w: ;
begin
i:=l; j:=r; { l=left; r=right }
“chon mot phan tu x lam chot”
Lưu ý rằng trong thủ tục trên, điều kiện "cho đến khi gặp nhau" để kết
thúc một bước phân đoạn được thể hiện bằng câu lệnh until i>j chứ không phải until i=j Lí do lμ vì điều kiện i>j luôn sẽ xảy ra, còn điều kiện i=j
có thể không xảy ra trong quá trình trên
Thủ tục sắp xếp nhanh chỉ bao gồm duy nhất một lời gọi đến thủ tục phân đoạn áp dụng cho dãy xuất phát ban đầu
procedure Quicksort;
begin
PhanDoan(1,n);
end;
Trang 155 Tự xây dựng thư viện chương trình con - Units
5.1 Sử dụng lại các chương trình con
Các chương trình con thường dùng, cần lμm sẵn để sử dụng lại nhiều lần trong chương trình chính cũng như trong tương lai về sau nμy Có hai cách để sử dụng lại các chương trình con:
1- Chỉ thị cho trình biên dịch chèn trực tiếp tệp mã nguồn của chương trình con vμo chỗ cần thiết khi tiến hμnh biên dịch chương trình Theo cách
nμy ta thêm chỉ thị biên dịch (compiler directive) sau đây vμo vị trí muốn
chèn thêm tệp mã nguồn của chương trình con
{$I tên tệp mã nguồn }
Công dụng của chỉ thị trên hoμn toμn giống như ta sao lại vμ chèn thêm một cách thủ công đoạn mã nguồn của chương trình con vμo vị trí đó
2- Tổ chức thμnh các thư viện chương trình con - các Unit
Các hμm, thủ tục mẫu hay dùng trong chương trình có thể tổ chức riêng thμnh một thư viện chương trình con Nếu có nhiều chương trình con thì người ta chia lμm nhiều thư viện, nhóm theo chức năng, mỗi phần lμ một Unit Khi xây dựng một chương trình rất lớn, có thể cần đến nhiều Unit
5.2 Cấu trúc của một unit
Để xây dựng một Unit vμ sử dụng nó trong chương trình ta phải theo những quy định chính xác trong từng công đoạn Dưới đây sẽ trình bμy lần lượt từng bước
5.2.1 Khung cấu trúc
Khung cấu trúc để viết một Unit như sau:
Unit tên Unit ;