Giáo trình nghiên cứu các kiểu dữ liệu có cấu trúc.
Trang 1GIớ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ớ
Trang 2Chương 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ương trì nh
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
Trang 3III 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(n2) có nghĩ a là :
Ta nó i T(n) là O(f(n)) nế u ∃ const c và n0 sao cho T(n) ≤ c.f(n), ∀ n ≥ n0
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 chặ 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, n0 sao cho T(n) ≥ c.g(n), ∀ n ≥ n0
Ví dụ : Để kiể m tra T(n) = n3 + 2n2 là Ω(n3) ta đ ặ t c = 1 thì T(n) ≥ c.n3, ∀n
= 0, 1, (no= 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(n2) Nế u chư ơ ng trì nh 1 chạ y mấ t 100.n2 thờ i gian (mili giâ y)
thì chương trì nh 2 chạ y mấ t 5.n3 thời gian, thì ta có tỷ số thời gian của 2 chương
trì nh là 5.n3/100.n2 = 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
Giả sử trong 103s 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ế ucó má y tốt tốc độ tă ng lê n 10 lầ n thì kí ch thước tối đa tương ứng
Trang 4Giả sử T1(n) và T2(n) là thời gian chạ y chương trì nh P1 và P2 tương ứng được
đ á nh giá là O(f(n)) và O(g(n)) Khi đ ó T1(n) + T2(n) sẽ là O(max(f(n),g(n))) (chạ y xong chư ơ ng trì nh P1 thì chạ y P2)
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
Nế u g(n) ≤ f(n), ∀ n ≥ no, no là const nà o đ ó thì O(f(n)+g(n)) sẽ là O(f(n))
Ví dụ : O(n2 + n) = O(n2)
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
Trang 5Ví 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 ;
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
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
Trang 63 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 ;
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) +
Trang 7c + T(n-1) nế u n > 1 T(n) =
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ớt1 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 N2
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.
{
Trang 8Khi 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 N2
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 N3
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 2n
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
Trang 9thiế 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 N2 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 N3/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 Nlog2N
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ử
Trang 10Cn 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 = 2m đ ể cho cô ng thứ c luô n luô n có nghĩ a Chú ng ta viế t như sau :
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 Cn khoả ng logn vớ i mọ i n
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
Trang 112
m m
m C
1 2
m m
Cn 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
Trang 12Sau khi gi¶ thiÕ t tn = xn ta ® a (VII.1) vÒ d¹ ng:
t n i k
i i
1
1
n n
Trang 14Ta cã c¸ c nghiÖ m 1 (cã bé i 1), 2 (cã bé i 2) VË y nghiÖ m tæ ng qu¸ t lµ :
VÝ dô 5 :
tn - 2tn-1 = (n+5)3n
Trang 15Ta nhË n thÊ y tõ tn = c11n + c22n cò ng cã thÓ kÕ t luË n tn cã O(2n)
Trang 16VÝ dô 7 :
tn = 2tn-1 + n hay tn - 2tn-1 = n
Trang 18n n
32)(
2
3 −
=
Trang 19Như 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ộ
nà o đ ó Như vậ y mô hì nh về cá c giả i thuậ t đ ệ qui là :
P ≡ if (B) P(Si, P)
hay P ≡ P(Si, 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(Si, P(n-1))
Hay P ≡ P (Si, if (n>0) P(n-1) )
Trang 20II 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
D();
}
C() { ;
D();
.;
}
D() { ;
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
Trang 21thì 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
if (n == 0) return(1);
else return(n * giaithua(n-1));
} hay:
long giaithua(int n) { return ((n==0) ? 1 : n*giaithua(n-1));
Trang 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)
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ạ độ x0, y0 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 x0,hà ng y0 (x0,y0) trê n bà n cờ , con m∙ có 1 trong 8 nư ớ c đ i như sau:
Trang 243 2
4 1
Con M∙
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í (x0,y0) của con m∙ , thì : + Vị trí 1 mà con m∙ có thể đ i đ ư ợ c là :
u= x0 + 2, v = y0 + 1 + Vị trí 2 mà con m∙ có thể đ i đ ư ợ c là :
u= x0 + 1, v = y0 + 2 + Vị trí 3 mà con m∙ có thể đ i đ ư ợ c là :
#define KICHTHUOC 5 // Kí ch thư ớ c củ a bà n cờ
int BanCo[KICHTHUOC][KICHTHUOC]; // Tổ chức bà n cờ là m∙ ng 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 ≤ n2 )
Trang 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í x0, y0 Thuậ t giả i đ ể thử thự c hiệ n nư ớ c đ i kế
- Đ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
{ int u,v, q1;
khở i đ ộ ng cá c chọ n lự a có thể đ i
Trang 26do
{ u = x + a[i] ;
v = x + b[i];
if (0 ≤ u < KICHTHUOC && 0 ≤ v < KICHTHUOC
Trang 27// Hµ m thu_nuoc_di gió p ® i n í c thø n xuÊ t ph¸ t tõ « (x, y)
void thu_nuoc_di (int n, int x, int y, int &q)
Trang 28printf("\n\t\t\t CHUONG TRINH MA DI TUAN\n");
printf("\n\t\tKich thuoc ban co %dx%d", KICHTHUOC, KICHTHUOC); printf("\n\n\t\t 0 1 2 3 4 5 6 7");
Trang 29* Bả ng sau đ â y cho ta một số lời giả i tương ứng với cá c vị trí đầ u và kí ch thư ớ c củ a bà n cờ :
Ví dụ 2: Bà i toá n tá m hoà ng hậ u
Bà i toá n tá m hà ng hậ u được mô tả như sau: tá m hoà ng hậ u được đặ t lê n bà n
cờ vua sao cho khô ng bà nà o có thể chiế m lấ y cá c bà khá c
* Theo luậ t của cờ vua, một hoà ng hậ u có thể chiế m lấ y cá c quâ n khá c nằ m
ở cùng dòng, hay cùng cột, hay cùng cá c đ ường ché o Do đó, ta suy ra rằ ng mỗi cột chỉ có thể chứa một hoà ng hậ u và chỉ 1 mà thôi Ta qui ước hoà ng hậ u thứ 0 sẽ
đặ t ở cột 0, hoà ng hậ u thứ 1 sẽ đặ t ở cột 1, , hoà ng hậ u thứ 7 sẽ đặ t ở cột 7 Như
vậ y, việ c chọn chỗ cho hoà ng hậ u thứ i là tì m vị trí dòng j có thể có trê n cột i Sau đ â y là hì nh minh họ a cho mộ t lờ i giả i củ a bà i toá n: (0 6 4 7 1 3 5 2)
Trang 30* Cá ch biể u diễ n dữ liệ u:
Bà n cờ 8x8 có 8 hà ng, 8 cột, 15 đường ché o xuôi, 15 đường ché o ngược, ta qui ước 1 con hậ u chỉ có thể đặ t trê n 1 cột i và hà ng j nà o đó của bà n cờ Khi đó, cá c vị trí trê n đường ché o xuôi và đường ché o ngược của bà n cờ không thể dùng
để đặ t cá c con hậ u khá c Ta lưu ý rằ ng cá c phầ n tử cùng nằ m trê n 1 đường ché o xuô i củ a bà n cờ thỏ a m∙ n biể u thứ c sau (cộ t i - hà ng j + 7 = hằ ng số ), và cá c phầ n tử cù ng nằ m trê n 1 đ ư ờ ng ché o ngư ợ c củ a bà n cờ thỏa m∙ n biể u thức sau (cộ t i + hà ng j = hằ ng số ) như hì nh sau:
đườ ng ché o xuô i đườ ng ché o ngượ c
14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
0 1 2 3 4 5 6
Đường chéo ngược
Như vậ y, ta sẽ xâ y dự ng cấ u trú c dữ liệ u sau đ ể lư u trữ dữ liệ u:
int hang_trong[8] ; // hà ng trố ng cò n có thể đ ặ t hoà ng hậ u
int cheo_xuoi[15];
// duong cheo xuoi co the dat hoang hau Cac phan tu tren duong cheo xuoi //thoa (cot i -hang j +7 = hangso)
int cheo_nguoc[15];
Trang 31// duong cheo nguoc co the dat hoang hau Cac phan tu tren duong cheo // nguoc thoa (cot i +hang j = hangso)
int loi_giai[8] ; // loi giai chua ket qua
ví i:
- hang_trong[j] = TRUE nghÜ a lµ ch a cã con hË u nµ o trª n hµ ng thø j
- cheo_xuoi[k] = TRUE nghÜ a lµ ch a cã con hË u nµ o trª n ®êng chÐ o xu«i thø k
- cheo_nguoc[k] = TRUE nghÜ a lµ ch a cã con hË u nµ o trª n ® ê ng chÐ o ng î c thø k
VÝ dô :
C¸ c vÞ trÝ trª n ® ê ng chÐ o xu« i thø 12 : 5 - 0 +7 = 6 -1 +7 = 7 -2 + 7 = 12 C¸ c vÞ trÝ trª n ® ê ng chÐ o ng î c thø 12: 7 + 5 = 6 + 6 = 5 + 7 = 12
}
} while (kh« ng thµ nh c« ng && ch a ® Æ t hÕ t c¸ c vÞ trÝ )
}
* NhË n xÐ t: Ví i c¸ c d÷ liÖ u ® ∙ cho, th× :
- §iÒ u kiÖ n an toµ n lµ ® iÒ u kiÖ n sao cho hoµ ng hË u thø i (cé t i) n» m trª n
hµ ng j sao cho hµ ng j vµ c¸ c ®êng chÐ o ®i qua « (j,i) cha bÞ chiÕ m gi÷ bëi c¸ c hoµ ng hË u kh¸ c; nghÜ a lµ nã ph¶ i thá a biÓ u thø c logic:
hang_trong[j] && cheo_xuoi [i-j+7] && cheo_nguoc[i+j]
- §Æ t hoµ ng hË u sÏ ® î c thÓ hiÖ n bë i:
Trang 32loi_giai[i] = j ;
hang_trong[j] = FALSE ; cheo_xuoi [i-j+7] =FALSE; cheo_nguoc[i+j] = FALSE;
- Dờ i hoà ng hậ u đ i sẽ đ ư ợ c thể hiệ n bở i:
hang_trong[j]=TRUE ; cheo_xuoi [i-j+7] =TRUE;
cheo_nguoc[i+j] = TRUE;
- Điề u kiệ n chư a đ ặ t hế t cá c hoà ng hậ u : i < 7
- Để biế t đ ư ợ c đ ặ t hoà ng hậ u thứ i có thà nh công hay không, ta dùng thê m
1 tham số hì nh thứ c biế n q Nế u đ ặ t thà nh cô ng thì q = TRUE, ngư ợ c lạ i q=FALSE
* Chương trì nh: Qua nhậ n xé t trê n, ta có chương trì nh của bà i toá n 8 hoà ng
// tim 1 loi giai cho bai toan 8 hoang hau
int hang_trong[8] ; // hà ng trong con co the dat hoang hau
int cheo_xuoi[15]; // duong cheo xuoi co the dat hoang hau Cac phan tu
// tren duong cheo xuoi thoa (cot i -hang j +7 = hangso) int cheo_nguoc[15]; // duong cheo nguoc co the dat hoang hau Cac phan tu
// tren duong cheo nguoc thoa (cot i +hang j = hangso) int loi_giai[8] ; // loi giai chua ket qua
Trang 33printf("\n\t\t\t CHUONG TRINH 8 HOANG HAU\n");
printf("\n\n\t\t 0 1 2 3 4 5 6 7 "); printf("\n\t\t + -+ -+ -+ -+ -+ -+ -+ -+ "); printf("\n\t\t 0 - - - - - - - - "); printf("\n\t\t + -+ -+ -+ -+ -+ -+ -+ -+ "); printf("\n\t\t 1 - - - - - - - - "); printf("\n\t\t + -+ -+ -+ -+ -+ -+ -+ -+ "); printf("\n\t\t 2 - - - - - - - - "); printf("\n\t\t + -+ -+ -+ -+ -+ -+ -+ -+ "); printf("\n\t\t 3 - - - - - - - - "); printf("\n\t\t + -+ -+ -+ -+ -+ -+ -+ -+ "); printf("\n\t\t 4 - - - - - - - - "); printf("\n\t\t + -+ -+ -+ -+ -+ -+ -+ -+ "); printf("\n\t\t 5 - - - - - - - - "); printf("\n\t\t + -+ -+ -+ -+ -+ -+ -+ -+ "); printf("\n\t\t 6 - - - - - - - - "); printf("\n\t\t + -+ -+ -+ -+ -+ -+ -+ -+ "); printf("\n\t\t 7 - - - - - - - - "); printf("\n\t\t + -+ -+ -+ -+ -+ -+ -+ -+ "); for(i = 0; i < 8; i++)
Trang 34void main (void)
Trang 35void chon_vi_tri (int i)
Trang 36cprintf("\n CHUONG TRINH 8 HOANG HAU\n ");
printf("\n Loi giai thu %d", ++SoLoiGiai);
Trang 37hang_trong[j]=FALSE; cheo_xuoi[i-j+7] = FALSE;
Trang 38H∙ y viÕ t ch ¬ ng tr× nh di chuyÓ n n dÜ a tõ cä c A sang cä c C ví i cä c B
lµ m trung gian, theo ® iÒ u kiÖ n :
- Mç i lÇ n chØ di chuyÓ n mé t dÜ a
- Bao giê dÜ a nhá cò ng n» m trª n dÜ a lí n
3 ViÕ t ch ¬ ng tr× nh t× m mä i lê i gi¶ i cho bµ i to¸ n m∙ ® i tuÇ n
Trang 39chương Iii
Danh sách tuyến tí nh
KHáI NIệM :
Danh sá ch là mộ t tậ p hợ p n phầ n tử a0, a1, a2, , an-1, mỗ i phầ n tử có kiể u
đ ơ n giả n hoặ c kiể u dữ liệ u có cấ u trú c
Tí nh tuyế n tí nh củ a danh sá ch thể hiệ n ở sự rà ng buộ c giữ a cá c phầ n tử trong danh sá ch với nhau, ví dụ như từ vị trí của phầ n tử ai ta sẽ tì m được giá trị
củ a phầ n tử ai+1
I Định nghĩ a:
Danh sá ch tuyế n tí nh là 1 d∙ y cá c phầ n tử có cù ng kiể u dữ liệ u đ ư ợ c sắ p
xế p liê n tiế p nhau trong bộ nhớ
đặ c đ iể m củ a danh sá ch tuyế n tí nh:
- Kí ch thư ớ c củ a danh sá ch sẽ đ ư ợ c cấ p phá t theo khai bá o
- Cá c phầ n tử củ a danh sá ch nằ m liê n tục nhau trong bộ nhớ, giữa cá c phầ n
tử nà y khô ng có khoả ng trố ng
- Tiê u biể u cho danh sá ch đ ặ c là d∙ y (array) Để cà i đ ặ t danh sá ch tuyế n
tí nh, ta dù ng mả ng 1 chiề u
! Khai báo: Ta khai bá o cấ u trúc list là một mẩ u tin (struct) có 2 field:
- n : cho biế t số phầ n tử hiệ n có trong danh sá ch Nế u n ==0 thì có nghĩ a là danh sá ch rỗ ng
- danhsach : là mả ng 1 chiề u, mỗi phầ n tử của mả ng là 1 phầ n tử trong danh sá ch
Trang 40};
struct list ds; // biế n ds thuộ c kiể u struct list
Ví dụ: Khai bá o 1 danh sá ch họ tê n học viê n của 1 lớp học, có tối đa 50 học
II Các phép toán trên danh sách tuyến tí nh:
Để đơn giả n, cá c phé p toá n sau đâ y sẽ đ ược thao tá c trê n danh sá ch cá c số nguyê n vớ i khai bá o như sau:
struct list ds; // biế n ds thuộ c kiể u struct list
1 Phé p toá n Empty: kiể m tra xem danh sá ch có rỗ ng hay khô ng?
int Empty(struct list plist)
{
return (plist.n==0 ? TRUE : FALSE);
}
2 Phé p toá n Full: kiể m tra xem danh sá ch đ ∙ đ ầ y chư a?
int Full(struct list plist)