Giáo trình Cấu trúc dữ liệu và giải thuật - Học viện Công nghệ Bưu chính viễn thông

HC VIN CÔNG NGHỆ BƢU CHÍNH VIỄN THÔNG  
CU TRÚC DLIU VÀ GII THUT  
(Dùng cho sinh viên hệ đào tạo đại hc txa)  
Lƣu hành nội bộ  
HÀ NI - 2007  
LI NÓI ĐẦU  
Cu trúc dliu và gii thut là mt trong nhng môn học cơ bản ca sinh viên ngành Công  
nghthông tin. Các cu trúc dliu và các gii thuật đƣợc xem nhƣ là 2 yếu tquan trng nht  
trong lập trình, đúng nhƣ câu nói nổi tiếng của Niklaus Wirth: Chƣơng trình = Cấu trúc dliu +  
Gii thut (Programs = Data Structures + Algorithms). Nm vng các cu trúc dliu và các gii  
thuật là cơ sở để sinh viên tiếp cn vi vic thiết kế và xây dng phn mềm cũng nhƣ sử dng các  
công clp trình hiện đại.  
Cu trúc dliu có thể đƣợc xem nhƣ là 1 phƣơng pháp lƣu trữ dliu trong máy tính  
nhm sdng mt cách có hiu qucác dliệu này. Và để sdng các dliu mt cách hiu quả  
thì cn phi có các thut toán áp dng trên các dliệu đó. Do vậy, cu trúc dliu và gii thut là  
2 yếu tkhông thtách ri và có nhng liên quan cht chvi nhau. Vic la chn mt cu trúc  
dliu có thsẽ ảnh hƣởng ln ti vic la chn áp dng gii thut nào.  
Tài liệu “Cấu trúc dliu và gii thuật” bao gồm 7 chƣơng, trình bày về các cu trúc dliu  
và các gii thuật cơ bản nht trong tin hc.  
Chƣơng 1 trình bày về phân tích và thiết kế thuật toán. Đầu tiên là cách phân tích 1 vấn đề,  
tthc tin cho tới chƣơng trình, cách thiết kế mt gii pháp cho vấn đề theo cách gii quyết bng  
máy tính. Tiếp theo, các phƣơng pháp phân tích, đánh giá độ phc tp và thi gian thc hin gii  
thuật cũng đƣợc xem xét trong chƣơng. Chƣơng 2 trình bày về đệ qui, mt khái nim rất cơ bản  
trong toán hc và khoa hc máy tính. Vic sdụng đệ qui có thxây dựng đƣợc những chƣơng  
trình gii quyết đƣợc các vấn đề rt phc tp chbng mt sít câu lệnh, đặc bit là các vấn đề  
mang bn chất đệ qui.  
Chƣơng 3, 4, 5, 6 trình bày về các cu trúc dliệu đƣợc sdng rt thông dụng nhƣ mảng  
và danh sách liên kết, ngăn xếp và hàng đợi, cây, đồ thị. Đó là các cấu trúc dliệu cũng rất gn  
gũi với các cu trúc trong thc tiễn. Chƣơng 7 trình bày về các thut toán sp xếp và tìm kiếm.  
Các thut toán này cùng vi các kthuật đƣợc sdụng trong đó đƣợc coi là các kthuật cơ sở  
cho lp trình máy tính. Các thuật toán đƣợc xem xét bao gm các lp thuật toán đơn giản và cả  
các thuật toán cài đặt phc tạp nhƣng có thời gian thc hin tối ƣu.  
Cui mi phần đều có các câu hi và bài tập để sinh viên ôn luyn và tkim tra kiến thc  
ca mình. Cui tài liu có các phlục hƣớng dn trli câu hi, mã ngun tham kho và tài liu  
tham kho.  
Vnguyên tc, các cu trúc dliu và các gii thut có thể đƣợc biu diễn và cài đặt bng  
bt cngôn nglp trình hiện đại nào. Tuy nhiên, để có đƣợc các phân tích sâu sắc hơn và có kết  
quthc tế hơn, tác giả đã sử dng ngôn nglập trình C để minh hocho các cu trúc dliu và  
thut toán. Do vy, ngoài các kiến thức cơ bản vtin học, ngƣời đọc cn có kiến thc vngôn ngữ  
lp trình C.  
Cui cùng, mặc dù đã hết sc cgắng nhƣng chắc chn không tránh khi các thiếu sót. Tác  
girt mong nhận đƣợc sgóp ý ca bạn đọc và đồng nghiệp để tài liệu đƣợc hoàn thiện hơn.  
Hà Ni, tháng 10/2007  
CHƢƠNG 1  
PHÂN TÍCH VÀ THIT KGII THUT  
Chƣơng 1 trình bày các khái nim vgii thuật và phƣơng pháp tinh chỉnh từng bƣớc  
chƣơng trình đƣợc thhin qua ngôn ngdiễn đạt gii thuật. Chƣơng này cũng nêu phƣơng pháp  
phân tích và đánh giá một thut toán, các khái niệm liên quan đến vic tính toán thi gian thc  
hiện chƣơng trình.  
Trong mi phần đều có các minh hocth. Phần đầu đƣa ra ví dụ vbài toán nút giao  
thông và phƣơng pháp giải quyết bài toán tphân tích vấn đề cho đến thiết kế gii thut, tinh  
chnh từng bƣớc cho ti mc cthể hơn. Phần 2 đƣa ra một ví dvphân tích và tính toán thi  
gian thc hin gii thut sp xếp ni bt.  
Để hc tốt chƣơng này, sinh viên cần nm vng phn lý thuyết và tìm các ví dụ tƣơng tự để  
thc hành phân tích, thiết kế, và đánh giá giải thut.  
1.1 GII THUT VÀ NGÔN NGDIN ĐẠT GII THUT  
1.1.1 Gii thut  
Trong thc tế, khi gp phi mt vấn đề cn phi gii quyết, ta cn phải đƣa ra 1 phƣơng  
pháp để gii quyết vấn đề đó. Khi muốn gii quyết vấn đề bng cách sdng máy tính, ta cn  
phải đƣa ra 1 giải pháp phù hp vi vic thc thi bằng các chƣơng trình máy tính. Thuật ngữ  
“thuật toán” đƣợc dùng để chcác giải pháp nhƣ vậy.  
Thut toán có thể đƣợc định nghĩa nhƣ sau:  
Thut toán là mt chui hu hn các lnh. Mi lnh có mt ngữ nghĩa rõ ràng và có thể  
được thc hin vi một lượng hu hn tài nguyên trong mt khong hu hn thi gian.  
Chng hn lnh x = y + z là mt lnh có các tính cht trên.  
Trong mt thut toán, mt lnh có thlặp đi lặp li nhiu lần, tuy nhiên đối vi bt kbdữ  
liệu đầu vào nào, thut toán phi kết thúc sau khi thc thi mt shu hn lnh.  
Nhƣ đã nói ở trên, mi lnh trong thut toán phi có ngữ nghĩa rõ ràng và có thể đƣợc thc  
thi trong mt khong thi gian hu hạn. Tuy nhiên, đôi khi một lnh có ngữ nghĩa rõ ràng đối vi  
ngƣời này nhƣng lại không rõ ràng đối với ngƣời khác. Ngoài ra, thƣờng rất khó để chng minh  
mt lnh có thể đƣợc thc hin trong 1 khong hu hn thi gian. Thm chí, kckhi biết rõ ngữ  
nghĩa của các lệnh, cũng khó để có thchng minh là vi bt kbdliu đầu vào nào, thut  
toán sdng.  
Tiếp theo, chúng ta sxem xét mt ví dvxây dng thuật toán cho bài toán đèn giao  
thông:  
Gisử ngƣời ta cn thiết kế mt hthống đèn cho một nút giao thông có nhiều đƣờng giao  
nhau phc tạp. Để xây dng tp các trng thái của các đèn giao thông, ta cần phi xây dng mt  
chƣơng trình có đầu vào là tp các ngã rẽ đƣợc phép ti nút giao thông (lối đi thẳng cũng đƣợc  
xem nhƣ là 1 ngã rẽ) và chia tp này thành 1 sít nht các nhóm, sao cho tt ccác ngã rtrong  
nhóm có thể đƣợc đi cùng lúc mà không xảy ra tranh chấp. Sau đó, chúng ta sẽ gn trng thái ca  
các đèn giao thông với mi nhóm vừa đƣợc phân chia. Vi cách phân chia có snhóm ít nht, ta  
sxây dựng đƣợc 1 hthống đèn giao thông có ít trạng thái nht.  
3
Chng hn, ta xem xét bài toán trên với nút giao thông đƣợc cho nhƣ trong hình 1.1 ở  
dƣới. Trong nút giao thông trên, C và E là các đƣờng 1 chiều, các đƣờng còn li là 2 chiu. Có tt  
c13 ngã rti nút giao thông này. Mt sngã rcó thể đƣợc điđng thi, chng hn các ngã rẽ  
AB (tA rsang B) và EC. Mt sngã rẽ thì không đƣợc đi đồng thi (gây ra các tuyến giao  
thông xung đột nhau), chng hn AD và EB. Hthống đèn tại nút giao thông phi hoạt động sao  
cho các ngã rẽ xung đột (chng hạn AD và EB) không đƣợc cho phép đi tại cùng mt thời điểm,  
trong khi các ngã rẽ không xung đột thì có thể đƣợc đi tại cũng 1 thời điểm.  
E
D
C
B
A
Hình 1.1 Nút giao thông  
Chúng ta có thmô hình hóa vấn đề này bng mt cu trúc toán hc gọi là đồ th(sẽ đƣợc  
trình bày chi tiết ở chƣơng 5). Đthlà mt cu trúc bao gm 1 tập các đim gọi là đnh và mt  
tập các đƣờng nối các điểm, gi là các cnh. Vấn đề nút giao thông có thể đƣợc mô hình hóa bng  
một đồ thị, trong đó các ngã rẽ là các đỉnh, và có mt cnh nối 2 đnh biu thrng 2 ngã rẽ đó  
không thể đi đồng thời. Khi đó, đồ thca nút giao thông hình 1.1 có thể đƣợc biu diễn nhƣ ở  
hình 1.2.  
AB  
BA  
DA  
EA  
AC  
AD  
BD  
DC  
EC  
BC  
DB  
EB  
ED  
Hình 1.2 Đồ thngã rẽ  
4
Ngoài cách biu diễn trên, đồ thcòn có thể đƣợc biu din thông qua 1 bảng, trong đó phần  
tử ở hàng i, ct j có giá tr1 khi và chkhi có 1 cnh nối đnh i và đỉnh j.  
AB  
AC AD BA  
BC BD DA DB  
DC EA EB EC ED  
1
AB  
AC  
AD  
BA  
BC  
BD  
DA  
DB  
DC  
EA  
EB  
EC  
ED  
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
1
Bng 1.1 Biu diễn đồ thngã rbng bng  
Ta có thsdụng đồ thị trên để gii quyết vấn đề thiết kế hthống đèn cho nút giao thông  
nhƣ đã nói.  
Vic tô màu một đồ thlà vic gán cho mỗi đỉnh của đồ thmt màu sao cho không có hai  
đỉnh đƣợc ni bi 1 cnh nào đó lại có cùng mt màu. Dthy rng vấn đề nút giao thông có thể  
đƣợc chuyển thành bài toán tô màu đồ thcác ngã rẽ ở trên sao cho phi sdng smàu ít nht.  
Bài toàn tô màu đồ thị là bài toán đã xuất hiện và đƣợc nghiên cu trất lâu. Tuy nhiên, để  
tô màu một đồ thbt kvi smàu ít nht là bài toán rt phc tạp. Để giải bài toán này, ngƣời ta  
thƣng sdụng phƣơng pháp “vét cạn” để thtt ccác khả năng có thể. Có nghĩa, đầu tiên thử  
tiến hành tô màu đồ thbng 1 màu, tiếp theo dùng 2 màu, 3 màu, v.v. cho tới khi tìm ra phƣơng  
pháp tô màu thomãn yêu cu.  
Phƣơng pháp vét cạn có vthích hp với các đồ thnhỏ, tuy nhiên đối với các đồ thphc  
tp thì stiêu tn rt nhiu thi gian thc hiện cũng nhƣ tài nguyên hệ thng. Ta có thtiếp cn  
vấn đề theo hƣớng cgng tìm ra mt giải pháp đủ tt, không nht thiết phi là gii pháp tối ƣu.  
Chng hn, ta scgng tìm mt giải pháp tô màu cho đồ thngã rẽ ở trên vi mt smàu khá ít,  
gn vi smàu ít nht, và thi gian thc hin vic tìm gii pháp là khá nhanh. Gii thut tìm các  
giải pháp đủ tốt nhƣng chƣa phải tối ƣu nhƣ vậy gi là các gii thuật tìm theo “cảm tính”.  
Đối với bài toán tô màu đồ th, mt thut toán cảm tính thƣờng đƣợc sdng là thut toán  
“tham ăn” (greedy). Theo thuật toán này, đầu tiên ta sdng một màu để tô nhiu nht số đỉnh có  
th, thomãn yêu cu bài toán. Tiếp theo, sdng màu thứ 2 để tô các đỉnh chƣa đƣợc tô trong  
bƣớc 1, ri sdụng đến màu thứ 3 để tô các đỉnh chƣa đƣợc tô trong bƣớc 2, v.v.  
5
Để tô màu các đỉnh vi màu mi, chúng ta thc hiện các bƣớc:  
-
-
La chọn 1 đnh chƣa đƣợc tô màu và tô nó bng màu mi.  
Duyệt qua các đỉnh chƣa đƣợc tô màu. Vi mỗi đnh dng này, kim tra xem có cnh  
nào ni nó vi một đnh vừa đƣợc tô bi màu mi hay không. Nếu không có cnh nào  
thì ta tô màu đỉnh này bng màu mi.  
Thuật toán này đƣợc gọi là “tham ăn” vì tại mỗi bƣớc nó tô màu tt cả các đnh có thmà  
không cn phi xem xét xem việc tô màu đó có để li những điểm bt lợi cho các bƣớc sau hay  
không. Trong nhiều trƣờng hp, chúng ta có thể tô màu đƣợc nhiều đỉnh hơn bằng 1 màu nếu  
chúng ta bớt “tham ăn” và bỏ qua mt số đỉnh có thể tô màu đƣợc trong bƣớc trƣớc.  
Ví dụ, xem xét đồ thị ở hình 1.3, trong đó đỉnh 1 đã đƣợc tô màu đỏ. Ta thy rng hoàn toàn  
có thtô cả 2 đnh 3 và 4 là màu đỏ, với điều kiện ta không tô đỉnh số 2 màu đỏ. Tuy nhiên, nếu ta  
áp dng thuật toán tham ăn theo thứ tự các đỉnh ln dần thì đỉnh 1 và đỉnh 2 sẽ là màu đỏ, và khi  
đó đnh 3, 4 skhông đƣợc tô màu đỏ.  
3
a) Đồ thị ban đầu  
2
1
5
4
3
b) Tô màu theo thuật toán tham ăn  
c) Mt cách tô màu tốt hơn  
2
1
1
5
5
4
3
2
4
Hình 1.3 Đồ thị  
Bây gita sxem xét thuật toán tham ăn đƣợc áp dụng trên đồ thcác ngã rẽ ở hình 1.2 nhƣ  
thế nào. Gista bắt đầu từ đỉnh AB và tô cho đỉnh này màu xanh. Khi đó, ta có thể tô cho đỉnh  
AC màu xanh vì không có cnh nối đnh này với AB. AD cũng có thể tô màu xanh vì không có  
cnh ni AD với AB, AC. Đỉnh BA không có cnh ni tới AB, AC, AD nên cũng có thể đƣợc tô  
màu xanh. Tuy nhiên, đỉnh BC không tô đƣợc màu xanh vì tn ti cnh nối BC và AB. Tƣơng tự  
nhƣ vậy, BD, DA, DB không thtô màu xanh vì tn ti cnh ni chúng ti một trong các đỉnh đã  
tô màu xanh. Cnh DC thì có thtô màu xanh. Cui cùng, cạnh EA, EB, EC cũng không thể tô  
màu xanh trong khi ED có thể đƣợc tô màu xanh.  
6
AB  
BA  
DA  
EA  
AC  
BC  
DB  
EB  
AD  
BD  
DC  
EC  
ED  
Hình 1.4 Tô màu xanh cho các đỉnh của đồ thngã rẽ  
Tiếp theo, ta sdụng màu đỏ để tô các đỉnh chƣa đƣợc tô màu ở bƣớc trƣớc. Đầu tiên là  
BC. BD cũng có thể tô màu đỏ, tuy nhiên do tn ti cnh ni DA với BD nên DA không đƣợc tô  
màu đỏ. Tƣơng tự nhƣ vậy, DB không tô đƣợc màu đỏ còn EA có thể tô màu đỏ. Các đỉnh chƣa  
đƣợc tô màu còn lại đều có cnh ni tới các đỉnh đã tô màu đỏ nên cũng không đƣợc tô màu.  
AB  
BA  
DA  
EA  
AC  
BC  
DB  
EB  
AD  
BD  
DC  
EC  
ED  
Hình 1.5 Tô màu đỏ trong bƣớc 2  
Bƣớc 3, các đỉnh chƣa đƣợc tô màu còn li là DA, DB, EB, EC. Nếu ta tô màu đỉnh DA là  
màu lc thì DB cũng có thể tô màu lục. Khi đó, EB, EC không thể tô màu lc và ta chn 1 màu  
thứ tƣ là màu vàng cho 2 đỉnh này.  
7
AB  
BA  
DA  
EA  
AC  
BC  
DB  
EB  
AD  
BD  
DC  
EC  
ED  
Hình 1.6 Tô màu lục và màu vàng cho các đỉnh còn li  
Nhƣ vậy, ta có thể dùng 4 màu xanh, đỏ, lục, vàng để tô màu cho đồ thngã rẽ ở hình 1.2  
theo yêu cầu nhƣ đã nói ở trên. Bng tng hợp màu đƣợc mô tả nhƣ sau:  
Màu  
Xanh  
Ngã rẽ  
AB, AC, AD, BA, DC, ED  
BC, BD, EA  
Đỏ  
Lc  
Vàng  
DA, DB  
EB, EC  
Bng 1.2 Bng tng hp màu  
Thuật toán tham ăn không đảm bo cho ra kết qutối ƣu là số màu ít nhất đƣợc dùng. Tuy  
nhiên, ngƣời ta có thdùng mt stính cht của đồ thị để đánh giá kết quả thu đƣợc.  
Trli vi vấn đề nút giao thông, tkết qutô màu trên, ta có ththiết kế hthống đèn  
giao thông theo bng tng hợp màu trên, trong đó mỗi trng thái ca hthống đèn tƣơng ng vi  
1 màu. Ti mi trng thái, các ngã rnm tại hàng tƣơng ứng với màu đó đƣợc cho phép đi, các  
ngã rcòn li bcm.  
1.1.2 Ngôn ngdin đạt gii thut và kthut tinh chnh từng bƣớc  
Sau khi đã xây dựng đƣc mô hình toán hc cho vấn đề cn gii quyết, tiếp theo, ta có thể  
hình thành mt thuật toán cho mô hình đó. Phiên bản đầu tiên ca thuật toán thƣờng đƣợc din tả  
dƣới dng các phát biểu tƣơng đối tổng quát, và sau đó sẽ đƣợc tinh chnh dn từng bƣớc thành  
chui các lnh cthể, rõ ràng hơn. Ví dtrong thuật toán tham ăn ở trên, ta mô tả bƣớc thc hin  
mc tổng quát là “Lựa chọn 1 đnh chƣa đƣợc tô màu”. Với phát biểu nhƣ vậy, ta hy vng rng  
ngƣời đọc có thnắm đƣợc ý tƣởng thc hiện thao tác. Tuy nhiên, để chuyn các phát biểu đó  
8
thành chƣơng trình máy tính, cần phi qua 1 số bƣớc tinh chnh cho tới khi đạt đến mc các phát  
biểu đều có thể đƣợc chuyển đổi trc tiếp sang các lnh ca ngôn nglp trình.  
Trli ví dvề bài toán tô màu đồ thbng thuật toán tham ăn. Ta sẽ xem xét vic mô tả  
thut toán tmc tng quát cho ti mt smc cthể hơn. Tại bƣớc nào đó, giả sử ta có đồ thG  
có 1 số đỉnh đã đƣợc tô màu theo quy tắc đã nói ở trên. Thtc Tham_an dƣới đây sẽ xác định 1  
tập các đỉnh chƣa đƣợc tô màu thuc G mà có thể cùng đƣợc tô bi 1 màu mi. Thtc này sẽ  
đƣợc gọi đi gọi li nhiu ln cho ti khi tt cả các đỉnh của G đã đƣợc tô màu. mc tng quát,  
thtục đƣợc mô tả nhƣ sau:  
void Tham_an(GRAPH:G, SET: Mau_moi)  
{
Mau_moi = Tp rng;  
For mi  
đnh v chƣa  
If v không  
đƣợc tô màu thuc G  
đƣợc ni ti đnh nào trong tp Mau_moi  
{
}
Tô màu mi cho đnh v;  
Đƣa v vào tập Mau_moi;  
}
Trong thtc trên, ta sdng mt ngôn ngdiễn đạt gii thut tựa nhƣ ngôn ngữ lp trình  
C. Trong ngôn ngnày, các lệnh đƣợc mô tả dƣới dng ngôn ngtự nhiên nhƣng vẫn tuân theo cú  
pháp ca ngôn nglp trình.  
Ta nhn thy rng các phát biu trong thtc trên còn rt tổng quát, và chƣa tƣơng ứng vi  
các lnh trong ngôn nglp trình, chng hạn các điều kin kim tra trong câu lnh For và If ở  
mc mô thin ti là không thc hiện đƣợc trong C. Để thtc có ththực thi đƣợc, ta cn phi  
tinh chnh mt số bƣớc để có thchuyển đổi về chƣơng trình trong ngôn ngữ lp trình C thông  
thƣng.  
Đầu tiên, ta xem xét lnh If ở trên. Để kim tra xem đỉnh v có ni ti một đnh nào đó trong  
tp Mau_moi hay không, ta xem xét từng đỉnh w trong Mau_moi và sdụng đồ thị G để kim tra  
xem có tn ti cnh nối v à w không. Để lƣu giữ kết qukim tra, ta sdng mt biến ton_tai.  
Khi đó, thủ tục đƣợc tinh chỉnh nhƣ sau:  
void Tham_an(GRAPH:G, SET: Mau_moi)  
{
int ton_tai;  
Mau_moi = Tp rng;  
For mi  
đnh v chƣa  
đƣợc tô màu thuc G  
{
ton_tai = 0;  
For mi  
đnh w thuc Mau_moi  
If tn ti cnh ni v và w trong G  
ton_tai = 1;  
If ton_tai = = 1  
{
9
Tô màu mi cho đnh v;  
Đƣa v vào tập Mau_moi;  
}
}
}
Nhƣ vậy, ta có ththy rằng điều kin kim tra trong phát biểu If đã đƣợc mô tcthể hơn  
bng các phát nhỏ hơn,và các phát biểu này có thddàng chuyn thành các lnh cthtrong C.  
Tiếp theo, ta stinh chnh các vòng lặp For để duyệt qua các đỉnh thuc G và thuộc Mau_moi. Để  
làm điu này, tt nht là ta thay For bng mt vòng lp While, biến v ban đầu đƣợc gán là phn tử  
đầu tiên chƣa tô màu trong tập G, và ti mỗi bƣớc lp, biến v sẽ đƣợc thay bng phn tử chƣa tô  
màu tiếp theo trong G. Vòng lp F bên trong có ththc hiện tƣơng tự.  
Void Tham_an(GRAPH:G, SET: Mau_moi)  
{
int ton_tai;  
int v, w  
Mau_moi = Tp rng;  
v = đnh chƣa tô màu  
While v != NULL  
{
đầu tiên trong G ;  
ton_tai = 0;  
w = đnh đầu tiên trong Mau_moi;  
While w != NULL{  
If tn ti cnh ni v và w trong G  
ton_tai = 1;  
w = đnh tiếp theo trong Mau_moi ;  
}
If ton_tai = = 1  
{
Tô màu mi cho đnh v;  
Đƣa v vào tập Mau_moi;  
}
v = đnh chƣa tô màu tiếp theo trong G;  
}
}
Nhƣ vậy, ta thy các phát biu trong thtục đã khá cụ thể, tuy nhiên, để chuyển đổi thành  
chƣơng trình trong ngôn ngữ C thì cn tới vài bƣớc tinh chnh na. Bạn đọc hãy xem nhƣ đó là  
bài tp và tgiải để hiu rõ vngôn ngdiễn đạt gii thuật cũng nhƣ kỹ thut tinh chnh tng  
bƣớc.  
1.2 PHÂN TÍCH THUT TOÁN  
Vi mi vấn đề cn gii quyết, ta có thtìm ra nhiu thut toán khác nhau. Có nhng thut  
toán thiết kế đơn giản, dhiu, dlp trình và sa li, tuy nhiên thi gian thc hin ln và tiêu tn  
10  
nhiều tài nguyên máy tính. Ngƣợc li, có nhng thut toán thiết kế và lp trình rt phc tp,  
nhƣng cho thời gian chạy nhanh hơn, sử dng tài nguyên máy tính hiu quả hơn. Khi đó, câu hỏi  
đặt ra là ta nên la chn gii thuật nào để thc hin?  
Đối vi những chƣơng trình chỉ đƣợc thc hin mt vài ln thì thi gian chy không phi là  
tiêu chí quan trng nhất. Đối vi bài toán kiu này, thời gian để lp trình viên xây dng và hoàn  
thin thuật toán đáng giá hơn thời gian chy của chƣơng trình và nhƣ vy nhng gii thuật đơn  
gin vmt thiết kế và xây dựng nên đƣợc la chn.  
Đối vi những chƣơng trình đƣợc thc hin nhiu ln thì thi gian chy của chƣơng trình  
đáng giá hơn rất nhiu so vi thời gian đƣợc sdụng để thiết kế và xây dựng nó. Khi đó, lựa chn  
mt gii thut có thi gian chạy nhanh hơn (cho dù việc thiết kế và xây dng phc tạp hơn) là một  
la chn cn thiết. Trong thc tế, trong giai đoạn đầu ca vic gii quyết vấn đề, mt gii thut  
đơn giản thƣờng đƣợc thc hiện trƣớc nhƣ là 1 nguyên mẫu (prototype), sau đó nó sẽ đƣợc phân  
tích, đánh giá, và cải tiến thành các phiên bn tốt hơn.  
1.2.1 Ƣớc lƣợng thi gian thc hiện chƣơng trình  
Thi gian chy của 1 chƣơng trình phụ thuc vào các yếu tsau:  
-
Dliệu đầu vào  
-
-
-
Chất lƣợng của mã máy đƣợc to ra bởi chƣơng trình dịch  
Tốc độ thc thi lnh ca máy  
Độ phc tp vthi gian ca thut toán  
Thông thƣờng, thi gian chy của chƣơng trình không phụ thuc vào giá trdliệu đầu vào  
mà phthuộc vào kích thƣớc ca dliệu đầu vào. Do vy thi gian chy của chƣơng trình nên  
đƣợc định nghĩa nhƣ là một hàm có tham số là kích thƣớc dliệu đầu vào. Gisử T là hàm ƣớc  
lƣng thi gian chy của chƣơng trình, khi đó với dliệu đầu vào có kích thƣớc n thì thi gian  
chy của chƣơng trình là T(n). Ví dụ, đối vi mt số chƣơng trình thì thời gian chy là an hoc  
2
an, trong đó a là hằng số. Đơn vị của hàm T(n) là không xác định, tuy nhiên ta có thể xem nhƣ  
T(n) là tng slệnh đƣợc thc hiện trên 1 máy tính lý tƣởng.  
Trong nhiều chƣơng trình, thời gian thc hin không chphthuộc vào kích thƣớc dliu  
vào mà còn phthuc vào tính cht ca nó. Khi tính cht dliu vào thomãn mt số đặc điểm  
nào đó thì thời gian thc hiện chƣơng trình có thể là ln nht hoc nhnhất. Khi đó, ta định nghĩa  
thi gian thc hiện chƣơng trình T(n) trong trƣờng hp xu nht hoc tt nhất. Đó là thời gian  
thc hin ln nht hoc nhnht trong tt ccác bdliệu vào có kích thƣớc n. Ta cũng định  
nghĩa thời gian thc hin trung bình của chƣơng trình trên mọi bdliu vào kích thƣớc n. Trong  
thc tế, ƣớc lƣợng thi gian thc hiện trung bình khó hơn nhiều so vi thi gian thc hin trong  
trƣng hp xu nht hoc tt nht, bi vì vic phân tích thuật toán trong trƣờng hp trung bình  
khó hơn về mt toán học, đồng thi khái niệm “trung bình” không có ý nghĩa thực srõ ràng.  
Yếu tchất lƣợng của mã máy đƣợc to bởi chƣơng trình dịch và tốc độ thc thi lnh ca  
máy cũng ảnh hƣởng ti thi gian thc hiện chƣơng trình cho thấy chúng ta không ththhin  
thi gian thc hin chuơng trình dƣới đơn vị thi gian chun, chng hn phút hoc giây. Thay vào  
2
đó, ta có thể phát biu thi gian thc hiện chƣơng trình tỷ lvi n hoc n v.v. Hsca tllà 1  
hng số chƣa xác định, phthuộc vào máy tính, chƣơng trình dịch, và các nhân tkhác.  
Ký hiu O(n)  
Để biu thcấp độ tăng của hàm, ta sdng ký hiu O(n). Ví d, ta nói thi gian thc hin  
2
2
T(n) của chƣơng trình là O(n), có nghĩa là tồn ti các hng số duơng c và n  
0
sao cho T(n) ≤ cn  
với n ≥ n0.  
11  
2
2
Ví d, xét hàm T(n) = (n+1)  
.
Ta có ththy T(n) là O(n) vi n = 1 và c = 4, vì ta có T(n)  
0
2
2
3
= (n+1) < 4n vi mọi n ≥ 1. Trong ví dụ này, ta cũng có thể nói rng T(n) là O(n ), tuy nhiên,  
2
phát biểu này “yếu” hơn phát biểu T(n) là O(n).  
Nhìn chung, ta nói T(n) là O(f(n)) nếu tn ti các hng số dƣơng c và n0sao cho T(n) <  
c.f(n) với n ≥ n  
0
. Một chƣơng trình có thời gian thc hiện là O(f(n)) thì đƣợc xem là có cấp độ  
tăng f(n).  
Việc đánh giá các chƣơng trình có thể đƣợc thc hin qua việc đánh giá các hàm thời gian  
chy của chƣơng trình,bqua các hng stl. Vi githiết này, một chƣơng trình với thi gian  
2
3
thc hin là O(n) stốt hơn chƣơng trình với thi gian chy O(n). Bên cnh các yếu thng số  
xut phát từ chƣơng trình dịch và máy, còn có thêm hng stbn thân chuơng trình. Ví dụ, trên  
2
cùng một chƣơng trình dịch và cùng 1 máy, chƣơng trình đầu tiên có thi gian thc hin là 100n,  
3
3
2
trong khi chuơng trình thứ 2 có thi gian thc hin là 5n. Vi n nh, có th5n nhỏ hơn 100n,  
3
2
tuy nhiên với n đủ ln thì 5n sln hơn 100nđáng kể.  
Mt lý do nữa để xem xét cấp độ tăng về thi gian thc hin của chƣơng trình là nó cho  
phép ta xác định độ ln ca bài toán mà ta có thgii quyết. Mc dù máy tính có tốc độ ngày càng  
2
cao, tuy nhiên, vi những chƣơng trình có thời gian thc hin có cấp độ tăng lớn (tn trlên),  
thì việc tăng tốc độ ca máy tính to ra skhác biệt không đáng kể về kích thƣớc bài toán có thể  
xbi máy tính trong mt khong thi gian cố định.  
1.2.2 Tính toán thi gian thc hiện chƣơng trình  
Để tính toán đƣợc thi gian thc hiện chƣơng trình, ta cần chú ý mt snguyên tc cng và  
nhân cấp độ tăng của hàm nhƣ sau :  
GisT1(n) và T2(n) là thi gian chy của 2 đoạn chƣơng trình P1 và P2, trong đó T1(n) là  
O(f(n)) và T2(n) là O(g(n)). Khi đó, thời gian thc hin của 2 đoạn chƣơng trình trình nối tiếp P1,  
P
2
O(max(f(n), g(n))).  
Nguyên tc cng trên có thsdụng để tính thi gian thc hin của chƣơng trình bao gồm  
1 stun tự các bƣớc, mỗi bƣớc có thể là 1 đoạn chƣơng trình bao gồm 1 svòng lp và rnhánh.  
2
3
Ví d, gista có 3 bƣớc thc hiện chƣơng trình lần lƣợt có thi gian chy là O(n), O(n),  
2
3
3
O(nlog n). Khi đó, thời gian chy của 2 đoạn chƣơng trình đầu là O(max(n, n)) = O(n), còn thi  
3
3
gian chy ca cả 3 đoạn chƣơng trình là O(max(n, nlog n)) = O(n).  
Nguyên tc nhân cấp độ tăng của hàm nhƣ sau: Với githiết vT  
1
(n) và T (n) nhƣ trên, nếu  
2
2 đoạn chƣơng trình P1 và P2 không đƣợc thc hin tun tmà lng nhau thì thi gian chy tng  
thslà T1(n).T2(n) = O(f(n).(g(n)).  
Để minh hocho vic phân tích và tính toán thi gian thc hin của 1 chƣơng trình, ta sẽ  
xem xét mt thuật toán đơn gian để sp xếp các phn tca mt tp hợp, đó là thuật toán sp xếp  
ni bt (bubble sort).  
Thuật toán nhƣ sau :  
void buble (int a[n]){  
int i, j, temp;  
1.  
2.  
3.  
for (i = 0; i < n-1; i++)  
for (j = n-1; j>= i+1; j--)  
if (a[j-1] > a[j]{  
// Đổi chcho a[j] và a[j-1]  
temp = a[j-1];  
4.  
5.  
a[j-1] = a[j];  
12  
6.  
}
a[j] = temp;  
}
Trong thut toán này, mi ln duyt ca vòng lp trong (biến duyt j) sẽ làm “nổi” lên trên  
phn tnhnht trong các phn tử đƣợc duyt.  
Dthy rằng kích thƣớc dliu vào chính là sphn tử đƣợc sp, n. Mi lnh gán scó  
thi gian thc hin cố đnh, không phthuc vào n, do vy, các lnh 4, 5, 6 scó thi gian thc  
hin là O(1), tc thi gian thc hin là hng s. Theo quy tc cng cấp độ tăng thì tổng thi gian  
thc hin c3 lnh là O(max(1, 1, 1)) = O(1).  
Tiếp theo ta sxem xét thi gian thc hin ca các lnh lp và rnhánh. Lnh If kim tra  
điều kiện để thc hin nhóm lnh gán 4, 5, 6. Vic kiểm tra điều kin scó thi gian thc hin là  
O(1). Ngoài ra, chúng ta chƣa biết đƣợc là điều kin có thomãn hay không, tc là không biết  
đƣợc nhóm lệnh gán có đƣợc thc hin hay không. Do vy, ta githiết trƣờng hp xu nht là tt  
ccác ln kiểm tra điều kiện đều thomãn, và các lệnh gán đƣợc thc hiện. Nhƣ vậy, toàn blnh  
If scó thi gian thc hin là O(1).  
Tiếp tc xét từ trong ra ngoài, ta xét đến vòng lp trong (biến duyt j). Trong vòng lp này,  
ti mỗi bƣớc lp ta cn thc hiện các thao tác nhƣ kiểm tra đã gặp điều kin dừng chƣa và tăng  
biến duyt lên 1 nếu chƣa dừng. Nhƣ vậy, mỗi bƣớc lp có thi gian thc hin là O(1). Số bƣớc  
lp là n-i, do đó theo quy tắc nhân cấp độ tăng thì tổng thi gian thc hin ca vòng lp này là  
O((n-i)x1) = O(n-i).  
Cui cùng, ta xét vòng lp ngoài cùng (biến duyt i). Vòng lặp này đƣợc thc hin (n-1) ln,  
do đó, tổng thi gian thc hin của chƣơng trình là:  
2
2
∑ (n-i) = n(n-1)/2 = n/2- n/2 = O(n)  
2
Nhƣ vậy, thi gian thc hin gii thut sp xếp ni bt là tlvi n.  
Mt squy tc chung trong vic phân tích và tính toán thi gian thc hiện chƣơng trình  
-
-
Thi gian thc hin các lệnh gán, đọc, ghi .v.v, luôn là O(1).  
Thi gian thc hin chui tun tcác lệnh đƣợc xác định theo quy tc cng cấp độ tăng.  
Có nghĩa là thời gian thc hin ca cnhóm lnh tun tự đƣợc tính là thi gian thc  
hin ca lnh ln nht.  
-
-
Thi gian thc hin lnh rẽ nhánh If đƣợc tính bng thi gian thc hin các lnh khi  
điều kin kiểm tra đƣợc thomãn và thi gian thc hin vic kiểm tra điều kin. Thi  
gian thc hin vic kiểm tra điều kin luôn là O(1).  
Thi gian thc hin 1 vòng lặp đƣợc tính là tng thi gian thc hin các lnh thân  
vòng lp qua tt cả các bƣớc lp và thời gian để kiểm tra điều kin dừng (thƣờng là  
O(1)). Thi gian thc hiện này thƣờng đƣợc tính theo quy tc nhân cấp độ tăng số ln  
thc hiện bƣớc lp và thi gian thc hin các lnh thân vòng lp. Các vòng lp phi  
đƣợc tính thi gian thc hin mt cách riêng r.  
1.3 TÓM TẮT CHƢƠNG 1  
Các kiến thc cn nhớ trong chƣơng 1:  
-
Thut toán là mt chui hu hn các lnh. Mi lnh có mt ngữ nghĩa rõ ràng và có thể  
đƣợc thc hin vi một lƣng hu hn tài nguyên trong mt khong hu hn thi gian.  
13  
-
-
-
-
Thuật toán thƣờng đƣợc mô tbng các ngôn ngdiễn đạt gii thut gn vi ngôn ngữ  
tnhiên. Các mô tnày sẽ đƣợc tnh chnh dn dần để đạt ti mc ngôn nglp trình.  
Thi gian thc hin thuật toán thƣờng đƣợc coinhƣ là 1 hàm của kích thƣớc dliệu đầu  
vào.  
Thi gian thc hin thuật toán thƣờng đƣợc tính trong các trƣờng hp tt nht, xu nht,  
hoc trung bình.  
Để biu thcấp độ tăng của hàm, ta sdng ký hiu O(n). Ví d, ta nói thi gian thc  
2
hin T(n) của chƣơng trình là O(n), có nghĩa tn ti các hng số duơng c và n0 sao  
2
cho T(n) ≤ cn với n ≥ n.  
0
-
-
Cấp độ tăng về thi gian thc hin của chƣơng trình cho phép ta xác định độ ln ca bài  
toán mà ta có thgii quyết.  
Quy tc cng cấp độ tăng: Giả sT1(n) và T2(n) là thi gian chy của 2 đoạn chƣơng  
trình P1 và P2, trong đó T1(n) là O(f(n)) và T2(n) là O(g(n)). Khi đó, thời gian thc hin  
của 2 đoạn chƣơng trình trình nối tiếp P1, P2 O(max(f(n), g(n))).  
-
Quy tc nhân cấp độ tăng: Với githiết vT1(n) và T2(n) nhƣ trên, nếu 2 đoạn chƣơng  
trình P1 và P2 không đƣợc thc hin tun tmà lng nhau thì thi gian chy tng thsẽ  
là T1(n).T2(n) = O(f(n).(g(n)).  
1.4 CÂU HI VÀ BÀI TP  
1. Trình bày khái nim thuật toán? Các đặc điểm ca thut toán?  
2. Trong mt giải vô địch bóng đá có 6 đội bóng đá vòng tròn. Các đội là A, B, C, D, E, F.  
Đội A đã đá với B và C. Đội B đã đá với D và F. Đội E đã đá với C và F. Mỗi đội đá  
mi tun 1 trn. Hãy lp 1 lịch cho các đội bóng sao cho tt cả các đội đều đá đủ strn  
quy định trong 1 stun va phi. Thc hin phân tích, thiết kế thut toán. Biu din  
thut toán bng ngôn ngdiễn đạt gii thuật, sau đó tinh chỉnh vdng ngôn nglp  
trình C.  
3. Thi gian thc hin một chƣơng trình thƣờng phthuc vào các yếu tnào? Phân tích  
cthtng yếu t.  
4. Nói thi gian thc hiện chƣơng trình là T(n) = O(f(n)) có nghĩa là gì? Cho ví dminh  
ho.  
5. Nêu quy tc cng và nhân cấp độ tăng của hàm. Có ví dminh ho.  
6. Nêu các quy tc chung trong việc phân tích và đánh giá thời gian thc hiện chƣơng  
trình.  
14  
CHƢƠNG 2  
ĐỆ QUI  
Chƣơng 2 trình bày các khái niệm về đnh nghĩa đệ qui, chƣơng trình đệ qui. Ngoài vic  
trình bày các ƣu điểm của chƣơng trình đệ qui, các tình hung không nên sdụng đệ qui cũng  
đƣợc đề cp cùng vi các ví dminh ho.  
Chƣơng này cũng đề cp và phân tích mt sthuật toán đệ qui tiêu biểu và kinh điển nhƣ  
bài toán tháp Hà ni, các thut toán quay lui .v.v  
Để hc tốt chƣơng này, sinh viên cần nm vng phn lý thuyết. Sau đó, nghiên cứu kcác  
phân tích thut toán và thc hin chy thử chƣơng trình. Có thể thay đổi mt số điểm trong  
chƣơng trình và chạy thử để nm kỹ hơn về thuật toán. Ngoài ra, sinh viên cũng có thể tìm các bài  
toán tƣơng tự để phân tích và gii quyết bằng chƣơng trình.  
2.1 KHÁI NIM  
Đệ qui là mt khái niệm cơ bản trong toán hc và khoa hc máy tính. Một đối tƣợng đƣợc  
gọi là đệ qui nếu nó hoc mt phn của nó đƣợc định nghĩa thông qua khái niệm vchính nó. Mt  
sví dụ điển hình vviệc định nghĩa bằng đệ qui là:  
1- Định nghĩa số tnhiên:  
- 0 là stnhiên.  
- Nếu k là stự nhiên thì k+1 cũng là số tnhiên.  
Nhƣ vậy, bắt đầu tphát biểu “0 là số tự nhiên”, ta suy ra 0+1=1 là số tnhiên. Tiếp  
theo 1+1=2 là stnhiên, v.v.  
2- Định nghĩa xâu ký tự bằng đệ qui:  
- Xâu rng là 1 xâu ký t.  
- Mt chcái bt kghép vi 1 xâu sto thành 1 xâu mi.  
Tphát biểu “Xâu rỗng là 1 xâu ký tự”, ta ghép bất k1 chcái nào vi xâu rỗng đều  
to thành xâu ký tự. Nhƣ vậy, chcái bt kcó thcoi là xâu ký t. Tiếp tc ghép 1 chữ  
cái bt kvi 1 chcái bt kỳ cũng tạo thành 1 xâu ký t, v.v.  
3- Định nghĩa hàm giai thừa, n!.  
- Khi n=0, định nghĩa 0!=1  
- Khi n>0, định nghĩa n!=(n-1)! x n  
Nhƣ vậy, khi n=1, ta có 1!=0!x1 = 1x1=1. Khi n=2, ta có 2!=1!x2=1x2=2, v.v.  
Trong lĩnh vực lp trình, một chƣơng trình máy tính gọi là đqui nếu trong chƣơng trình có  
li gọi chính nó. Điều này, thot tiên, nghe có vẻ hơi vô lý. Một chƣơng trình không thể gi mãi  
chính nó, vì nhƣ vậy sto ra mt vòng lp vô hn. Trên thc tế, một chƣơng trình đệ qui trƣớc  
khi gi chính nó bao giờ cũng có một thao tác kiểm tra điều kin dng. Nếu điều kin dng tha  
mãn, chƣơng trình sẽ không gi chính nó nữa, và quá trình đệ qui chm dt. Trong các ví dụ ở  
trên, ta đều thấy có các điểm dng. Chng hn, trong ví dthnht, nếu k = 0 thì có thsuy ngay  
k là stnhiên, không cn tham chiếu xem k-1 có là stnhiên hay không.  
Nhìn chung, các chƣơng trình đệ qui đều có các đặc điểm sau:  
15  
-
-
Chƣơng trình này có thể gi chính nó.  
Khi chƣơng trình gọi chính nó, mục đích là để gii quyết 1 vấn đề tƣơng tự, nhƣng nhỏ  
hơn.  
-
Vấn đề nhỏ hơn này, cho tới 1 lúc nào đó, sẽ đơn giản ti mức chƣơng trình có thể tự  
gii quyết đƣợc mà không cn gi ti chính nó na.  
Khi chƣơng trình gọi ti chính nó, các tham s, hoc khong tham s, thƣng trnên nhỏ  
hơn, để phn ánh 1 thc tế là vấn đề đã trở nên nhỏ hơn, dễ hơn. Khi tham số gim ti mc cc  
tiu, một điều kiện so sánh đƣợc kiểm tra và chƣơng trình kết thúc, chm dt vic gi ti chính  
nó.  
Ƣu đim của chƣơng trình đệ qui cũng nhƣ định nghĩa bằng đệ qui là có ththc hin mt  
số lƣợng lớn các thao tác tính toán thông qua 1 đoạn chƣơng trình ngắn gn (thm chí không có  
vòng lp, hoặc không tƣờng minh để có ththc hin bng các vòng lp) hay có thể đnh nghĩa  
mt tp hp vô hn các đối tƣợng thông qua mt shu hn li phát biểu. Thông thƣờng, mt  
chƣơng trình đƣợc viết dƣới dạng đệ qui khi vấn đề cn xlý có thể đƣợc gii quyết bằng đệ qui.  
Tc là vấn đề cn gii quyết có thể đƣa đƣợc vvấn đề tƣơng tự, nhƣng đơn giản hơn. Vấn đề này  
lại đƣợc đƣa về vấn đề tƣơng tự nhƣng đơn giản hơn nữa .v.v, cho đến khi đơn giản ti mc có  
thtrc tiếp gii quyết đƣợc ngay mà không cần đƣa về vấn đề đơn giản hơn nữa.  
2.1.1 Điều kin để có thviết một chƣơng trình đệ qui  
Nhƣ đã nói ở trên, để chƣơng trình có thể viết dƣới dạng đệ qui thì vấn đề cn xlý phi  
đƣợc gii quyết 1 cách đệ qui. Ngoài ra, ngôn ngữ dùng để viết chƣơng trình phải htrợ đệ qui.  
Để có thviết chƣơng trình đệ qui chcn sdng ngôn nglp trình có htrhàm hoc thtc,  
nhờ đó một thtc hoc hàm có thcó li gọi đến chính thtc hoặc hàm đó. Các ngôn ngữ lp  
trình thông dng hiện nay đều htrkthut này, do vy vấn đề công cụ để tạo các chƣơng trình  
đệ qui không phi là vấn đề cn phi xem xét. Tuy nhiên, cũng nên lƣu ý rằng khi mt thtục đệ  
qui gọi đến chính nó, mt bn sao ca tập các đối tƣợng đƣợc sdng trong thtục này nhƣ các  
biến, hng, các thtục con, .v.v. cũng đƣợc to ra. Do vy, nên hn chế vic khai báo và sdng  
các đối tƣợng này trong thtục đệ qui nếu không cn thiết nhm tránh lãng phí bnhớ, đặc bit  
đối vi các li gọi đệ qui đƣợc gọi đi gọi li nhiu lần. Các đối tƣợng cc bca 1 thtục đệ qui  
khi đƣợc to ra nhiu ln, mặc dù có cùng tên, nhƣng do khác phạm vi nên không ảnh hƣởng gì  
đến chƣơng trình. Các đối tƣợng đó sẽ đƣợc gii phóng khi thtc cha nó kết thúc.  
Nếu trong mt thtc có li gọi đến chính nó thì ta gọi đó là đệ qui trc tiếp. Còn trong  
trƣng hp mt thtc có mt li gi thtc khác, thtc này li gọi đến thtục ban đầu thì  
đƣợc gọi là đệ qui gián tiếp. Nhƣ vậy, trong chƣơng trình khi nhìn vào có thể không thy ngay sự  
đệ qui, nhƣng khi xem xét kỹ hơn thì sẽ nhn ra.  
2.1.2 Khi nào không nên sdng đệ qui  
Trong nhiều trƣờng hp, một chƣơng trình có thviết dƣới dạng đệ qui. Tuy nhiên, đệ qui  
không hẳn đã là giải pháp tt nht cho vấn đề. Nhìn chung, khi chƣơng trình có thể viết dƣới dng  
lp hoc các cu trúc lnh khác thì không nên sdụng đệ qui.  
Lý do thnhất là, nhƣ đã nói ở trên, khi mt thtục đệ qui gi chính nó, tập các đối tƣợng  
đƣợc sdng trong thtục này nhƣ các biến, hng, cu trúc .v.v sẽ đƣợc to ra. Ngoài ra, vic  
chuyển giao điều khin tcác thtục cũng cần lƣu trữ các thông sdùng cho vic trlại điều  
khin cho thtc ban đầu.  
Lý do thhai là vic sdụng đệ qui đôi khi tạo ra các tính toán tha, không cn thiết do  
tính cht tự động gi thc hin thtục khi chƣa gặp điều kin dng của đệ qui. Để minh ha cho  
16  
điều này, chúng ta sxem xét mt ví dụ, trong đó cả đệ qui và lặp đều có thể đƣợc sdng. Tuy  
nhiên, ta sẽ phân tích để thy sdụng đệ qui trong trƣờng hp này gây lãng phí bnhvà các tính  
toán không cn thiết nhƣ thế nào.  
Xét bài toán tính các phn tcủa dãy Fibonaci. Dãy Fibonaci đuợc định nghĩa nhƣ sau:  
-
-
F(0) = 0  
F(1) =1  
-
Vi n >1 thì F(n) = F(n-1) + F(n-2)  
Rõ ràng là nhìn vào một đnh nghĩa đệ qui nhƣ trên, chƣơng trình tính phần tca dãy  
Fibonaci có vẻ nhƣ rất phù hp vi thuật toán đệ qui. Phƣơng thức đệ qui để tính dãy này có thể  
đƣợc viết nhƣ sau:  
int Fibonaci(int i){  
if (i==0) return 0;  
if (i==1) return 1;  
return Fibonaci(i-1) + Fibonaci (i-2)  
}
Kết quthc hiện chƣơng trình không có gì sai. Tuy nhiên, chú ý rằng mt li gọi đệ qui  
Fibonaci (n) sdn ti 2 li gọi đệ qui khác ng vi n-1 và n-2. Hai li gi này li gây ra 4 li gi  
na .v.v, cứ nhƣ vậy sli gọi đệ qui sẽ tăng theo cấp số mũ. Điều này rõ ràng là không hiu quả  
vì trong scác li gọi đệ qui đó có rất nhiu li gi trùng nhau. Ví dli gọi đệ qui Fibonaci (6)  
sdẫn đến 2 li gi Fibonaci (5) và Fibonaci (4). Li gi Fibonaci (5) sgi Fibonaci (4) và  
Fibonaci (3). Ngay chỗ này, ta đã thấy có 2 li gọi Fibonaci (4) đƣợc thc hin. Hình 2.1 cho thy  
scác li gọi đƣợc thc hin khi gi thtc Fibonaci (6).  
6
5
4
4
3
2
3
1
1
0
2
2
1
3
2
1
0
1
0
2
1
1
0
1
0
Hình 2.1 Các li gọi đệ qui đƣợc thc hin khi gi thtc Fibonaci (6)  
Trong hình vtrên, ta thấy để tính đƣợc phn tth6 thì cn có ti 25 li gọi ! Sau đây, ta  
sxem xét vic sdng vòng lặp để tính giá trcác phn tcủa dãy Fibonaci nhƣ thế nào.  
Đầu tiên, ta khai báo mt mng F các stự nhiên để cha các sFibonaci. Vòng lặp để tính  
và gán các snày vào mng rất đơn giản nhƣ sau:  
F[0]=0;  
F[1]=1;  
for (i=2; i<n-1; i++)  
17  
F[i] = F[i-1] + F [i-2];  
Rõ ràng là vi vòng lp này, mi sFibonaci (n) chỉ đƣợc tính 1 lần thay vì đƣợc tính toán  
chồng chéo nhƣ ở trên.  
Tóm li, nên tránh sdụng đệ qui nếu có mt gii pháp khác cho bài toán. Mc dù vy, mt  
sbài toán tra rt phù hp với phƣơng pháp đệ qui. Vic sdụng đệ qui để gii quyết các bài  
toán này hiu quvà rt dhiu. Trên thc tế, tt ccác gii thuật đệ qui đều có thể đƣợc đƣa về  
dng lp (còn gọi là “khử” đệ qui). Tuy nhiên, điều này có thể làm cho chƣơng trình trở nên phc  
tp, nht là khi phi thc hiện các thao tác điều khiển stack đệ qui (bạn đọc có thtìm hiu thêm  
kthut khử đệ qui các tài liu tham kho khác), dẫn đến việc chƣơng trình trở nên rt khó hiu.  
Phn tiếp theo strình bày mt sthuật toán đệ qui điển hình.  
2.2 THIT KGII THUT ĐỆ QUI  
2.2.1 Chƣơng trình tính hàm n!  
Theo định nghĩa đã trình bày ở phần trƣớc, n! = 1 nếu n=0, ngƣợc li, n! = (n-1)! * n.  
int giaithua (int n){  
if (n==0) return 1;  
else return giaithua(n-1) * n;  
}
Trong chƣơng trình trên, điểm dng ca thuật toán đệ qui là khi n=0. Khi đó, giá trị ca  
hàm giaithua(0) có thể tính đƣợc ngay lp tc mà không cn gi hạm đệ qui khác. Nếu điều kin  
dng không tha mãn, scó mt li gọi đệ qui hàm giai tha vi tham slà n-1, nhỏ hơn tham số  
ban đầu 1 đơn vị (tức là bài toán tính n! đã đƣợc qui về bài toán đơn giản hơn là tính (n-1)!).  
2.2.2 Thut toán Euclid tính ƣớc schung ln nht ca 2 số nguyên dƣơng  
Ƣớc schung ln nht (USCLN) ca 2 số nguyên dƣơng m, n là 1 số k ln nht sao cho m  
và n đều chia hết cho k. Một phƣơng pháp đơn giản nhất để tìm USCLN ca m và n là duyt tsố  
nhỏ hơn trong 2 số m, n cho đến 1, ngay khi gp số nào đó mà m và n đều chia hết cho nó thì đó  
chính là USCLN của m, n. Tuy nhiên, phƣơng pháp này không phải là cách tìm USCLN hiu qu.  
Cách đây hơn 2000 năm, Euclid đã phát minh ra một gii thut tìm USCLN ca 2 snguyên  
dƣơng m, n rất hiu quả. Ý tƣởng cơ bản ca thuật toán này cũng tƣơng tự nhƣ ý tƣởng đệ qui, tc  
là đƣa bài toán về 1 bài toán đơn giản hơn. Cụ th, gism lớn hơn n, khi đó việc tính USCLN  
ca m và n sẽ đƣợc đƣa về bài toán tính USCLN ca m mod n và n vì USCLN(m, n) = USCLN(m  
mod n, n).  
Thuật toán đƣợc cài đặt nhƣ sau:  
int USCLN(int m, int n){  
if (n==0) return m;  
else return USCLN(n, m % n);  
}
Điểm dng ca thuật toán là khi n=0. Khi đó đƣơng nhiên là USCLN ca m và 0 chính là  
m, vì 0 chia hết cho mi s. Khi n khác 0, li gọi đệ qui USCLN(n, m% n) đƣợc thc hin. Chú ý  
rng ta gism >= n trong thtục tính USCLN, do đó, khi gọi đệ qui ta gi USCLN (n, m% n)  
để đảm bo thtcác tham svì n bao giờ cũng lớn hơn phần dƣ của phép m cho n. Sau mi ln  
gọi đệ qui, các tham sca thtc snhdần đi, và sau 1 số hu hn li gi tham snhỏ hơn sẽ  
bằng 0. Đó chính là điểm dng ca thut toán.  
18  
Ví dụ, để tính USCLN ca 108 và 45, ta gi thtục USCLN(108, 45). Khi đó, các thủ tc  
sau slần lƣợt đƣợc gi:  
USCLN(108, 45) 108 chia 45 dư 18, do đó tiếp theo gi  
USCLN(45, 18) 45 chia 18 dư 9, do đó tiếp theo gi  
USCLN(18, 9) 18 chia 9 dư 0, do đó tiếp theo gi  
USCLN(9, 0) tham sth2 = 0, do đó kết qulà tham sthnht, tc là 9.  
Nhƣ vậy, ta tìm đƣợc USCLN ca 108 và 45 là 9 chsau 4 ln gi thtc.  
2.2.3 Các gii thut đệ qui dng chia để tr(divide and conquer)  
Ý tƣởng cơ bản ca các thut toán dạng chia để trị là phân chia bài toán ban đầu thành 2  
hoc nhiu bài toán con có dạng tƣơng tvà lần lƣợt gii quyết tng bài toán con này. Các bài  
toán con này đƣợc coilà dạng đơn giản hơn của bài toán ban đầu, do vy có thsdng các li  
gi đệ qui để gii quyết. Thông thƣờng, các thuật toán chia để trchia bdliệu đầu vào thành 2  
phn riêng rẽ, sau đó gọi 2 thtục đệ qui để vi các bdliệu đầu vào là các phn vừa đƣợc chia.  
Mt ví dụ đin hình ca gii thuật chia để trlà Quicksort, mt gii thut sp xếp nhanh. Ý  
tƣởng cơ bản ca gii thuật này nhƣ sau:  
Gii sta cn sp xếp 1 dãy các stheo chiều tăng dần. Tiến hành chia dãy đó thành 2 nửa  
sao cho các strong nửa đầu đều nhỏ hơn các số trong nửa sau. Sau đó, tiến hành thc hin sp  
xếp trên mi na này. Rõ ràng là sau khi mi nửa đã đƣợc sp, ta tiến hành ghép chúng li thì sẽ  
có toàn bộ dãy đƣợc sp. Chi tiết vgii thut Quicksort sẽ đƣợc trình bày trong chƣơng 7 - Sp  
xếp và tìm kiếm.  
Tiếp theo, chúng ta sxem xét mt bài toán cũng rất điển hình cho lớp bài toán đƣợc gii  
bng gii thuật đệ qui chia để tr.  
Bài toán tháp Hà ni  
Có 3 chiếc cc và mt bn chiếc đĩa. Các đĩa này có kích thƣớc khác nhau và mỗi đĩa đều  
có 1 lỗ ở giữa để có thxuyên chúng vào các cọc. Ban đầu, tt cả các đĩa đu nm trên 1 cc,  
trong đó, đĩa nhỏ hơn bao giờ cùng nằm trên đĩa lớn hơn.  
Cc B  
Cc C  
Cc A  
Hình 2.2 Bài toán tháp Hà ni  
Yêu cu ca bài toán là chuyn bộ n đĩa từ cọc ban đầu A sang cọc đích C (có thsdng  
cc trung gian B), với các điều kin:  
-
Mi ln chuyển 1 đĩa.  
-
Trong mọi trƣờng hợp, đĩa có kích thƣớc nhỏ hơn bao giờ cũng phải nằm trên đĩa có  
kích thƣớc lớn hơn.  
Vi n=1, có ththc hin yêu cu bài toán bng cách chuyn trc tiếp đĩa 1 từ cc A sang  
cc C.  
19  
Vi n=2, có ththc hiện nhƣ sau:  
-
-
Chuyển đĩa nhỏ tcc A sang cc trung gian B.  
Chuyển đĩa lớn tcc A sang cc đích C.  
-
Cui cùng, chuyển đĩa nhỏ tcc trung gian B sang cọc đích C.  
Nhƣ vậy, cả 2 đĩa đã đƣợc chuyn sang cọc đích C và không có tình huống nào đĩa lớn nm  
trên đĩa nhỏ.  
Vi n > 2, gisử ta đã có cách chuyển n-1 đĩa, ta thực hiện nhƣ sau:  
-
-
Ly cc đích C làm cọc trung gian để chuyn n-1 đĩa bên trên sang cọc trung gian B.  
Chuyn cọc dƣới cùng (cc thn) sang cọc đích C.  
-
Ly cọc ban đầu A làm cọc trung gian để chuyn n-1 đĩa từ cc trung gian B sang cc  
đích C.  
Có thminh ha quá trình chuyn này nhƣ sau:  
Trng thái ban đầu:  
Cc C  
Bƣớc 1: Chuyn n-1 đĩa bên trên từ cc A sang cc B, sdng cc C làm cc trung gian.  
Cc A  
Cc B  
Cc C  
Cc B  
Bƣớc 2: Chuyển đĩa dƣới cùng tcc A thng sang cc C.  
Cc A  
Cc C  
Bƣớc 3: Chuyn n-1 đĩa từ cc B sang cc C sdng cc A làm cc trung gian.  
Cc A  
Cc B  
20  
Tải về để xem bản đầy đủ
pdf 145 trang Thùy Anh 04/05/2022 7620
Bạn đang xem 20 trang mẫu của tài liệu "Giáo trình Cấu trúc dữ liệu và giải thuật - Học viện Công nghệ Bưu chính viễn thông", để tải tài liệu gốc về máy hãy click vào nút Download ở trên

File đính kèm:

  • pdfgiao_trinh_cau_truc_du_lieu_va_giai_thuat_hoc_vien_cong_nghe.pdf