1
GIớI THIệU MÔN HọC
Trong ngôn ngữ lậ p trì nh, dữ liệ u bao gồm hai kiể u chí nh là :
- Kiể u dữ liệ u đơn giả n: char, int, long, float, enumeration, subrange.
- Kiể u dữ liệ u có cấ u trúc : struct, array, file (kiể u dữ liệ u có kí ch thước
không đổi)...
Giá o trì nh nà y tậ p trung và o việ c nghiê n cứu cá c kiể u dữ liệ u có cấ u trúc
có kí ch thước không đổi hoặ c thay đổi trong ngôn ngữ lậ p trì nh, mô tả thông qua
ngôn ngữ C. Ngoà i ra còn giới thiệ u cá c giả i thuậ t chung quanh cá c cấ u trúc dữ
liệ u nà y như cá ch tổ chức, thực hiệ n cá c phé p toán tì m kiế m, sắ p thứ tự nội, sắp
thứ tự ngoạ i...
Điề u kiệ n để có thể tì m hiể u rõ rà ng về môn học nà y là học viê n đ biế t
cá c khá i niệ m về kỹ thuậ t lậ p trì nh trê n ngôn ngữ C. Trong phầ n mở đầ u, bà i
giả ng nà y sẽ giới thiệ u cá ch thức phâ n tí ch & thiế t kế một giả i thuậ t trước khi
tì m hiể u về cá c cấ u trúc dữ liệ u cụ thể .
Và o cuối khóa học, sinh viê n có thể :
- Phâ n tí ch độ phức tạ p của cá c chương trì nh có kí ch thước nhỏ và trung
bì nh.
- Nhậ n thức đ ược sự cầ n thiế t của việ c thiế t kế cấ u trúc dữ liệ u.
- Là m quen với cá c khá i niệ m stacks, queues, danh sá ch đặ c, danh sá ch
liê n kế t, câ y nhị phâ n, câ y nhị phâ n tì m kiế m, ....
- Hiể u đ ược nguyê n lý của việ c xâ y dựng một chương trì nh má y tí nh.
- Có thể chọn lựa việ c tổ chức dữ liệ u phù hợp và cá c giả i thuậ t xử lý dữ
liệ u có hiệ u quả trong khi xâ y dựng chương trì nh. Sinh viê n cầ n lưu ý rằ ng, tùy
và o công việ c cụ thể mà ta nê n chọn cấ u trúc dữ liệ u nà o là thí ch hợp theo hướng
tối ưu về thời gian thực hiệ n hay tối ưu về bộ nhớ.
2
Chươn g I
PHÂN Tí CH & THIếT Kế
GIảI THUậT
I. mở đầu
Hầ u hế t cá c bà i toá n đề u có nhiề u giả i thuậ t khá c nhau để giả i quyế t chúng.
Vậ y là m thế nà o chọn đ ược một giả i thuậ t tốt nhấ t ?
Việ c chọn lựa phụ thuộc và o nhiề u yế u tố như : Độ phức tạ p tí nh toá n của
giả i thuậ t, chiế m dung lượng bộ nhớ, tầ n suấ t sử dụng, tí nh đơn giả n, tốc độ thực
hiệ n...
Thông thường mục tiê u chọn lựa là :
1. Giả i thuậ t rõ rà ng, dễ hiể u, dễ m hóa và hiệ u chỉ nh.
2. Giả i thuậ t sử dụng có hiệ u quả tà i nguyê n của má y tí nh và đặ c biệ t
chạ y cà ng nhanh cà ng tốt.
Do đó khi viế t chương trì nh để chạ y một lầ n hoặ c í t chạ y thì mục tiê u 1 là
quan trọng hơn cả .
Ngược lạ i khi viế t chương trì nh để chạ y nhiề u lầ n thì phí tổn chạ y chương
trì nh có thể vượt quá phí tổn lậ p chương trì nh, nhấ t là khi phả i nhậ p nhiề u số
liệ u. Nói chung, người lậ p trì nh phả i biế t chọn lựa, viế t, đá nh giá cá c giả i thuậ t
để có được giả i thuậ t tối ưu cho bà i toá n của mì nh.
II. đánh giá thời gian chạy của chươn g t r ì n h
Thời gian chạ y của chưong trì nh phụ thuộc và o :
1. Input cho chương trì nh
2. Chấ t lượng m sinh ra của chương trì nh dị ch.
3. Trạ ng thá i và tốc độ của cá c lệ nh chạ y trê n má y.
4. Độ phức tạ p thời gian của giả i thuậ t.
Điề u 1 là chức nă ng nhậ p. Kí ch thước của input (ví dụ là n) và ta thường ký
hiệ u T(n) là đạ i lượng thời gian cầ n thiế t để giả i bà i toá n kí ch thước n.
Điề u 2, 3 thường đá nh giá khó khă n vì phụ thuộc và o phầ n mề m chương
trì nh dị ch và phầ n cứng của má y.
Điều 4 là điều mà người lậ p trì nh cầ n khả o sá t để là m tă ng tốc độ của
chương trì nh.
3
III. ký hiệu o(n) và
(n) :
Ta đá nh giá tỷ lệ phá t triể n cá c hà m T(n) qua ký hiệ u O(n).
Ta nói thời gian chạ y T(n) của chương trì nh là O(n
2
) có nghĩ a là :
c > 0 và n
0
sao cho n n
0
ta có T(n) c.n
2
.
Ví dụ
: Giả sử T(0) = 1, T(1) = 4, v v...
Tổng quá t T(n) = (n +1)
2
thì ta nói T(n) là O(n
2
) vì có thể đặ t c
1
= 4, n
0
= 1,
thì khi n 1 ta có (n +1)
2
4n
2
.
Nhưng không thể lấ y n
0
= 0 vì T(0) = 1 không nhỏ hơn c.0
2
= 0,c; giả thiế t
rằ ng n 0 và T(n) 0.
Ta nói T(n) là O(f(n)) nế u const c và n
0
sao cho T(n) c.f(n), n n
0
.
Chương trì nh chạ y với thời gian O(f(n)) ta nói nó phá t triể n tỷ lệ với f(n).
Khi nói T(n) là O(f(n)) thì f(n) là chặ n trê n của T(n).
Để nó i c h ặ n d ưới của T(n) ta dùng ký hiệ u .
Ta nói T(n) là (g(n)) nế u const c, n
0
sao cho T(n) c.g(n), n n
0
.
Ví dụ
: Để kiể m tra T(n) = n
3
+ 2n
2
là (n
3
) ta đặ t c = 1 thì T(n) c.n
3
, n
= 0, 1,... (n
o
= 0).
* Sự trá i ngược của tỷ lệ phá t triể n
:
Ta giả sử cá c chương trì nh có thể đá nh giá bằ ng cá ch so sá nh cá c hà m thời
gian của chúng với cá c hằ ng tỷ lệ không đá ng kể . Khi đó ta nói chương trì nh có
thời gian chạ y O(n
2
). Nế u chương trì nh 1 chạ y mấ t 100.n
2
thời gian (mili giâ y)
thì chương trì nh 2 chạ y mấ t 5.n
3
thời gian, thì ta có tỷ số thời gian của 2 chương
trì nh là 5.n
3
/100.n
2
= n/20, nghĩ a là khi n = 20 thì thời gian chạ y 2 chương trì nh
là bằ ng nhau, khi n < 20 thì chương trì nh 2 chạ y nhanh hơn chương trì nh 1. Do
đó khi n > 20 thì nê n dùng chương trì nh 1.
Ví dụ
: Có 4 chương trì nh có 4 độ phức tạ p khá c nhau đ ược biể u diễ n trong
bả ng dưới đây.
Thời gian
chạ y T(n)
Kí ch thước bà i toá n
tối đa cho 10
3
s
Kí ch thước bà i toá n
tối đa cho 10
4
s
Tỷ lệ tă ng về
kí ch thước
100.n 10 100 10.0 lầ n
5.n
2
14 45 3.2 lầ n
n
3/2
12 27 2.3 lầ n
2
n
10 13 1.3 lầ n
Giả sử trong 10
3
s thì 4 chương trì nh giả i cá c bà i toá n có kí ch thước tối đa
trong cột 2. Nế u có má y tốt tốc độ tă ng lê n 10 lầ n thì kí ch thước tối đa tương ứng
4
của 4 chương trì nh trì nh bà y ở cột 3. Tỉ lệ hai cột 1,2 ghi ở cột 4. Như vậ y nế u
đầu tư về tốc độ 10 lầ n thì chỉ thu lợi có 30% về kí ch thước bà i toá n nế u dùng
chương trì nh có độ phức tạ p O(2
n
).
IV. cách tí nh thời gian chạy chươn g t r ì n h
:
1. Qui tắc tổng:
Giả sử T
1
(n) và T
2
(n) là thời gian chạ y chương trì nh P
1
và P
2
tương ứng đ ược
đá nh giá là O(f(n)) và O(g(n)). Khi đó T
1
(n) + T
2
(n) sẽ là O(max(f(n),g(n)))
(chạ y xong chương trì nh P
1
thì chạ y P
2
).
Chứng minh
:
Theo đị nh nghĩ a O(f(n)) và O(g(n)) thì c
1
, n
1
, c
2
, n
2
sao cho
T
1
(n) c
1
.f(n) n n
1
; T
2
(n) c
2
.g(n) n n
2
.
Đặ t n
0
= max(n
1
, n
2
)
Nế u n n
o
thì T
1
(n) + T
2
(n) (c
1
+ c
2
).max(f(n),g(n)).
2. Qui tắc tí ch:
T
1
(n). T
2
(n) là O(f(n).g(n)).
Chứng minh
: tương tự như tổng.
Ví dụ
: Có 3 chương trì nh có thời gian chạ y tương ứng là O(n
2
), O(n
3
),
O(n.logn). Thế thì thời gian chạ y 3 chương trì nh đồng thời là O(max(n
2
, n
3
,
nlogn)) sẽ là O(n
3
).
Nói chung thời gian chạ y một d y cố đị nh cá c bước là thời gian chạ y lớn
nhấ t của một bước nào đó trong d y. Cũng có trường hợp có 2 hay nhiề u bước có
thời gian chạ y không tương xứng (không lớn hơn mà cũng không nhỏ hơn). Khi
đó qui tắ c tí nh tổng phả i đ ược tí nh trong từng trường hợp.
n
4
nế u n chẵ n
Ví dụ : f(n) =
{
n
2
nế u n lẻ
g(n) = n
2
nế u n chẵ n
{
n
3
nế u n lẽ
Thời gian chạ y là O(max(f(n),g(n))) là n
4
nế u n chẵ n và n
3
nế u n lẻ .
Nế u g(n) f(n), n n
o
, n
o
là const nà o đó thì O(f(n)+g(n)) sẽ là O(f(n)).
Ví dụ
: O(n
2
+ n) = O(n
2
)
Trước khi đ ưa ra qui tắ c chung để phâ n tí ch thời gian chạ y của chương trì nh
thì ta xé t ví dụ đơn giả n sau.
5
Ví dụ : Xé t chương trì nh Bubble dùng sắ p d y số nguyê n theo chiề u tă ng.
Procedure Bubble (var A: array [1..n] of integer);
Var i, j, temp : integer ;
Begin
1 For i := 2 to n do
2 For j := n downto i do
3 If A[j-1] > A[j] then
Begin
4 temp := A[j-1] ;
5 A[j-1] := A[j] ;
6 A[j] := temp ;
End ;
End ;
Phâ n tí ch
:
- N là số phầ n tử - kí ch thước của bà i toá n. Mỗi lệ nh gá n từ dòng 4 - > dòng
6 mấ t 3 đơn vị thời gian, theo qui tắ c tí nh tổng sẽ là O(max(1,1,1) = O(1).
- Vòng If và For lồng nhau, ta phả i xé t từ trong ra ngoà i. Đối với điề u kiệ n
sau If phả i kiể m tra O(1) thời gian. Ta không chắ c thâ n lệ nh If từ 4 - 6 có thực
hiệ n hay không. Vì xé t trong trường hợp xấ u nhấ t nê n ta giả thuyế t là cá c lệ nh từ
4 - 6 đề u có thực hiệ n. Vậ y nhóm If từ cá c lệ nh 3 -6 là m mấ t O(1) thời gian.
- Ta xé t vòng lặ p ngoà i từ 2 - 6. Nguyê n tắ c chung của vòng lặ p: thời gian
vòng lặ p là tổng thời gian mỗi lầ n lặ p trong thâ n vòng lậ p. í t nhấ t là O(1) cho
mỗi lầ n lặ p khi chỉ số tă ng. Số lầ n lặ p từ 2 - 6 là n - i +1
Vậ y theo qui tắ c tí ch : O((n - i +1), 1) là O(n -i +1).
- Ta xé t vòng ngoà i cùng chứa cá c lệ nh của chương trì nh. Lệ nh 1 là m n-1
lầ n, tốn n-1 đơn vị thời gian. Vậ y tổng thời gian chạ y của chương trì nh bị chặ n
dưới bởi 1 thời gian cố đị nh là :
=
=+
n
2i
2/)1n(*n)1in(
tức là O(n
2
)
Tuy nhiê n không có qui tắ c đầ y đủ để phâ n tí ch chương trì nh.
Nói chung thời gian chạ y của 1 lệ nh hoặ c 1 nhóm lệ nh có thể là 1 hà m của
kí ch thước cá c input hoặ c 1 hay nhiề u biế n. Nhưng chỉ có n - kí ch thước của bà i
toá n là thông số cho phé p đối với thời gian chạ y của chương trì nh.
6
3. Qui tắc tí nh thời gian chạy
a) Thời gian chạ y của mỗi lệ nh gá n, read, write có giả thiế t là O(1).
b) Thời gian chạ y của 1 d y lệ nh xá c đị nh theo qui tắ c tổng; nghĩ a là
thời gian chạ y của d y là thời gian lớn nhấ t của 1 lệ nh nà o đó trong d y lệ nh.
c) Thời gian chạ y lệ nh If là thời gian thực hiệ n lệ nh điề u kiệ n cộng với
thời gian kiể m tra điề u kiệ n.
Thời gian thực hiệ n lệ nh If có cấ u trúc If then eles là thời gian kiể m
tra điề u kiệ n cộng với thời gian lớn nhấ t của 1 trong 2 lệ nh rẽ nhá nh true và
false.
d) Thời gian thực hiệ n vòng lặ p là tổng thời gian thực hiệ n thâ n vòng lặ p
và thời gian kiể m tra kế t thúc vòng lặ p.
e) Gọi thủ tục:Nế u chương trì nh có cá c thủ tục và không có thủ tục nà o
là đệ qui thì ta có thể tí nh thời gian chạ y cùng một lúc, bắ t đầ u từ cá c thủ tục
không gọi đế n cá c thủ tục khá c. Tấ t nhiê n phả i có í t nhấ t 1 thủ tục như vậ y trong
trường hợp nà y, nế u không thì phả i có thủ tục đệ qui. Sau đó ta có thể đá nh giá
thời gian chạ y của cá c thủ tục có gọi, đế n cá c thủ tục không chứa lời gọi đ đ ược
đá nh giá . Cứ như thế ta lạ i đá nh giá thời gian chạ y của cá c thủ tục có lời gọi đế n
cá c thủ tục đ đá nh giá , nghĩ a là mỗi thủ tục đ ược đá nh giá sau khi đá nh giá hế t
cá c thủ tục mà đ ược nó gọi.
Nế u có thủ tục đệ qui thì không thể tì m đ ược thứ tự của tấ t cả cá c thủ tục
sao cho mỗi thủ tục chỉ gọi đế n cá c thủ tục đ đá nh giá . Khi đó ta phả i lậ p 1 liê n
hệ giữa mỗi thủ tục đệ qui với 1 hà m thời gian chưa biế t T(n) trong đó n là kí ch
thước của đối số của thủ tục. Lúc đó ta có thể nhậ n đ ược sự truy hồi đối với T(n),
nghĩ a là 1 phương trì nh diễ n tả T(n) qua cá c T(k) với cá c giá trị k khá c nhau.
Ví dụ
: Xé t chương trì nh đệ qui tí nh n giai thừa (n!), trong đó n là kí ch
thước của hà m nê u trê n.
Function Fact (n:integer) : LongInt ;
Begin
1 If n <= 1 then
2 Fact := 1
Else
3 Fact := n*fact (n-1)
End ;
Phâ n tí ch
:
Ta ký hiệ u T(n) là thời gian chạ y để tí nh hà m Fact(n).
Thời gian chạ y đối với cá c dòng 1, 2 là O(1) và đối với dòng 3 là O(1) +
T(n-1). Vậ y với cá c hằ ng c, d nà o đó ta có phương trì nh:
7
c + T(n-1) nế u n > 1
T(n) =
d nế u n 1
Giả i phương trì nh
:
Giả sử n > 2, ta có thể khai triể n T(n-1) trong công thức :
T(n) = 2.c + T(n-2) nế u n > 2
Sau đó ta lạ i thay T(n-2) = c + T(n-3) ta đ ược.
T(n) = 3.c + T(n-3) nế u n > 3
.....
T(n) = i.c + T(n-i) nế u n > i
Cuối cùng ta thay i = n - 1, ta đ ược
T(n) = c(n-1) + T(1) = c(n-1) + d
Kế t luậ n T(n) là O(n).
V. sự phân lớp các thuật toán
:
Như đ đ ược chú ý ở trê n, hầ u hế t cá c thuậ t toá n đề u có một tham số chí nh là
N, Thông thường đó là số lượng cá c phầ n tử dữ liệ u đ ược xử lý mà ả nh hưởng rấ t
nhiề u tới thời gian chạ y. Tham số N có thể là bậ c của 1 đa thức, kí ch thước của 1
tậ p tin đ ược sắ p xế p hay tì m kiế m, số nút trong 1 đồ thị ...Hầ u hế t tấ t cả thuậ t toá n
trong bà i giả ng nà y có thời gian chạ y tiệ m cậ n tới 1 trong cá c hà m sau :
1. Hầ u hế t tấ t cả cá c chỉ thị của các chương trì nh đề u đ ược thực hiệ n một
lầ n hay nhiề u nhấ t chỉ một và i lầ n. Nế u tấ t cả cá c chỉ thị của cùng 1 chương trì nh
có tí nh chấ t nà y thì chúng ta sẽ nói rằ ng thời gian chạ y của nó là hằ ng số. Điề u
nà y hiể n nhiê n là mục tiê u phấ n đấ u để đạ t đ ược trong việ c thiế t kế thuậ t toá n.
2. logN
Khi thời gian chạ y của chương trì nh là logarit, tức là thời gian chạ y
chương trì nh tiế n chậ m khi N lớn dầ n. Thời gian chạ y loạ i nà y xuấ t hiệ n trong
cá c chương trì nh mà giả i 1 bà i toá n lớn bằ ng cá ch chuyể n nó thà nh bà i toá n nhỏ
hơn, bằ ng cá ch cắ t bỏ kí ch thước bớt 1 hằ ng số nà o đó. Với mục đí ch của chúng
ta, thời gian chạ y có đ ược xem như nhỏ hơn 1 hằ ng số "lớn". Cơ số của logarit
là m thay đổi hằ ng số đó nhưng không nhiề u: Khi n là 1000 thì logN là 3 nế u cơ
số là 10; là 10 nế u cơ số là 2 ; khi N là 1000000, logN đ ược nhân gấp đôi. Bất cứ
khi nà o N được nhâ n gấ p đôi, logN đ ược tă ng lê n thê m một hằ ng số, nhưng logN
không đ ược nhâ n gấ p đôi tới khi N tă ng tới N
2
.
3. N
Khi thời gian chạ y của chương trì nh là tuyế n tí nh, nói chung đâ y là
trường hợp mà một số lượng nhỏ cá c xử lý đ ược là m cho mỗi phầ n tử dữ liệ u nhậ p
.
{
8
Khi N là 1.000.000 thì thời gian chạ y cũng cỡ như vậ y.
Khi N đ ược nhâ n gấ p đôi thì thời gian chạ y cũng đ ược nhâ n gấ p đôi.
Đâ y là tì nh huống tối ưu cho 1 thuậ t toá n mà phả i xử lý N dữ liệ u nhậ p (hay sản
sinh ra N dữ liệ u xuấ t).
4. NlogN
Đâ y là thời gian chạ y tă ng dầ n lê n cho cá c thuậ t toá n mà giả i 1 bà i toá n
bằ ng cá ch tá ch nó thà nh cá c bà i toá n con nhỏ hơn, kế đế n giả i quyế t chúng 1
cá ch độc lậ p và sau đó tổ hợp cá c lời giả i. Bởi vì thiế u 1 tí nh từ tốt hơn (có lẽ là
"tuyế n tí nh logarit" ?), chúng ta nói rằ ng thời gian chạ y của thuậ t toán như thế là
"NlogN".
Khi N là 1000000, NlogN có lẽ khoả ng 6 triệ u.
Khi N đ ược nhâ n gấ p đôi, thời gian chạ y bị nhâ n lê n nhiề u hơn gấ p đôi
(nhưng không nhiề u lắ m).
5. N
2
Khi thời gian chạ y của 1 thuậ t toá n là bậc hai, trường hợp nà y chỉ có ý
nghĩ a thực tế cho cá c bà i toá n tương đối nhỏ. Thời gian bì nh phương thường tă ng
lê n trong cá c thuậ t toá n mà xử lý tấ t cả cá c cặp phầ n tử dữ liệ u (có thể là 2 vòng
lặ p lồng nhau).
Khi N là 1000 thì thời gian chạ y là 1000000.
Khi N đ ược nhâ n đôi thì thời gian chạ y tă ng lê n gấ p 4 lầ n.
6. N
3
Tương tự, một thuậ t toá n mà xử lý một bộ 3 của cá c phầ n tử dữ liệ u (có
lẽ 3 vòng lặ p lồng nhau) có thời gian chạ y bậ c 3 và cũng chỉ có ý nghĩ a thực tế
trong cá c bà i toá n nhỏ.
Khi N là 100 thì thời gian chạ y là 1.000.000.
Khi N đ ược nhâ n đôi thì thời gian chạ y tă ng lê n gấ p 8 lầ n.
7. 2
n
Một số í t thuậ t toá n có thời gian chạ y lũy thừa lạ i thí ch hợp trong 1 số
trường hợp thực tế , mặ c dù cá c thuậ t toá n như thế là "sự é p buộc thô bạ o" để giả i
bà i toá n.
Khi N là 20 thì thời gian chạ y xấ p xỉ là 1.000.000
Khi N là gấ p 2 thì thời gian chạ y đ ược nâ ng lê n lũy thừa 2.
Thời gian chạ y của 1 chương trì nh cụ thể đôi khi là một hằ ng số nhâ n
với cá c số hạ ng nói trê n cộng thê m một số hạ ng nhỏ hơn. Cá c giá trị của hằng số
và cá c số hạ ng phụ thuộc và o cá c kế t quả của sự phâ n tí ch và cá c chi tiế t cà i đặ t.
Hệ số của hằ ng số liê n quan tới số chỉ thị bê n trong vòng lặ p : ở 1 tầ ng tùy ý của
9
thiế t kế thuậ t toá n thì phả i cẩ n thậ n giới hạ n số chỉ thị như thế . Với N lớn thì cá c
hằ ng số đóng vai trò chủ chốt, với N nhỏ thì cá c số hạ ng cùng đóng góp và o và
sự so sá nh thuậ t toá n sẽ khó khă n hơn. Ngoà i những hà m vừa nói trê n cũng còn
có 1 số hà m khá c, ví dụ như 1 thuậ t toá n với N
2
phầ n tử dữ liệ u nhậ p mà có thời
gian chạ y là bậ c 3 theo N thì sẽ đ ược phâ n lớp như 1 thuậ t toá n N
3/2
. Một số
thuậ t toá n có 2 giai đoạ n phâ n tá ch thà nh cá c bà i toá n con và có thời gian chạ y
xấ p xỉ với Nlog
2
N.
VI. các công thức truy hồi cơ sở
:
Phầ n lớn cá c thuậ t toá n đề u dựa trê n việ c phâ n r đệ qui một bà i toá n lớn
thà nh cá c bà i toá n nhỏ hơn, rồi dùng cá c lời giả i của cá c bà i toá n nhỏ để giả i bà i
toá n ban đầ u. Thời gian chạ y của cá c thuậ t toá n như thế đ ược xá c đị nh bởi kí ch
thướ c và số lượng cá c bà i toá n con và giá phả i trả của sự phâ n r . Trong phầ n
nà y ta quan sá t cá c phương phá p cơ sở để phâ n tí ch cá c thuậ t toá n như thế và
trì nh bà y một và i công thức chuẩ n thường đ ược á p dụng trong việ c phâ n tí ch
nhiề u thuậ t toá n.
Tí nh chấ t rấ t tự nhiê n của 1 chương trì nh đệ qui là thời gian chạ y cho dữ
liệ u nhậ p có kí ch thước N sẽ phụ thuộc và o thời gian chạ y cho cá c dữ liệ u nhậ p
có kí ch thước nhỏ hơn : điề u nà y đ ược diễ n dị ch thà nh 1 công thức toá n học gọi
là quan hệ truy hồi. Cá c công thức như thế mô tả chí nh xá c tí nh nă ng của cá c
thuậ t toá n tương ứng, do đó để có đ ược thời gian chạ y chúng ta phả i giả i cá c bà i
toá n truy hồi. Bâ y giờ chúng ta chú ý và o cá c công thức chứ không phả i cá c
thuậ t toá n.
Công thức 1
:
Công thức nà y thường dùng cho cá c chương trì nh đệ qui mà có vòng lặ p
duyệ t qua dữ liệ u nhậ p để bỏ bớt 1 phầ n tử.
C
n
= C
n-1
+ n, với n >= 2 và C
1
= 1
Chứng minh
:
C
n
khoả ng n
2
/2. Để giả i 1 công thức truy hồi như trê n, chúng ta lầ n lượt áp
dụng chí nh công thức đó như sau :
C
n
= C
n-1
+ n
= C
n-2
+ (n-1) + n
= ...
= C
1
+ 2 + ... + (n-2) + (n-1) + n
= 1 + 2 + ... + n
= n(n+1)/2
10
Công thức 2 :
Công thức nà y dùng cho chương trì nh đệ qui mà chia dữ liệ u nhậ p thà nh 2
phầ n trong mỗi bước.
C
n
= C
n/2
+ 1, với n >= 2 và C
1
= 0
Chứng minh
:
C
n
khoả ng logn. Phương trì nh nà y vô nghĩ a trừ phi n chẵ n hay chúng ta giả
sử rằ ng n/2 là phé p chia nguyê n : bâ y giờ chúng ta giả sử rằ ng n = 2
m
để cho
công thức luôn luôn có nghĩ a. Chúng ta viế t như sau :
1
22
1
+=
CC
mm
2
2
2
+=
C
m
3
2
3
+=
C
m
= ......
m
C
mm
+=
2
nm log
==
Công thức chí nh xá c cho n tổng quá t thì phụ thuộc và o biể u diễ n nhị phâ n
của n, nói chung C
n
khoả ng logn với mọi n.
Công thức 3
:
Công thức nà y dùng cho chương trì nh đệ qui mà chia đôi dữ liệ u nhậ p
nhưng có thể kiể m tra mỗi phầ n tử của dữ liệ u nhậ p.
C
n
= C
n/2
+ n, với n >= 2 và C
1
= 0
Chứng minh
:
C
n
khoả ng 2n. Tương tự trê n, công thức nà y chí nh là tổng n + n/2 + n/4 + ...
(dĩ nhiê n điề u nà y chỉ chí nh xá c khi n là lũy thừa của 2).
Nế u d y là vô hạ n, thì đâ y là 1 chuỗi hì nh học đơn giả n mà đ ược ước lượng
chí nh xá c là 2n. Trong trường hợp tổng quá t lời giả i chí nh xá c phụ thuộc và o
biể u diễ n nhị phâ n của n.
Công thức 4
:
Công thức nà y dùng cho chương trì nh đệ qui mà duyệ t tuyế n tí nh xuyê n
qua dữ liệ u nhậ p, trước, trong, hay sau khi dữ liệ u nhậ p đ ược chia đôi.
C
n
= 2C
n/2
+ n, với n >= 2 và C
1
= 0
Chứng minh
:
C
n
khoả ng nlogn. Công thức nà y á p dụng cho nhiề u thuậ t toá n theo phương
phá p "chia đ ể trị ".
11
2
22
1
m
mm
CC
+=
1
22
1
1
22
+=
m
m
m
m
CC
11
2
2
2
2
++=
m
m
C
m
C
mm
mm
+=
2
2
mm
C
=+=
2
0
nn
mC
m
n
log
2
==
Lời giả i cho công thức nà y rấ t giống như trong công thức 2, nhưng phả i
chia 2 vế của công thức cho 2
n
trong bước thứ hai.
Công thức 5
:
Công thức nà y dùng cho chương trì nh đệ qui mà tách dữ liệ u thà nh 2 phầ n.
C
n
= 2C
n/2
+ 1, với n >= 2 và C
1
= 0
Chứng minh
:
C
n
khoả ng 2n. Chứng minh giống như công thức 4.
Cá c biế n dạ ng của những công thức nà y chẳ ng hạ n như điề u kiệ n khá c nhau
hay cá c số hạ ng thê m và o khá c nhau một í t, có thể ước lượng bằ ng cá ch dùng
cũng một kỹ thuậ t như trê n. Mặ c dù vậ y, chúng ta cũng nê n chú ý 1 quan hệ truy
hồi dường như tương tự với một quan hệ đ biế t thì đôi khi lạ i khó giả i hơn rấ t
nhiề u.
VII. giải phương trì nh truy hồi
:
Để giả i phương trì nh truy hồi có nhiề u cá ch giả i khá c nhau, ở đâ y chúng tôi
trì nh bà y cá ch giả i phương trì nh truy hồi bằ ng cá ch truy về phương trì nh đặ c
trưng. Chúng tôi dùng cá ch giả i nà y để viế t chương trì nh giả i tự động phương
trì nh truy hồi.
a) Ta xé t phương trì nh truy hồi thuầ n nhấ t tuyế n tí nh với cá c hệ số không
đổi sau đây :
a
0
t
n
+ a
1
t
n-1
+ ... + a
k
t
n-k
= 0 (VII.1)
trong đó t
i
(i=n, n-1,..., n-k) là cá c ẩ n số cầ n tì m.
Tuyế n tí nh vì cá c t
i
chỉ có bậ c nhấ t, thuầ n nhấ t vì vế phả i bằ ng không và
cá c hệ số a
0
, a
1
,..., a
k
là không đổi vì không phụ thuộc và o n.
12
Sau khi giả thiế t t
n
= x
n
ta đ ưa (VII.1) về dạ ng:
a
0
x
n
+ a
1
x
n-1
+...+ a
k
x
n-k
= 0
hay x
n-k
(a
0
x
k
+ a
1
x
k-1
+...+ a
k
) = 0
Rõ rà ng x = 0 là nghiệ m hiể n nhiê n, nhưng ta quan tâ m nghiệ m phương
trì nh a
0
x
k
+ a
1
x
k-1
+...+ a
k
= 0 (VII.2) và đâ y chí nh là phương trì nh đặ c trưng bậ c
k của phương trì nh truy hồi (VII.1)
Giả sử r
1
, r
2
,..., r
k
là k nghiệ m của phương trì nh (VII.2) và chúng khá c nhau
(có thể phức). Dễ dà ng kiể m tra:
r
ct
n
i
k
i
in
=
=
1
Với c
1
, c
2
,..., c
k
là cá c hằ ng xá c đị nh từ k điề u kiệ n ban đầ u.
Ví dụ 1
:
Xé t phương trì nh truy hồi:
0
43
21
=
ttt
nnn
Điề u kiệ n ban đầ u : t
0
= 1 ; t
1
=1
Phương trì nh đặ c trưng tương ứng của nó là :
x
2
- 3x - 4 = 0
có nghiệ m bằ ng -1 và 4. Vậ y nghiệ m tổng quá t là :
)4()1(
21
nn
n
cct
+=
Theo điề u kiệ n ban đầ u (khi n =0 và n = 1) ta có :
c
1
+ c
2
= 1 = t
0
- c
1
+ 4c
2
=1
Vậ y c
1
= 3/5, c
2
= 2/5. Ta được t
n
= - [4
n
- (-1)
n
] /5
Ví dụ 2
: (phương trì nh Fibonacci)
t
n
= t
n-1
+ t
n-2
n 2
Điều kiện : t
0
= 0, t
1
= 1
Viế t lạ i phương trì nh trê n :
t
n
- t
n-1
- t
n -2
= 0
Phương trì nh đặ c trưng tương ứng :
x
2
- x -1 = 0
13
Nghiệ m :
2/)51(
r
1
+=
,
2/)51(
r
2
=
Nghiệ m tổng quá t : t
n
= c
1
r
1
n
+ c
2
r
2
n
Từ điề u kiệ n ban đầ u :
c
1
+ c
2
= 0 (n = 0)
r
1
c
1
+ r
2
c
2
= 1 (n =1)
Ta có
5/1
c
1
=
,
5/1
c
2
=
Vậ y: t
n
=
5/)nn(
rr
21
Giả sử cá c nghiệ m phương trì nh đặ c trưng là không phâ n biệ t, P(x) là 1 đa
thức.
P(x) = a
0
x
k
+ a
1
x
k-1
+ ... + a
k
và r là nghiệ m ké p.
Với mỗi r > k, ta xé t đa thức bậ c n đ ược xá c đị nh như sau :
h(x) = x [x
n-k
P(x)] = a
0
nx
n
+ a
1
(n-1)x
n-1
+ ... + a
k
(n-k)x
n-k
Đặ t q(x) là đa thức thỏa điề u kiệ n
P(x) = (x-r)
2
q(x)
Ta có :
h(x) = x[(x-r)
2
x
n-k
q(x)] = x[2(x-r)x
n-k
q(x) + (x-r)
2
[x
n-k
q(x)]]
Rõ rà ng h(r) = 0, do đó
a
0
nr
n
+ a
1
(n-1)x
n-1
+ ... + a
k
(n-k) r
n-k
= 0
Nghĩ a là t
n
= nr
n
cũng là nghiệ m của (5.13). Tổng quá t hơn, nế u nghiệ m r
trùng nhau m lầ n (r bội m) thì
t
n
= r
n
, t
n
= nr
n
, t
n
= n
2
r
n
,...., t
n
= n
m-1
r
n
cũng là cá c nghiệ m của (5.13). Nghiệ m tổng quá t (nghiệ m chung) là tổ hợp
tuyế n tí nh của cá c nghiệ m riê ng nà y và nghiệ m riê ng khá c của phương trì nh đặ c
trưng. K hằ ng đ ược xá c đị nh từ cá c điề u kiệ n ban đầ u.
Ví dụ 3
: Xé t phương trì nh
t
n
= 5t
n-1
- 8t
n-2
+ 4t
n-3
n 3
với cá c điề u kiệ n t
0
= 0, t
1
= 1, t
2
= 2
Ta viế t lạ i phương trì nh:
t
n
- 5t
n-1
+ 8t
n-2
- 4t
n-3
= 0
và phương trì nh đặ c trưng tương ứng là :
x
3
- 5x
2
+ 8x - 4 = 0
hay (x-1) (x-2)
2
= 0
14
Ta có cá c nghiệ m 1 (có bội 1), 2 (có bội 2). Vậ y nghiệ m tổng quá t là :
t
n
= c
1
1
n
+ c
2
2
n
+ c
3
n2
n
Cá c điề u kiệ n ban đầ u cho trước là :
c
1
+ c
2
= 0 khi n = 0
c
1
+ 2c
2
+ 2c
3
= 1 khi n = 1
c
1
+ 4c
2
+ 8c
3
= 2 khi n = 2
Từ đâ y ta tì m ra c
1
= -2, c
2
= 2, c
3
= -1/2. Vậ y t
n
= 2
n+1
- n2
n-1
- 2
b) Phương trì nh truy hồi không thuầ n nhấ t:
Ta xé t phư ơng trì nh có dạ ng sau :
a
0
t
n
+ a
1
t
n-1
+ ... + a
k
t
n-k
= b
n
P(n) (VII.3)
Trong đó vế trá i như trong (VII.1), vế phả i là b
n
P(n) với b là hằ ng và P(n) là
đa thức.
Ví dụ 4
:
t
n
- 2t
n-1
= 3
n
thì b = 3 và P(n) = 1 là đa thức bậ c 0.
Bằ ng phé p biế n đổi đơn giả n ta có thể chuyể n ví dụ này về dạ ng (VII.1) là
phương trì nh truy hồi thuầ n nhấ t. Trước hế t ta nhâ n 2 vế cho 3 ta đ ược :
3t
n
- 6t
n-1
= 3
n+1
(1)
Sau đó ta thay n ra n + 1 trong phương trì nh ban đầ u:
t
n+1
- 2t
n
= 3
n+1
(2)
Cuối cùng, lấ y (2) - (1) , ta thu đ ược (có cùng vế phả i 3
n+1
), ta đ ược:
t
n+1
- 5t
n
+ 6t
n-1
= 0
Đế n đâ y ta có thể giả i phương trì nh đ trì nh bà y ở mục a.
Phương trì nh đặ c trưng của nó là :
x
2
- 5x + 6 = 0
hay (x-2) (x-3) = 0
Trực giá c cho ta thấ y rằ ng thà nh phầ n (x-2) tương ứng với vế trá i
phương trì nh ban đầ u; còn (x-3) là biể u hiệ n kế t quả của việ c biến đổi và trừ vế
phả i.
Ví dụ 5
:
t
n
- 2t
n-1
= (n+5)3
n
15
Sự biến đổi có phức tạp như sau :
-
Nhâ n 2 vế cho 9
-
Thay n bởi n+2
-
Thay n bởi n+1,sau đó nhâ n cho -6
-
Ta đ ược kế t quả :
9t
n
- 18t
n-1
= (n + 5) 3
n+2
t
n+2
- 2t
n+1
= (n + 7) 3
n+2
-6t
n+1
+ 12t
n
= -6(n + 6) 3
n+1
Cộng 3 phương trì nh lạ i ta đ ược :
t
n+2
- 8t
n+1
+ 21t
n
- 18t
n-1
= 0
Phương trì nh đặ c trưng.
x
2
- 8x
2
+ 21x - 18 = 0 hay (x-2) (x-3)
2
= 0
Ta lạ i thấ y (x-2) tương ứng vế trá i phương trì nh ban đầ u và (x-3)
2
là kế t quả
của sự biế n đổi.
Như vậ y chúng ta có thể nói rằ ng để giả i phương trì nh truy hồi không thuầ n
nhấ t có dạ ng (VII.3) ta chỉ cầ n giả i phương trì nh đặ c trưng sau.
(a
0
x
k
+ a
1
x
k-1
+ ... + a
k
) (x-b)
d+1
= 0 (VII.4)
Ví dụ 6
: (bà i toá n thá p Hà Nội)
Phương trì nh truy hồi cho bà i toá n chuyể n n đĩ a nà y có dạ ng:
1 nế u n = 1
t
n
=
{
2t
n-1
+ 1 nế u n > 1
hay t
n
= 2t
n-1
+ 1, n > 1 với t
0
= 0
Ta viế t lạ i phương trì nh :
t
n
- 2t
n-1
= 1
Và thấ y nó có dạ ng (VII.3) với b = 1, P(n) = 1 bậ c 0
Phương trì nh đặ c trưng là (x-2) (x-1) = 0
Vậ y : t
n
=c
1
1
n
+ c
2
2
n
. Từ t
0
= 0 để tì m t
1
ta viế t :
t
1
= 2t
o
+ 1 = 1
Vậ y c
1
+ c
2
= 0, n = 0
c
1
+ 2c
2
= 1, n = 1
Suy ra c
1
= -1, c
2
= 1. Vậ y t
n
= 2
n
-1
Ta nhậ n thấ y từ t
n
= c
1
1
n
+ c
2
2
n
cũng có thể kế t luậ n t
n
có O(2
n
).
16
Ví dụ 7 :
t
n
= 2t
n-1
+ n
hay t
n
- 2t
n-1
= n
ở đâ y b = 1, P(n) = n bậ c 1
Ta có phương trì nh đặ c trưng:
(x-2) (x-1)
2
= 0
Vậ y nghiệ m tổng quá t là :
t
n
= c
1
2
n
+ c
2
1
n
+ c
3
n1
n
Nế u t
n
> 0 với mỗi n thì ta có thể kế t luậ n T(n)= O(2n),
Bâ y giờ ta xé t phương trì nh truy hồi không thuầ n nhấ t tổng quá t hơn.
a
o
t
n
+a
1
t
n-1
+ ... + a
k
t
n-k
= b
1
n
p
1
(n) + b
2
n
p
2
(n) + ... (VII.5)
Trong đó b
i
là cá c hằ ng khá c nhau và p
i
(n) là cá c đa thức bậ c d
i
của n.
Bằ ng cá ch biế n đổi gầ n như tương tự với dạ ng phương trì nh (VII.1), ta có
thể viết được phương trì nh đặ c trưng cho dạ ng (VII.1)5) như sau :
(a
o
x
k
+ a
1
x
k-1
+ ... + a
k
) (x-b
1
)
d1+1
(x-b
2
)
d2+1
= 0 (VII.6)
Ví dụ 8
: Giả i phương trì nh
t
n
= 2t
n-1
+ n + 2
n
n 1
với t
o
= 0, ta có
t
n
- 2t
n-1
= n + 2
n
có dạ ng (VII.1)5) với b
1
= 1, p
1
(n) = n, b
2
= 2, p
2
(n) = 1. Bậ c của p
1
(n) là 1,
bậ c của p
2
(n) là 0. Vậ y phương trì nh đặ c trưng là :
(x-2) (x-1)
2
(x-2) = 0
Cả hai nghiệ m 1 và 2 đề u có bội là 2. Vậ y nghiệ m tổng quá t của
phương trì nh truy hồi là :
t
n
= c
1
1
n
+ c
2
n1
n
+ c
3
2
n
+ c
4
n2
n
Sử dụng dạ ng truy hồi t
n
= 2t
n-1
+ n+ 2
n
với t
o
= 0 ta có thể tí nh đ ược t
1
,
t
2
và t
3
và từ đó xác đị nh được cá c hệ số c
1
, c
2
, c
3
và c
4
qua hệ sau:
c
1
+ c
3
= 0 khi n = 0
c
1
+ c
2
+ 2c
3
+ 2c
4
= 3 n = 1
c
1
+ 2c
2
+ 4c
3
+ 8c
4
= 12 n = 2
c
1
+ 3c
2
+ 8c
3
+ 24c
4
= 35 n = 3
17
Kế t quả cuối cùng là :
t
n
= -2 -n + 2
n+1
+ n2
n
Dễ dà ng nhậ n thấ y t
n
có O(n2
n
)
Ví dụ 9
:
Giả sử n là lũy thừa của 2. Tì m T(n) từ phương trì nh:
T(n) = 4T(n/2) + n, n > 1
Thay n bằ ng 2k (với k = logn), ta có T(2k) = 4T(2k-1) + 2k. Khi đó ta có
thể viế t:
t
k
= 4t
k-1
+ 2
k
Nế u t
k
= T(2k) = T(n). Ta đ biế t cá ch giả i phương trì nh truy hồi mới nà y.
Phương trì nh đặ c trưng của nó là :
(x-4) (x-2) = 0
và từ đó ta có t
k
= c
1
4
k
+ c
2
2
k
Đặ t n ngược lạ i thay cho k, ta tì m đ ược :
T(n) = c
1
n
2
+ c
2
n
Do đó T(n) có 0(n
2
) khi n là lũy thừa của 2.
Ví dụ 10
:
T(n) = 4t(n/2) + n
2
, n > 1, lũy thừa của 2. Đặ t n = 2
k
, ta có.
T(2
k
) = 4T(2
k-1
) + 4
k
Phương trì nh đặ c trưng (x-4)2 = 0 và ta có t
k
= c
1
4
k
+ c
2
k4
k
Vậ y T(n) = c
1
n2 + c
2
n
2
logn và T(n) là 0(n
2
logn) với n lũy thừa 2.
Ví dụ 11
:
T(n) = 2T(n/2) + nlogn, n > 1
Sau khi thay n = 2k, ta có T(2
k
)= 2T(2
k-1
) + k2
k
và
t
k
= 2t
k-1
+ k2
k
Phương trì nh đặ c trưng (x-2)
3
= 0 và t
k
= c
1
2
k
+ c
2
k2
k
+ c
3
k
2
2
k
.
Vậ y T(n) = c
1
n + c
2
nlogn + c
3
nlog
2
n có 0(nlog
2
n), n lũy thừa 2.
18
Ví dụ 12 :
T(n) = 3T(n/2) + cn (c là const, n = 2
k
> 1)
Ta sẽ nhậ n đ ược :
T(2
k
) = 3T(2
k-1
) + c2
k
; t
k
= 3t
k-1
+ c2
k
Phương trì nh đặ c trưng là (x-3) (x-2) = 0, và do đó.
Tk = c
1
3
k
+ c
2
2
k
; T(n) = c
1
3
logn
+ c
2
n
Do alogb = bloga nê n T(n) = c
1
n
log3
+ c
2
n có 0(n
log3
),n lũy thừa 2.
c) Phương trì nh truy hồi có hệ số biế n đổi
Ta xé t ví dụ cụ thể :
T(1) = 6
T(n) = nT
2
(n/2), n > 1,n lũy thừa của 2
(hệ số ở vế phải là biến n)
Trước hế t ta đặ t t
k
= T(2
k
) và từ đấ y ta có :
t
k
= 2
k
t
2
K-1
k > 0
to = 6
Để lậ p phương trì nh truy hồi mới không có hệ số biến đổi ta đặ t V
k
= lgt
k
, ta
đ ược :
V
k
= K + 2V
k-1
k >0
V
o
= lg6
Nghĩ a là ta có hệ phương trì nh dạ ng (VI.3)
Phương trì nh đặ c trưng sẽ là
(x-2) (x-1)2 = 0
và do đó :
V
k
= c
1
2
k
+ c
2
1
k
+ c
3
k1
k
Từ V
o
= 1 + lg3, V
1
= 3+2lg3 và V
2
= 8 + 4lg3 ta tì m ra
c
1
= 3 + lg3, c
2
= -2 và c
3
= -1.
Vậ y V
3
= (3 + lg3) 2
k
- K -2
Cuối cùng, sử dụng tk = 2
vk
và T(n) = tlgn, ta đ ược :
n
nT
nn
32
)(
23
=
19
chương Ii
đệ qui
I. Khái niệm :
Đệ qui là 1 công cụ rất thường dùng trong khoa học má y tí nh và trong toá n
học để giả i quyế t cá c vấ n đề . Trước hế t, chúng ta h y khả o sá t thế nà o là một vấ n
đề có đệ qui qua ví dụ sau:
Tí nh S(n) = 1 +2 +3 +4+ ... +n
Ta nhậ n thấ y rằ ng, công thức trê n có thể diễ n đạ t lạ i như sau:
S(n) = S(n-1) + n, và
S(n-1) = S(n-2) + (n-1)
.....
S(2) = S(1) + 2
S(1) = 1
Như vậ y, một vấn đề có đệ qui là vấn đề được đị nh nghĩ a lại bằng chí nh nó.
Một cá ch tổng quá t, một chương trì nh đệ qui có thể đ ược biể u diễ n như bộ
P gồm cá c mệ nh đề cơ sở S (không chứa P) và bả n thâ n P:
P P (S
i
, P)
Để tí nh S(n)
: ta có kế t quả của S(1), thay nó và o S(2), có S(2) ta thay nó và o
S(3)...., cứ như vậ y có S(n-1) ta sẽ tí nh đ ược S(n)
Cũng như cá c lệ nh lặ p, cá c thủ tục đệ qui cũng có thể thực hiệ n cá c tí nh
toá n không kế t thúc, vì vậ y ta phả i xé t đế n vấ n đề kế t thúc cá c tí nh toá n trong
giả i thuậ t đệ qui. Rõ rà ng 1 thủ tục P đ ược gọi đệ qui chỉ khi nà o thỏa 1 điều
kiệ n B, và dĩ nhiê n điề u kiệ n B nà y phả i không được thỏa m n tạ i 1 thời điể m
nào đó. Như vậ y mô hì nh về cá c giả i thuậ t đệ qui là :
P if (B) P(S
i
, P)
hay P P(S
i
, if (B) P).
Thông thường trong cá c vòng lặ p while, để đả m bả o cho vòng lặ p kế t thúc
ta phả i đị nh nghĩ a một hà m f(x) (x là 1 biế n trong chương trì nh) sao cho nó phả i
trả về trị bằ ng 0 tạ i một thời điể m nà o đó. Tương tự như vậ y, chương trì nh đệ qui
cũng có thể đ ược chứng minh là sẽ dừng bằ ng cá ch chứng minh rằ ng hà m f(x) sẽ
giả m sau mỗi lầ n thực hiệ n. Một cá ch thường là m là kế t hợp một giá trị n với P
và gọi P một cá ch đệ qui với giá trị tham số là n-1. Điề u kiệ n B bâ y giờ là n > 0
thì sẽ đả m bả o đ ược sự kế t thúc của giả i thuậ t đệ qui. Như vậ y, ta có mô hì nh đệ
qui mới:
P(n) if (n >0) P(S
i
, P(n-1))
Hay P P (S
i
, if (n>0) P(n-1) )
20
II. Hàm đệ qui và Stack:
Một chương trì nh C thường gồm có hà m main() và cá c hà m khá c. Khi chạ y
chương trì nh C thì hà m main() sẽ được gọi chạ y trước, sau đó hà m main() gọi cá c
hà m khá c, cá c hà m nà y trong khi chạ y có thể gọi cá c hà m khá c nữa. Khi một hà m
đ ược gọi, thì một khung kí ch hoạ t của nó đ ược tạ o ra trong bộ nhớ stack. Khung
kí ch hoạ t nà y chứa cá c biế n cục bộ của hà m và mẩ u tin hoạ t động của hà m. Mẩ u
tin hoạ t động chứa đị a chỉ trở về của hà m gọi nó và cá c tham số khá c.
Biế n cục bộ
Đị a chỉ trở về Mẩ u tin
hoạ t động
{
Thông số khá c
Khung kí ch hoạ t
Sau khi hà m đ ược gọi đ thi hà nh xong thì chương trì nh sẽ thực hiệ n tiế p
dòng lệ nh ở đị a chỉ trở về của hà m gọi nó, đồng thời xóa khung kí ch hoạ t của
hà m đó khỏi bộ nhớ.
Giả sử ta có cơ chế gọi hà m trong một chương trì nh C như sau:
main()
{ ......
A();
.....;
B();
....;
}
A()
{.....;
C();
....;
D();
}
B()
{.....;
D();
}
C()
{......;
D();
.....;
}
D()
{........;
........;
}
Hì nh sau đâ y cho ta thấ y sự chiế m dụng bộ nhớ stack khi chạ y chương trì nh
C như mô tả ở trê n.
MMMMMMMMMMMMM
AAAAAAA BBB
CCC D D
D
Boọ nhụự
Stack
Thụứi gian
Tương tự với trường hợp hà m đệ qui, khi gọi đệ qui lẫ n nhau thì một loạ t
cá c khung kí ch hoạ t sẽ đ ược tạ o ra và nạ p và o bộ nhớ Stack. Cấ p đệ qui cà ng cao
21
thì số khung kí ch hoạ t trong Stack cà ng nhiề u, do đó, có khả nă ng dẫ n đế n trà n
Stack (Stack overflow). Trong nhiề u trường hợp khi lậ p trì nh, nế u có thể được, ta
nê n gỡ đệ qui cho cá c bà i toá n.
III. ví dụ
Ví dụ 1
: Hà m giai thừa:
1*2*3*......*(n-1)*n , n>0
n! =
{
1 , n=0
n*(n-1)! , n>0
n! =
{
1 , n= 0
Nhận xé t
:
- Theo công thức trê n, ta nhậ n thấ y trong đị nh nghĩ a của n giai thừa (n!) có
đị nh nghĩ a lạ i chí nh nó nê n hà m giai thừa có đệ qui.
- Điề u kiệ n dừng tí nh hà m giai thừa là n=0, khi đó n! = 1
- Hà m đệ qui
:
long giaithua(int n)
{
if (n == 0)
return(1);
else
return(n * giaithua(n-1));
}
hay:
long giaithua(int n)
{ return ((n==0) ? 1 : n*giaithua(n-1));
}
- Hà m không đệ qui
:
long giaithua (int n)
{ long gt=1;
for (int i=1; i<=n; i++)
gt= gt * i ;
return (gt);
}
22
Ví dụ 2: Hà m FIBONACCI:
F
n
=
{
1 ; n =0,1
F
n-1
+ F
n-2
; n>1
Nhận xé t
:
- Theo đị nh nghĩ a trê n, hà m Fibonacci có lời gọi đệ qui.
- Quá trì nh tí nh dừng lạ i khi n= 1
- Hà m đệ qui
:
long fib(int n)
{ if (n==0 || n==1)
return 1 ;
else return(fib(n-1) + fib(n-2));
}
- Hà m không đệ qui
:
long fib(int n)
{ long kq, Fn_1, Fn_2;
kq = 1;
if (n > 1)
{
Fn_1 = 1;
Fn_2 = 1;
for (int i=2; i<=n; i++)
{
kq = Fn_1 + Fn_2 ;
Fn_2 = Fn_1;
Fn_1 = kq;
}
}
return (kq);
}
Ví dụ 3
: Bà i toá n Thá p Hà nội
Có 3 cột A, B, C. Cột A hiệ n đang có n dĩ a kí ch thước khá c nhau, dĩ a nhỏ ở
trê n dĩ a lớn ở dưới. H y dời n dĩ a từ cột A sang cột C (xem cột B là cột trung
gian) với điề u kiệ n mỗi lầ n chỉ đ ược dời 1 dĩ a và dĩ a đặ t trê n bao giờ cũng nhỏ
hơn dĩ a đặ t dưới.
23
- Giả i thuậ t đệ qui: Để dời n dĩ a từ cột A sang cột C (với cột B là cột trung
gian), ta có thể xem như :
+ Dời (n-1) dĩ a từ cột A sang cột B ( với cột C là cột trung gian)
+ Dời dĩ a thứ n từ cột A sang cột C
+ Dời (n-1) dĩ a từ cột B sang cột C ( với cột A là cột trung gian)
- Chương trì nh
:
void hanoi (int n, char cotA, char cotC, char cotB)
{
if(n == 1)
printf("\n%s%c%s%c", " chuyen dia 1 tu cot ", cotA, " den cot ", cotC);
else
{
hanoi(n-1, cotA, cotB, cotC);
printf("\n%s%d%s%c%s%c", " chuyen dia ", n, " tu cot ", cotA,
" den cot ", cotC);
hanoi(n-1, cotB, cotC, cotA);
}
}
IV. CáC THUậT TOáN LầN NGƯợC
:
Trong lậ p trì nh, đôi khi ta phả i xá c đị nh cá c thuậ t giả i để tì m lời giả i cho
cá c bà i toá n nhấ t đị nh nhưng không phả i theo một luậ t tí nh toán cố đị nh, mà
bằ ng cá ch thử-và -sai. Cá ch chung là phâ n tí ch thử-và -sai thà nh những công việ c
cục bộ. Thông thường công việ c nà y đ ược thực hiệ n trong dạ ng đệ qui và bao
gồm việ c thă m dò một số hữu hạ n cá c nhiệ m vụ nhỏ. Trong bà i giả ng nà y ta
không tì m hiể u cá c qui tắ c tì m kiế m tổng quá t, mà chỉ tì m những nguyê n lý
chung để chia việ c giả i bà i toá n thà nh những việ c nhỏ và ứng dụng của sự đệ qui
là chủ đề chí nh. Trước hế t, ta minh họa kỹ thuậ t că n bản bằ ng cá ch xé t bà i toá n
m đi tuầ n.
Ví dụ 1
. Bà i toá n m đi tuầ n.
Cho bà n cờ có n x n ô. Một con m đ ược phé p đ i theo luậ t cờ vua, đầ u tiê n
nó đ ược đặt ở ô có toạ độ x
0
, y
0
. Câ u hỏi là , nế u có thì h y tì m cá ch sao cho con
m đi qua đ ược tấ t cả cá c ô của bà n cờ, mỗi ô đi qua đúng 1 lầ n.
* Luậ t đi của con m trê n bà n cờ: Tạ i một ô có tọa độ cột x
0
,
hà ng y
0
(x
0
,y
0
)
trê n bà n cờ, con m có 1 trong 8 nước đi như sau:
24
3 2
4 1
Con
M
5 8
6 7
Hì nh 2.1 8 nước đi có thể của con m xuất phát từ cột x
0
, hàng y
0
.
Với tọa độ bắ t đầ u (x
0
,y
0
), có tấ t cả 8 ô (u,v) mà con m có thể đi đến được.
Chúng đ ược đánh số từ 1 đế n 8 trong hì nh 2.1
Phương pháp đơn giản để có được u,v từ x,y là cộng cá c chê nh lệ ch cột,
dòng về tọa độ đ ược lưu trong 2 mả ng a và b. Cá c giá trị trong 2 mả ng a, b đ
đ ược khởi động thí ch ứng như sau:
Ta xem như có 1 hệ trục tọa độ (Oxy) ngay tạ i vị trí (x
0
,y
0
) của con m , thì :
+ Vị trí 1 mà con m có thể đi đ ược là :
u= x
0
+ 2, v = y
0
+ 1
+ Vị trí 2 mà con m có thể đi đ ược là :
u= x
0
+ 1, v = y
0
+ 2
+ Vị trí 3 mà con m có thể đi đ ược là :
u= x
0
+ (-1), v = y
0
+ 2 ....
Như vậ y, mả ng a và b có giá trị sau:
int a[8] = {2, 1, -1,-2, -2, -1, 1, 2};
int b[8] = {1, 2, 2, 1, -1, -2,-2, -1};
* Cá ch biể u diễ n dữ liệ u: Để mô tả đ ược bà n cờ, ta dùng ma trậ n BanCo
theo khai bá o sau:
#define KICHTHUOC 5 // Kí ch thước của bà n cờ
int BanCo[KICHTHUOC][KICHTHUOC]; // Tổ chức bà n cờ là mng hai chiề u
Ta thể hiệ n mỗi ô cờ bằ ng 1 số nguyê n để đá nh đấ u ô đó đ đ ược đi qua
chưa, vì ta muốn lầ n dò theo quá trì nh di chuyể n của con m . Và ta qui ước như
sau:
BanCo [x][y]=0 ; ô (x,y) chưa đi qua
BanCo [x][y]=i ; ô (x,y) đ đ ược đi qua ở nước thứ i ( 1 i n
2
)
25
* Thuật giải:
Cá ch giả i quyế t là ta phả i xé t xem có thể thực hiệ n một nước đi kế nữa hay
không từ vị trí x
0
, y
0
. Thuậ t giả i để thử thực hiệ n nước đi kế.
void thử nước đi kế
{ khởi động cá c chọn lựa có thể đi
do
{ chọn một nước đi;
if chấ p nhậ n đ ược
{ ghi nhậ n nước đi;
if bà n cờ chưa đầ y
{ thử nước đi kế tạ i vị trí vừa ghi nhậ n đ ược;
if không đ ược
xóa nước đi trước
}
}
} while (không đi đ ược && còn nước đi)
}
* Nhận xé t
:
- Để xá c đị nh tọa độ (u,v) của nước đi kế ( 0 i 7 ), ta thực hiệ n như sau:
u = x + a[i] ; v = y + b[i]
- Điề u kiệ n để nước đi kế chấ p nhậ n đ ược là (u,v) phả i thuộc bà n cờ và con
m chưa đi qua ô đó, nghĩ a là ta phả i thỏa cá c điề u kiệ n sau:
(0 u <KICHTHUOC && 0 v< KICHTHUOC && BanCo[u][v]==0 )
- Ghi nhậ n nước đi thứ n, nghĩ a là BanCo [u][v] = n; còn bỏ việ c ghi nhậ n
nước đi là BanCo [u][v] = 0
- Bà n cờ đầ y khi ta đ đi qua tấ t cả cá c ô trong BanCo, lúc đó :
n = KICHTHUOC
2
.
Qua nhậ n xé t trê n, ta có thuậ t giả i chi tiế t hơn như sau:
void thu_nuoc_di(int n, int x, int y, int &q) // thử 8 cá ch đi của con m tạ i
// nước thứ n xuất phát từ ô (x,y)
{ int u,v, q1;
khởi động cá c chọn lựa có thể đi