You are on page 1of 23

Chương 1.

Một số vấn đề cơ sở 12/12/2020

1
CHƯƠNG 1. MỘT SỐ VẤN ĐỀ CƠ SỞ
Chương 1. Một số vấn đề cơ sở 12/12/2020

2 1.1 ĐỊNH NGHĨA TRỰC QUAN VỀ THUẬT TOÁN

• Thuật toán được hiểu là sự đặc tả chính xác một dãy các bước có
thể thực hiện được một cách máy móc để giải quyết một vấn đề.
• Mỗi thuật toán có 1 dữ liệu vào (Input) và 1 dữ liệu ra (Output);
➔ khi thực hiện thuật toán (thực hiện các bước đã mô tả), thuật
toán cần cho ra các dữ liệu ra tương ứng với các dữ liệu vào.
12/12/2020

3 1.2 CÁC TÍNH CHẤT CƠ BẢN CỦA THUẬT TOÁN

• Tính đúng đắn(correctness): khi thực hiện nó phải cho ra các dữ liệu mà ta
mong muốn tương ứng với các dữ liệu vào.
• Tính hiệu quả (efficiency): lựa chọn thuật toán để áp dụng dựa vào các tiêu
chí: TT đơn giản, dễ hiểu; TT dễ cài đặt (dễ viết chương trình); TT cần ít bộ
nhớ; TT chạy nhanh.
12/12/2020

4 CÁC ĐẶC TRƯNG CỦA THUẬT TOÁN

• Tính đơn định: mỗi bước của thuật toán, các thao tác phải hết sức rõ ràng khong gây nên sự nhập nhằng, đa
nghĩa. Thực hiện đúng các bước của thuật toán thì với 1 dữ liệu vào chi có duy nhất 1 dữ liệu ra.
• Tính dừng: thuật toán phải dừng và cho kết quả sau 1 số hữu hạn bước, không được phép rơi vào vòng vô
hạn.
• Tính đúng: sau khi thực hiện thuật toán với quá trình đã định, ta phải được kết quả mong muốn với mọi bộ
dữ liệu đầu vào. Kết quả đó được kiểm chứng bằng yêu cầu bài toán.
• Tính phổ dụng: thuật toán phải dễ sửa đổi để thích ứng với bất kỳ bài toán nào trong một lớp các bài toán và
có thể làm trên các dữ liệu khác nhau
• Tính khả thi: kích thước phải đủ nhỏ, hiệu quả của thuật toán sẽ bằng 0 nếu kích thước của nó vượt khả
năng lưu trữ của bộ nhớ; thuật toán phải được kết thúc trong thời gian cho phép; Phải dễ hiểu và dễ cài đặt
12/12/2020

5 1.3. CÁC CÁCH BIỂU DIỄN THUẬT TOÁN

Để đảm bảo tính chính xác, chỉ có thể hiểu một cách duy nhất, thụât toán cần
được mô tả:
• Dưới dạng mã (code): trong một ngôn ngữ lập trình thành một chương trình
(hoặc một hàm, một thủ tục);
• Dưới dạng giả mã (pseudo code): trình bày một thuật toán để cho ngắn gọn
nhưng vẫn đảm bảo đủ chính xác, sử dụng các câu lệnh trong một ngôn ngữ
lập trình (pascal hoặc C++) và cả các ký hiệu toán học, các mệnh đề trong
ngôn ngữ tự nhiên
12/12/2020

6 1.4. ĐỘ PHỨC TẠP

Tính hiệu quả của thuật toán: gồm 2 yếu tố: độ phức tạp không gian (dung
lượng bộ nhớ lưu dữ liệu vào, dữ liệu ra, và các kết quả trung gian khi thực hiện
thuật toán) và độ phức tạp thời gian (thời gian thực hiện thuật toán)
12/12/2020

7 1.4. ĐỘ PHỨC TẠP ( TIẾP)

Độ phức tạp tính toán của giải thuật: thời gian thực hiện 1 giải thuật bằng máy tính phụ thuộc
vào nhiều yếu tố:
• Kích thước dữ liệu vào: DL càng lớn thì thời gian xử lý càng chậm. Nếu gọi kích thước
DLvào là n thì thời gian thực hiện giải thuật có thể biểu diễn một cách tương đối như 1 hàm
của n: T(n)
• Phần cứng máy tính, ngôn ngữ viết CT và CTD đều ảnh hưởng đến thời gian thực hiện.
Tuy nhiên các yếu tố này không giống nhau trên các loại máy → không thể xác định T(n) dựa
trên chúng được, nói cách khác T(n) không thể biểu diễn bằng đơn vị đo thời gian được
12/12/2020

8 1.4. ĐỘ PHỨC TẠP ( TIẾP)

Vẫn cần phải có cách để so sánh các giải thuật về mặt tốc độ.
Nếu 2 giải thuật có thời gian tính toán là: T1(n) = n2 và T2(n) = 100n thì với n đủ
lớn, giải thuật T2 có thời gian thực hiện nhanh hơn T1
Nói: thời gian thực hiện thuật toán tỷ lệ với n và n2 cho phép ta đánh giá một
cách tương đối về tốc độ thực hiện của giải thuật đó khi n khá lớn. Cách đánh
giá giải thuật độc lập với máy tính và các yếu tốc liên quan đến máy tính đó gọi
là độ phức tạp tính toán của giải thuật
12/12/2020

9 1.4. ĐỘ PHỨC TẠP ( TIẾP)

Cho f và g là 2 hàm xác định tương đương với mọi n. Hàm f(n) được gọi là
O(g(n)) nếu tồn tại 1 hằng số c>0 và một giá trị n0 sao cho:
f(n)  c.g(n) với mọi n ≥ n0
Khi đó, nếu f(n) là thời gian thực hiện 1 giải thuật thì giải thuật đó có cấp g(n),
ký hiệu là O(g(n)) – ký pháp O lớn
12/12/2020

10 1.4.1. XÁC ĐỊNH ĐỘ PHỨC TẠP TÍNH TOÁN CỦA GIẢI


THUẬT

a) Quy tắc cộng:


Nếu đoạn chương trình P1 có thời gian thực hiện T1(n) = O(f(n)) và đoạn chương
trình P2 có thời gian thực hiện là T2(n) = O(g(n)) thì thời gian thực hiện P1 rồi đến
P2 tiếp theo sẽ là: T1(n) + T2(n) = O(max(f(n),g(n)))
b) Quy tắc nhân:
Nếu đoạn chương trình P có thời gian thực hiện là T(n) = O(f(n)). Khi đó, nếu thực
hiện k(n) lần đoạn chương trình P với k(n) = O(g(n)) thì độ phức tạp tính toán sẽ là
O(g(n).f(n))
12/12/2020

11 1.4.1. XÁC ĐỊNH ĐỘ PHỨC TẠP TÍNH TOÁN CỦA GIẢI


THUẬT

c) Một số tính chất:


- Với P(n) là 1 đa thức bậc k thì O(P(n)) = O(nk). Vì thế 1 TT có độ phức tạp cấp đa
thức, người ta ký hiệu là O(nk).
- Với a, b à 2 cơ số tùy ý và f(n) là một hàm dương thì logaf(n) = logab.logbf(n), tức
là: O(logaf(n)) = O(logbf(n)). Với 1 TT có độ phức tạp cấp logarit của f(n), người
ta ký hiệu là O(logf(n)) mà không cẫn ghi cơ số của logarit.
- Nếu 1 TT có độ phức tạp hằng số tức là thời gian thực hiện TT không phụ thuộc
kích thước dữ liệu vào thì ta ký hiệu độ phức tạp tính toán của TT đó là O(1).
12/12/2020

12 1.4.1. XÁC ĐỊNH ĐỘ PHỨC TẠP TÍNH TOÁN CỦA GIẢI


THUẬT

c) Một số tính chất:


- Một TT có cấp là các hàm như 2n, n!, nn được gọi là một giải thuật có độ phức tạp
hàm mũ, các giải thuật này trên thực tế có tốc độ rất chậm.
- Không phải lúc nào một giải thuật cấp O(n2) cũng tốt hơn giải thuật cấp O(n3), vì
vậy khi chọn một TT để giải một bài toán thực tế phải có sự mềm dẻo nhất định.
12/12/2020

13 1.4.1. XÁC ĐỊNH ĐỘ PHỨC TẠP TÍNH TOÁN CỦA GIẢI


THUẬT

Một số hàm số dùng để ký hiệu độ phức tạp tính toán và bảng giá trị của chúng
Log2n n nlog2n n2 n3 2n
0 1 0 1 1 2
1 2 2 4 8 4
2 4 8 16 64 16
3 8 24 64 512 256
4 16 64 256 4096 65536
5 32 160 1024 32768 2147483648
12/12/2020

14 1.4.1. XÁC ĐỊNH ĐỘ PHỨC TẠP TÍNH TOÁN CỦA GIẢI


THUẬT

d) Phép toán tích cực


12/12/2020

15 1.5. TỐI ƯU THUẬT TOÁN

• Một chương trình chạy đúng không có nghĩa là việc lập trình đã xong, ta cần sửa đổi
lại một một vài chi tiết để chương trình có thể chạy nhanh hơn, hiệu quả hơn.
• Trước khi kiểm thử, cần đặt mục tiêu viết chương trình đơn giản: chương trình chạy
ra kết quả đúng, sau đó khi tối ưu chương trình, ta xem lại những chỗ nào viết chưa
tốt thì tối ưu lại mã lệnh để chương trình ngắn hơn, chạy nhanh hơn.
• Không nên viết đến đâu tối ưu đến đấy, vì chương trình có mã lệnh tối ưu thường
phức tạp và khó kiểm soát
• Việc tối ưu chương trình dựa trên các tiêu chuẩn sau:
12/12/2020

16 1.5. TỐI ƯU THUẬT TOÁN( TIẾP)

• Tính tin cậy: Chương trình phảu chạy đúng như dự định, mô tả đúng một giải thuật
đúng. Khi viết chương trình, nên kiểm tra tính đúng đắn của các bước mỗi khi có thể
• Tính uyển chuyển: chương trình phải dễ sửa đổi. Chương trình dễ sửa đổi sẽ làm
giảm bớt công sức của lập trình viên khi phát triển chương trình
• Tính trong sáng: chương trình viết ra phải dễ đọc, dễ hiểu, để sau một thời gian dài,
đọc lại vẫn hiểu được mình làm cái gì. Để nếu có điều kiện, thì có thể sửa sai ( nếu
phát hiện lỗi mới), cải tiến hay biến đổi để chương trình giải quyết bài toán khác.
Tính trong sáng của CT phụ thuộc rất nhiều vào công cụ lập trình và phong cách lập
trình
12/12/2020

17 1.5. TỐI ƯU THUẬT TOÁN( TIẾP)

• Tính hữu hiệu: chương trình phải chạy nhanh và ít tốn bộ nhớ tức là tiết kiệm được
cả không gian và thời gian. Tuy nhiên tiêu chuẩn này không cần được đề cao quá vì
phần cứng phát triển rất nhanh.
→Việc viết ra một chương trình đòi hỏi rất nhiều công đoạn và tiêu tốn nhiều công
sức, nghĩ ra cách giải quyết vấn đề đã khó, biến ý tưởng đó thành hiện thực cũng
không dễ chút nào.
→Không nên viết chương trình khi chưa suy xét kỹ về giải thuật và các dữ liệu cần
thao tác, vì có thể mắc lỗi sai giải thuật hoặc giải thuật không thể triển khai nổi trên
cấu trúc dữ liệu không phù hợp
12/12/2020

18 VD1; GIẢ SỬ CÓ MẢNG A CÁC SỐ THỰC CÓ N PHẦN TỬ, TA


KIỂM TRA XEM MẢNG A CÓ CHỨA SỐ THỰC X HAY KHÔNG?

Thực hiện tìm kiếm tuần tự trong mảng A:


(1)i = 0 // thời gian thực hiện O(1)
(2)While(i<n && x!=A[i])
(3)i++;
// lệnh (2) và (3) thì có tối đa số lần lặp là n vòng lặp, có thể là x xuất hiện ở phần tử
cuối cùng hoặc không có trong dãy số này. Lệnh (2) sẽ có thời gian thực hiện là O(n)
và lệnh thứ (3) sẽ có thời gian thực hiện là O(1)
Theo quy tắc cộng: thời gian thực hiện đoạn chương trình; (1) (2)(3) là max{O(1),
O(n), O(1)} = O(n)
VD2: VIẾT THUẬT TOÁN TẠO MA TRẬN ĐƠN VỊ A CẤP N

(1) for(i=0; i<n;i++)//O(n)


(2) for(j=0; j<n;j++)//O(n)
(3) A[i][j] = 0;// O(1)
(4) for(i=0; i<n;i++)//O(n)
(5) A[i][i] = 1;//O(1)
Vòng lặp for đầu tiên ( dòng (1)-(3) có thân là 1 lệnh lặp (2)-(3) : O(n)
Thời gian thực hiện vòng lặp (1) tính theo quy tắc nhân: O(n)*O(n) = O(n2)
Vòng lặp (4) gồm lệnh (4) và (5): thời gian thực hiện vòng lặp (4) là : O(n)
Thời gian thực hiện đoạn chương trình (1)-(5): được tính dựa trên quy tắc cộng; =
max(O(n2), O(n)) = O(n2)

19 12/12/2020
12/12/2020

20 BÀI TẬP VỀ NHÀ:

Viết chương trình tính n! bằng phương pháp lặp và phương pháp đệ
quy.
Tính thời gian thực hiện thuật toán cho cả 2 trường hợp.
Kết luận gì về thời gian thực hiện thuật toán theo 2 phương pháp đó.
12/12/2020

VÍ dụ 2:
( Hàm tính giai thừa của số nguyên dương n).
int Fact(int n)
{
if (n = = 1)
return 1;
else return n * Fact(n-1);
}
Giả sử thời gian chạy của hàm là T(n), với n = 1 ta có T(1) = O(1).
Với n > 1, ta cần kiểm tra điều kiện của lệnh if-else và thực hiện
phép nhân n với kết quả của lời gọi hàm, do đó T(n) = T(n-1) + O(1).

21 Chương 1. Một số vẫn đề cơ sở


12/12/2020

22

• Như vậy ta có quan hệ đệ quy sau:


• T(1) = O(1)
• T(n) = T(n-1) + O(1) với n > 1
• Thay các ký hiệu O(1) bởi các hằng số dương a và b tương ứng, ta có
• T(1) = a
• T(n) = T(n-1) + b với n > 1
• Sử dụng các phép thế T(n-1) = T(n-2) + b, T(n-2) = T(n-3) + b,..., ta có
• T(n) = T(n-1) + b
• = T(n-2) + 2b
• = T(n-3) + 3b
• ...
• = T(1) + (n-1)b
• = a + (n-1)b
• Từ đó, ta suy ra T(n) = O(n).
1. Đánh giá thời gian chạy của các đoạn chương trình sau:
a. sum = 0;
for ( int i = 0; i < n; i + +)
for ( int j = 0; j < n; j + +)
sum + +;

b. sum = 0;
for ( int i = 0; i < n; i + +)
for ( int j = 0; j < n*n; j + +)
for ( int k = 0; k < j; k + +)
sum + + ;
23 12/12/2020

You might also like