Giáo trình môn Thuật toán

MỤC LỤC

1. THUẬT TOÁN

2. CÁC PHƯỢNG PHÁP BIỂU DIỄN THUẬT TOÁN

3. ĐỘ PHỨC TẠP CỦA THUẬT TOÁN

4.PHÂN LOẠI VẤN ĐỀ - BÀI TOÁN

5. THUẬT TOÁN ĐỆ QUY

6.THUẬT GIẢI

5.1.GIỚI THIỆU NGÔN NGỮ PASCAL

5.2. CÁC PHẦN TỬ CƠ BẢN CỦA NGÔN NGỮ PASCAL

5.3. CẤU TRÚC CHUNG CỦA CHƯƠNG TRÌNH PASCAL

5.4. SỬ DỤNG PHẦN MỀM TURBO PASCAL

5.5 CÂU HỎI TRẮC NGHIỆM

5.6. BÀI TẬP

6.1. KHÁI NIỆM VỀ KIỂU DỮ LIỆU

6.2. KIỂU SỐ NGUYÊN

6.3. KIỂU SỐ THỰC

6.4. KIỂU KÝ TỰ (CHAR)

6.5. KIỂU LÔGIC (BOOLEAN)

6.6. CHUỖI KÝ TỰ (STRING)

6.7. CÂU HỎI TRẮC NGHIỆM

7.1. HẰNG, BIẾN và BIỂU THỨC

7.2. CÂU LỆNH và LỜI CHÚ GIẢI

7.3.1. NHẬP DỮ LIỆU, THỦ TỤC “READLN”

7.3.2. XUẤT DỮ LIỆU, THỦ TỤC “WRITE” và “WRITELN”

7.4. KIỂU LIỆT KÊ và KIỂU ÐOẠN CON

7.5. CÂU HỎI TRẮC NGHIỆM

7.6. BÀI TẬP8.1. CÂU LỆNH IF

8.2. CÂU LỆNH CASE

8.3. CÂU HỎI TRẮC NGHIỆM

8.4. BÀI TẬP

9.1. CÂU LỆNH LẶP FOR

9.2. CÂU LỆNH LẶP WHILE

9.3. CÂU LỆNH LẶP REPEAT

9.4. CÂU HỎI TRẮC NGHIỆM

9.5. BÀI TẬP

10.1. MẢNG MỘT CHIỀU

10.2. MẢNG HAI CHIỀU (MA TRẬN)

10.3. CÂU HỎI TRẮC NGHIỆM

10.4. BÀI TẬP

11.1. CÁC VÍ DỤ NÂNG CAO VỀ CÂU LỆNH LẶP

11.2. CÁC VÍ DỤ NÂNG CAO VỀ MẢNG

11.3. KIỂU CHUỖI KÝ TỰ

11.4. CÂU HỎI TRẮC NGHIỆM

11.5. BÀI TẬP

12.1. KHÁI NIỆM VỀ CHƯƠNG TRÌNH CON

12.2. HÀM (FUNCTION)

12.3. THỦ TỤC (PROCEDURE)

12.4. CÂU HỎI TRẮC NGHIỆM

12.5. BÀI TẬP

13.1. THAM SỐ TRỊ VÀ THAM SỐ BIẾN

13.2. PHẠM VI TÁC DỤNG CỦA CÁC KHAI BÁO

13.3. SỰ THAM KHẢO TRƯỚC và SỰ ÐỆ QUI

13.4. CÂU HỎI TRẮC NGHIỆM13.5. BÀI TẬP

14.1 KIỂU BẢN GHI

14.2. CÁC VÍ DỤ VỀ BẢN GHI

14.3. CÂU HỎI TRẮC NGHIỆM

14.4 .BÀI TẬP

15.1. KIỂU TẬP HỢP

15.2. DỮ LIỆU KIỂU TẬP TIN

15.3. CÂU HỎI TRẮC NGHIỆM

15.4. BÀI TẬP

pdf297 trang | Chia sẻ: trungkhoi17 | Lượt xem: 378 | Lượt tải: 0download
Bạn đang xem trước 20 trang tài liệu Giáo trình môn Thuật toán, để xem tài liệu hoàn chỉnh bạn click vào nút DOWNLOAD ở trên
6:2); Readln; End. Chạy Chép file nguồn Ví dụ 9.4: In bảng các chữ cái từ A đến Z thành bốn cột như sau: KÝ TỰ MÃ KÝ TỰ MÃ A 65 a 97 B 66 b 98 Yêu cầu in thành từng trang màn hình, mỗi trang 15 dòng. Trong chương trình ta dùng biến Dem để đếm số dòng đã in, mỗi khi in xong một dòng thì biến Dem được cộng thêm 1. Khi Dem = 15, 30, 45, ... (tức Dem mod 15=0) thì phải làm lệnh Readln; lệnh này sẽ dừng màn hình cho đến khi ta gõ Enter mới in tiếp. PROGRAM VIDU94; { In bảng các chữ cái} Uses Crt; Var ch, ch1 : Char; Dem: Integer; Begin CLRSCR; Writeln(‘ KY TU MA KY TU MA’); Dem:=0; For ch:=‘a’ to ‘z’ do begin ch1:=Upcase(ch); Writeln( ch1 :3 , Ord(ch1) :6 , ch :6 , Ord(ch) :6 ); Inc(Dem); If Dem mod 15 = 0 then begin Write(‘ Enter để xem tiếp ‘); Readln; end; end; Writeln(‘ HET ‘); Readln; End. Chạy Chép file nguồn Chương trình trên là một ví dụ về cách dùng biến chạy kiểu ký tự (ch) trong lệnh FOR, ngoài ra, đóng vai trò LệnhP là một lệnh ghép, gồm nhiều lệnh đặt trong khối begin và end. 9.1.2. Câu lệnh FOR dạng 2: Cú pháp: FOR biến := m2 DOWNTO m1 DO LệnhP; Cách thức hoạt động của FOR dạng 2: Bước 1: gán gía trị biến := m2; Bước 2: Nếu biến ≥ m1 thì làm LệnhP, rồi sang bước 3. Nếu biến<m1 thì không làm LệnhP mà chuyển sang lệnh kế tiếp ở phía dưới. Bước 3 : Giảm gía trị của biến : biến:=Pred(biến); Quay lại bước 2. Tóm lại, LệnhP sẽ được làm đi làm lại, bắt đầu khi biến=m2, và kết thúc khi biến = m1-1, cả thảy là m2-m1+1 lần. Ví dụ 9.5: Ðể tính S= N!, ta có thể viết : S=N*(N-1)*(N-2)*...*2*1 Cách viết cho thấy ngay cách tính: đầu tiên gán S:=1, sau đó thực hiện việc nhân dồn S:=S* i với i= N, N-1,..., 2, 1. Tức là: S:=1; For i:=N downto 1 do S:=S* i; Tương tự , để tính S=xN , ta cũng có thể dùng FOR dạng 2 : S:=1; For i:=N downto 1 do S:=S* x; Như vậy, lệnh FOR dạng 2 về bản chất chỉ là một cách viết khác của dạng 1. Thông thường người ta hay dùng lệnh FOR dạng 1, tuy nhiên có khá nhiều tình huống mà việc dùng lệnh FOR dạng 2 tỏ ra rất hiệu qủa, như ví dụ sau đây: Ví dụ 9.6 : In các chữ cái theo thứ tự ngược từ Z đến A thành hai dòng : Z, Y, X, ..., C, B, A z, y, x, ... , c, b, a Chương trình được viết như sau: PROGRAM VIDU96; { In các chữ cái theo thứ tự đảo ngược từ z đến a} Var Ch: Char; Begin For ch:=‘Z’ downto ‘A’ do write(ch:3 ); Writeln; For ch:=‘z’ downto ‘a’ do write(ch :3 ); Writeln; Readln; End. Chạy Chép file nguồn 9.1.3. Câu lệnh FOR lồng nhau : Trong cấu trúc FOR, khi LệnhP cũng là một lệnh FOR thì ta có cấu trúc FOR lồng nhau: FOR biến1:= m1 TO m2 DO {1} FOR biến2:=n1 TO n2 DO LệnhP; {2} Cách thức hoạt động của lệnh này như sau: Ðầu tiên cho biến1:=m1 và làm lệnh ở dòng {2}. Vì dòng {2} là lệnh FOR nên với mỗi gía trị của biến2=n1, ..., n2, đều phải làm LệnhP, kết qủa là LệnhP được làm n2-n1+1 lần. Bây giờ tăng: biến1:=Succ(biến1), rồi lại làm lệnh FOR ở dòng {2}, kết qủa lệnhP được làm thêm n2-n1+1 lần nữa. .v.v. Qúa trình trên cứ tiếp tục cho đến khi biến1=m2+1 thì dừng. Lệnh FOR {1} làm m2-m1+1 lần lệnh FOR {2}, còn chính lệnh FOR {2} lại làm n2-n1+1 lần LệnhP. Vì thế lệnhP được làm cả thảy là (m2-m1+1)*(n2-n1+1) lần. Ví dụ 9.7: In hình chữ nhật đặc như dưới đây: Ta thấy mỗi dòng gồm m chữ A, tức là chữ A được in liên tiếp cả thảy m lần, việc này được làm bằng lệnh : For j:=1 to m do write(‘A’); Lệnh Write in m chữ A trên một dòng. In xong, con trỏ vẫn nằm ở cuối dòng đó, vì thế trước khi in dòng tiếp theo, cần phải đưa con trỏ xuống dòng dưới bằng lệnh: Writeln; Tóm lại, muốn in dòng thứ i, cần phải làm hai lệnh: For j:=1 to m do write(‘A’); Writeln; Cả thảy ta phải in n dòng như thế, tức là: For i:=1 to n do In dòng i ; Thay In dòng i bằng hai lệnh nói trên (đặt trong khối begin ... end) , ta có thuật toán để in hình chữ nhật đặc là: For i:=1 to n do begin for j:=1 to m do write(‘A’); Writeln; end; Các bạn hãy viết chương trình cụ thể cho ví dụ này, ở đây m và n là hai số nguyên dương nhập từ bàn phím. 9.1.4. Các ứng dụng khác của lệnh FOR : Lệnh For rất thông dụng, dễ dùng và giải quyết được nhiều bài toán trong khoa học kỹ thuật và trong thực tiễn. Dưới đây chỉ xin nêu hai ứng dụng . Ví dụ 9.8: Tìm các số Fibonaci. Dãy số Fibonaci { 1, 1, 2, 3, 5, 8, 13, 21,... } được nhắc nhiều trong giới khoa học kỹ thuật, nó được xây dựng như sau: U0=1, U1=1 , Uk=Uk-1 + Uk-2 với mọi k= 2, 3, 4, ... Gọi U là số hạng thứ k, Uo và U1 lần lượt là hai số hạng đứng ngay trước U. Ðầu tiên ta gán: Uo:=1; U1:=1; Bước 1: tính U:=Uo+U1 và in U. Lúc này U=2 chính là U2 . Ðể chuẩn bị tính U3, ta cho Uo đóng vai trò của U1 và U1 đóng vai trò của U, tức là gán: Uo:=U1; U1:=U; Kết qủa là Uo=1 và U1=2. Bước 2: tính U:=Uo+U1 và in U. Lúc này U=3 chính là U3 . Ðể chuẩn bị tính U4, ta lại cho Uo đóng vai trò của U1 và U1 đóng vai trò của U, tức là gán: Uo:=U1; U1:=U; Kết qủa là Uo=2 và U1=3. .v.v. Tóm lại các lệnh phải lặp đi lặp lại là: U:=Uo+U1; Uo:=U1; U1:=U; Vì sang bước sau thì gía trị của U sẽ bị thay đổi nên tại mỗi bước ta đều phải in U. chương trình được viết như sau: PROGRAM VIDU98; { In N+1 số Fibonaci đầu tiên } Var N, i, U, Uo, U1 : Integer; Begin Write(‘ Nhập N :’); Readln(N); Uo:=1; U1:=1; Writeln( N+1 , ‘ số Fibonaci đầu tiên là :’ ); Write(Uo:3 , U1:3); For i :=2 to N do begin U:=Uo+U1; Write(U:3); Uo:=U1; U1:=U; end; Readln; End. Chạy Chép file nguồn Ví dụ 9.9: Bài toán tính tiền lãi gửi ngân hàng: Nhập tiền vốn ban đầu, số tháng gửi N và lãi suất hàng tháng. Tính số tiền nhận được sau mỗi tháng gửi biết rằng tiền lãi hàng tháng được gộp vào tiền vốn. Ví dụ, tiền vốn là100, lãi suất tháng là 2%. Sau 1 tháng gửi sẽ có số tiền là: Số tiền=100 + 100*0.02 = 102 Sau 2 tháng gửi sẽ có số tiền là: Số tiền=102 + 102*0.02 = 104.04 Công thức tính tiền thu được sau mỗi tháng gửi là: Số tiền := Tiền vốn + Tiền vốn * Lãi suất Số tiền này lại trở thành tiền vốn của tháng sau, tức là: Tiền vốn := Số tiền; Qúa trình cứ lặp đi lặp lại từ tháng 1 đến tháng N. Chương trình cụ thể như sau: PROGRAM VIDU99; { Tính tiền gửi ngân hàng sau N tháng} Var Tienvon, Laisuat, Sotien : Real; N, i : Byte; Begin Write(‘ Nhập tiền vốn, lãi suất và số tháng gửi : ‘); Readln(Tienvon, Laisuat, N); For i:=1 to N do begin Sotien:= Tienvon + Tienvon*Laisuat; Writeln(‘Số tiền sau ‘, i , ‘ tháng =‘ , Sotien:8:2); Tienvon:=Sotien; end; Readln; End. Chạy Chép file nguồn 9.2. CÂU LỆNH WHILE 9.2.1. Cú pháp, lưu đồ, cách thức hoạt động : Cú pháp: WHILE Ðiềukiện DO LệnhP ; Ý nghĩa : Chừng nào Ðiềukiện còn đúng thì cứ làm LệnhP , cho đến khi Ðiềukiện sai thì không làm LệnhP nữa mà chuyển sang lệnh kế tiếp ở phía dưới. Cách thức hoạt động của WHILE: Bước 1: Nếu Ðiềukiện sai thì chuyển ngay sang lệnh kế tiếp sau LệnhP, ngược lại, nếu Ðiềukiện đúng thì làm LệnhP, rồi quay lại bước 1. Lệnh P được gọi là thân của vòng lặp WHILE. Nếu Ðiềukiện không bao giờ sai thì LệnhP sẽ phải làm hoài, lúc đó ta có vòng lặp vô hạn. Trong trường hợp này, để dừng chương trình, hãy gõ đồng thời hai phím Ctrl và Pause ( viết tắt là ^Pause). Ðể tránh các vòng lặp vô hạn, trong thân của vòng WHILE cần có ít nhất một lệnh có tác dụng làm biến đổi các đại lượng tham gia trong Ðiềukiện để đến một lúc nào đó thì Ðiềukiện sẽ sai và do đó vòng lặp sẽ kết thúc. 9.2.2. Các ví dụ về lệnh While : Ví dụ 9.10 : Nhập số tự nhiên N, dùng lệnh WHILE tính S=N!: PROGRAM VIDU910; { Tinh S=N! bằng lệnh WHILE..} Var N, i : Integer; S : LongInt; Begin Write(‘ Nhập N > 0 : ‘ ); Readln(N); S:=1; i :=1; {9} While i<= N do begin S:=S*i; i:=i+1; {13} end; Writeln(‘ Giai thua = ‘, S); Readln; End. Chạy Chép file nguồn Khởi đầu biến i được gán gía trị 1 (dòng {9}). Trong vòng lặp WHILE, sau mỗi lệnh S:=S*i; biến i được tăng lên 1 đơn vị bằng lệnh i:=i+1; (dòng {13}). Khi i=N+1 thì điều kiện i<=N bị sai và lúc đó vòng lặp kết thúc, kết qủa là lệnh S:=S*i; được thực hiện đúng N lầ? ứng với i=1, 2, 3, ..., N. Trong chương trình trên, nếu không có dòng lệnh {13}: i:=i+1; thì i luôn luôn bằng 1 nên điều kiện i<=N luôn luôn đúng (vì N ≥ 1), và do đó vòng lặp sẽ vô hạn . Sự khác nhau của lệnh WHILE so với FOR là ở chỗ: trong lệnh FOR, biến i được tự động gán gía trị ban đầu và sau mỗi bước lặp được tự động tăng lên, còn trong WHILE thì không, ta phải viết các lệnh đó. Tất cả các bài toán giải quyết được bằng lệnh FOR thì đều giải quyết được bằng lệnh WHILE. Ðặc điểm chung của các bài toán dạng này là số lần lặp của các vòng lặp đã được biết trước. Lệnh WHILE đặc biệt thích hợp với các vòng lặp có số lần lặp chưa biết trước, trong khi lệnh FOR không giải quyết được. Ðây chính là điểm mạnh của lệnh WHILE. Hãy xem ví dụ sau. Ví dụ 9.11: Trở lại bài toán tính tiền gửi ngân hàng có tiền lãi hàng tháng gộp vào vốn (ví dụ 9.9). Câu hỏi bây giờ là: cần gửi tối thiểu là bao nhiêu tháng để có được số tiền ? S cho trước. Giả sử tiền vốn là 100, lãi suất hàng tháng là 2%, số tiền cần có là S=108. Ta tính số tiền có được sau mỗi tháng gửi: Sau 1 tháng gửi: Số tiền=100 + 100*0.02 = 102 Sau 2 tháng gửi: Số tiền=102 + 102*0.02 = 104.04 Sau 3 tháng gửi: Số tiền=104.04 + 104.04*0.02 = 106.1208 Sau 4 tháng gửi: Số tiền=106.1208 + 106.1208*0.02 = 108.2432 Vậy chỉ cần gửi N=4 tháng, số tiền sẽ có là 108.2431. Qúa trình lặp kết thúc khi tới tháng đầu tiên có Số tiền ≥ S. Chương trình như sau: PROGRAM VIDU911; { Tính số tháng gửi ngân hàng để có số tiền S } Var Tienvon, Laisuat, Sotien, S : Real; N : Byte; Begin Write(‘ Nhập tiền vốn, lãi suất và số tiền S cần có: ‘); Readln(Tienvon, Laisuat, S); Sotien:=Tienvon; N:=0; { N là số tháng gửi } While Sotien< S do begin N:=N+1; Sotien:= Tienvon + Tienvon*Laisuat ; Tienvon:=Sotien; end; Writeln(‘ Cần gửi ‘, N , ‘ tháng ‘); Writeln(‘ Số tiền sẽ có = ‘ , Sotien:6:2); Readln; End. Chạy Chép file nguồn Số lần lặp của lệnh: While Sotien < S do . . . không phải do ta ấn định từ trước mà tùy thuộc vào biểu thức Sotien < S là mau bị sai hay chậm bị sai. Số lần lặp ít hay nhiều phụ thuộc vào gía trị S nhỏ hay lớn và vào tốc độ tăng nhanh hay chậm của số tiền. 9.3. CÂU LỆNH REPEAT 9.3.1. Cú pháp, lưu đồ, cách thức hoạt động : Cú pháp: REPEAT LệnhP; UNTIL Ðiềukiện ; Ý nghĩa: Chừng nào Ðiềukiện còn sai thì cứ làm LệnhP, cho đến khi Ðiềukiện đúng thì không làm LệnhP nữa mà chuyển sang lệnh kế tiếp ở phía dưới. Cách thức hoạt động của REPEAT: Bước 1: Làm LệnhP, rồi kiểm tra Ðiềukiện, nếu Ðiềukiện đúng thì chuyển sang lệnh tiếp theo ở phía dưới, ngược lại, nếu Ðiềukiện sai thì quay lại bước 1. LệnhP cũng được gọi là thân của vòng lặp REPEAT, nếu nó gồm nhiều lệnh thì các lệnh đó không cần phải đặt trong khối begin va?end. Nếu Ðiềukiện không bao giờ đúng thì LệnhP sẽ phải làm hoài, lúc đó ta có vòng lặp vô hạn. Trong trường hợp này, muốn dừng chương trình, hãy gõ đồng thời hai phím Ctrl và Pause (^Pause). Ðể tránh các vòng lặp vô hạn, trong thân của lệnh REPEAT cần có ít nhất một lệnh có tác dụng làm biến đổi các đại lượng tham gia trong Ðiềukiện để đến một lúc nào đó thì Ðiềukiện sẽ đúng và do đó vòng lặp sẽ kết thúc. Các vòng lặp có số lần lặp biết trước đều có thể giải được bằng lệnh REPEAT. Ðặc biệt, cũng như lệnh WHILE, lệnh REPEAT rất thích hợp với các vòng lặp có số lần lặp không biết trước 9.3.2. Các ví dụ về lệnh Repeat : Ví dụ 9.12: Ðảm bảo tính hợp lý của dữ liệu nhập từ bàn phím. Khi giải phương trình bậc hai Ax2+Bx+C=0, ta thường giả thiết A? 0, khi tính S=N!, ta thường yêu cầu N? 0. Sự hạn chế phạm vi đối với các dữ liệu nhập sẽ đảm bảo tính hợp lý của chúng và làm giảm bớt các phức tạp khi biện luận. Ðể buộc người sử dụng phải nhập A ≠ 0, nếu nhập A=0 thì bắt nhập lại cho tới khi nhập A ≠ 0 mới thôi, ta dùng cấu trúc : Repeat Write(‘Nhập A khác không : ‘); Readln(A); Until A 0; Ðể đảm bảo chắc chắn nhập N thỏa điều kiện 0<N<20, ta dùng cấu trúc : Repeat Write(‘ Nhập N (0<N<20) : ‘); Readln(N); If (N=20) then write(#7); Until (0<N) and (N<20) ; Lệnh write( chr(7) ) hay write(#7) có công dụng phát ra tiếng kêu bip để cảnh báo người dùng đã nhập dữ liệu sai yêu cầu. Ví dụ 9.13: Tìm bội số chung nhỏ nhất của hai số nguyên dương M và N. Bài toán này có những cách giải khác nhau, dưới đây là một cách đơn giản. Trước hết, hãy xem cách tìm BSCNN của hai số M=5 và N=9. Vì N>M nên ta sẽ tìm trong tập các bội số của N :{ 9, 18, 27, 36, 45, ...} số nhỏ nhất chia hết cho M, đó là số 45. Một cách tổng quát, gọi Max là số lớn nhất của M và N. Ðầu tiên ta gán : BSCNN:=0; Sau đó cứ làm lệnh BSCNN:=BSCNN+Max ; hoài cho đến khi BSCNN chia hết cho cả M và N thì dừng. Trong chương trình ta dùng lệnh repeat để nhập hai số M, N đảm bảo dương. PROGRAM VIDU913; { Tìm BSCNN của M và N } Var M, N, Max, BSCNN : Integer; Begin Repeat Write(‘ Nhập M và N dương :’); Readln(M, N); Until (M>0) and (N>0); If N>M then Max:=N else Max:=M; BSCNN:=0; Repeat BSCNN:=BSCNN + Max; Until (BSCNN mod N=0) and (BSCNN mod M=0) ; Writeln(‘ Bội số chung nhỏ nhất= ‘, BSCNN) ; Readln; End. Chạy Chép file nguồn Ví dụ 9.14: Thiết kế để chạy nhiều lần một chương trình. Trong Turbo Pascal, mỗi lần muốn chạy chương trình ta phải gõ cặp phím Ctrl và F9 (viết tắt là ^F9), điều này sẽ bất tiện nếu cần chạy chương trình nhiều lần ứng với các bộ dữ liệu thử khác nhau. Cấu trúc sau đây cho phép ta chạy chương trình một số lần theo ý muốn: REPEAT { Các lệnh của chương trình} Write(‘ Tiếp tục nữa không (Y/N) ? :’); Readln(Traloi); {5} UNTIL (Traloi =‘N’) or ( Traloi=‘n’); Ở đây, Traloi là một biến kiểu ký tự (Char); Sau khi thực hiện xong {các lệnh của chương trình }, nếu muốn chạy tiếp thì ta gõ phím Y ? , nếu muốn dừng thì gõ N? . Chú ý : lệnh Readln(Traloi); ở dòng thứ {5} có thể thay bằng: Traloi:=Readkey; Hàm Readkey thuộc thư viện CRT cho kết qủa là một ký tự gõ từ bàn phím, nó khác lệnh Readln(Traloi) ở chỗ là khi nhập ký tự ta không cần phải Enter. Chương trình dưới đây cho phép thực hiện một số lần việc : in tam giác cân đặc có chiều cao m (0<m<20) : PROGRAM VIDU914; { In tam giác cân đặc } Uses CRT; Const sao =‘*’; Var k, j, m: integer; Traloi : Char ; Begin REPEAT {9} Clrscr; Repeat {11} Write(‘ Nhập m (0<m<20) : ‘); Readln(m); If (m =20) then write(#7); Until (m>0) and ( m<20) ; {15} Writeln(sao :m); { in đỉnh } { In hai cạnh bên của tam gíac } For k:=1 to m-2 do begin Write(chr(32): m-k-1); { in m-k-1 ký tự trắng} For j:=1 to 2*k+1 do Write(sao); { in 2k+1 dấu *} Writeln; end; For k:=1 to 2*m-1 do Write(sao); {in cạnh đáy} Writeln; Write(‘ Tiếp tục nữa không (Y/N) ?: ‘); Readln( Traloi); UNTIL (Traloi=‘N’) or ( Traloi=‘n’); {28} End. Chạy Chép file nguồn Chương trình 9.14 là một ví dụ về hai câu lệnh Repeat lồng nhau, điều này xảy ra khi thân của một lệnh Repat lại chứa một lệnh Repeat khác: lệnh Repeat thứ nhất, từ dòng {9} đến dòng {28}, chứa lệnh Repeat thứ hai từ dòng {11} đến dòng {15}. 9.3.3. So sánh các lệnh For, While và Repeat: Lệnh For dùng cho các vòng lặp có số lần lặp đã biết trước Lệnh While hay Repeat tổng quát hơn lệnh For, dùng được cho tất cả các loại vòng lặp, nhưng thường dùng cho các vòng lặp có số lần lặp chưa biết trước. Lệnh While và Repeat khác nhau ở điểm sau: lệnh While kiểm tra điều kiện trước, nếu đúng mới thực hiện các lệnh ghi trong thân của nó ( lệnhP ), còn lệnh Repeat thực hiện lệnhP rồi mới kiểm tra điều kiện. Vì thế, lệnh Repeat sẽ thực hiện các lệnh ghi trong thân của nó ít nhất được một lần. Ngoài ra, lệnh While kết thúc khi điều kiện sai, lệnh Repeat kết thúc khi điều kiện đúng. 9.4. CÂU HỎI TRẮC NGHIỆM Câu 1: Cho S và i là biến nguyên. Khi chạy đoạn chương trình : s:=0; for i:=1 to 10 do s := s+i; writeln(s); Kết quả in lên màn hình là : a) s = 11 b) s = 55 c) s = 100 d) s = 101 Câu 2: Cho S, i và N>0 là các biến nguyên. Ðể tính S = N!, chọn câu nào : a) S := 1; For i := 1 to N do S := S * i; b) S := 0; For i := 1 to N do S := S * i; c) S := 1; For i := 1 to N do S := S * N; d) S := 1; For i:= 1 to N do S := S + i; Câu 3: Cho S = 12 + 22 + ... + 1002 . Nhóm lệnh nào tính sai Giá trị của S: a) S:=0; FOR i:=1 TO 100 DO S := S + i*i; b) S:=0; FOR i:=1 TO 100 DO S := S + SQR(i); c) S:=0; FOR i:=100 DOWNTO 1 DO S := S + i*i; d) S:=1; FOR i:=1 TO 100 DO S := S + i*i; Câu 4-Khi chạy chương trình : Var S, i, j : Integer; Begin S := 0; for i:= 1 to 3 do for j:= 1 to 4 do S := S + 1 ; End. Giá trị sau cùng của S là : a) 0 b) 12 c) 3 d) 4 Câu 5: Cho S và i biến kiểu nguyên. Khi chạy đoạn chương trình : S:= 0; i:= 1; while i<= 6 do begin S:= S + i; i:= i + 2; end; Giá trị sau cùng của S là : a) 6 b) 9 c) 11 d) 0 Câu 6: Khi chạy chương trình : Var S, i : Integer; Begin S:= 0; i:= 1; Repeat S:= S + i * i; i:= i + 1; Until i > 4 ; End. Giá trị sau cùng của S là : a) 0 b) 14 c) 16 d) 30 Câu 7: Cho i là biến nguyên. Khi chạy đoạn chương trình : i := 5; Repeat i := i + 1; Until i > 4 ; Giá trị sau cùng của i là : a) 6 b) 4 c) 5 d) 0 Câu 8: Cho m, n, i là các biến nguyên. Khi chạy đoạn chương trình : m:=4; n:=5; i:=5; Repeat i:=i+1; Until (i Mod m = 0) and (i Mod n = 0); Giátrị sau cùng của i là : a) 20 b) 5 c) 4 d) 0 Câu 9: Cho chương trình : Var A : Real; Begin . . . While A = 0 do begin write ('nhap A # 0:'); Readln (A); end; End. Ðể lệnh Readln(A) được thực hiện ít nhất một lần, phải điền vào chỗ ... lệnh nào trong các lệnh dưới đây ? a) A:=0; b) A:=1; c) A:=-1; d) A 0; Câu 10: Giảsử các khai báo biến đều hợp lệ. Ðể tính S = 10!, chọn câu nào : a) S := 1; i := 1; while i<= 10 do S := S * i; i := i + 1; b) S := 1; i := 1; while i<= 10 do i := i + 1; S := S * i; c) S := 0; i := 1; while i<= 10 do begin S := S * i; d) S := 1; i := 1; while i<= 10 do begin S := S * i; i := i + 1; end; i := i + 1; end; 9.5. BÀI TẬP Câu 1) In bảng mã ASCII thành hai cột : Mã Ký tự , yêu cầu hiển thị từng trang một , (mỗi trang 22 dòng) rồi dừng lại chờ ta gõ Enter mới hiện trang kế tiếp, cứ thế cho đến hết. Câu 2) Nhập một số nguyên dương N. Tính : Câu 3) Nhập số n nguyên đảm bảo sao cho n dương. ( Nếu nhập n ? 0 thì chương trình phải bắt nhập laị ), rồi tính : S1 = 12 + 32 + 52 + 72 + ...+ (2n+1)2 Câu 4) Nhập một số nguyên dương n . Tính : S4 = 1.2.3 + 2.3.4 + 3.4.5 +....+ n(n+1)(n+2) Câu 5) Nhập một số nguyên dương n . Tính : Câu *6) Nhập số x thực và số n nguyên ? 1, tính gần đúng ex theo công thức : Câu 7) Nhập n, k nguyên đảm bảo phải dương và k<= n. Tính tổ hợp chập k của n theo công thức : Câu 8) Cho dãy Fibonaci xác đinh như sau: F0=0, F1=1, Fn = Fn-1 + Fn-2 , với n >= 2 Hãy nhập số nguyên N>0 và tính S= F0 + F1 + F2 +...+ Fn . Câu 9) Tìm và in lên màn hình tất cả các số nguyên trong phạm vi từ 10 đến 99 sao cho tích của hai chữ số của nó thì bằng hai lầ? tổng của hai chữ số của nó. Ví dụ : số N=36 có hai chữ số là 3 và 6, và 3*6 = 2*(3+6). Tương tự đối với số 44 . Câu 10) Nhập N nguyên đảm bảo lớn hơn 1. Tính tổng các số lẻ ? N. Ví dụ : nếu N=5 thì tổng S=1+3+5 = 9, nếu N=8 thì S=1+3+5+7=16. Câu 11) Nhập số thực A đảm bảo 0<A< 2, tìm số n nhỏ nhất thỏa mãn : Câu 12) Nhập vào tuổi cha và tuổi con hiện nay đảm bảo sao cho tuổi cha lớn hơn hai lần tuổi con. Hỏi sau bao nhiêu năm nữa thì tuổi cha bằng hai lần tuổi con. Ví dụ tuổi cha là 30, tuổi con là 5, sau 20 năm tuổi cha là 50 sẽ gấp đôi tuổi con 25. Câu 13) Tìm bội số chung nhỏ nhất của hai số nguyên dương m, n nhập từ bàn phím. Suy ra ước số chung lớn nhất của chúng. ( Hd : BSCNN * USCLN = m* n ). Câu 14) Nhập m, n nguyên ( 0 < m, n < 20 ) . In lên màn hình tam giác cân có chiều cao m, và hình chữ nhật có chiều dài n, chiều rộng là m : 10.1. MẢNG MỘT CHIỀU 10.1.1. Mảng và cách khai báo mảng : Khái niệm : Mảng là một tập gồm nhiều phần tử có cùng chung một kiểu dữ liệu. Mỗi phần tử của mảng có một đại lượng xác định vị trí tương đối của phần tử đó so với các phần tử khác trong mảng, gọi là chỉ so? Các yếu tố để xác định một mảng gồm có: Tên mảng Kiểu dữ liệu chung của các phần tử trong mảng Kiểu dữ liệu của chỉ số và phạm vi của chỉ số. Kiểu dữ liệu của các phần tử mảng là mọi kiểu dữ liệu mà một biến có thể có. Tuy nhiên, kiểu dữ liệu của chỉ số thì không được là kiểu thực hay kiểu chuỗi, nó chỉ có thể là kiểu đếm được : nguyên, ký tự, lôgic, liệt kê hay đoạn con. Khai báo mảng một chiều : Mảng một chiều, còn gọi là dãy, hay đơn giản là mảng, có thể khai báo theo một trong hai cách : Cách 1: Khai báo trực tiếp theo cách sau : VAR Tênmảng : Array[m1 . . m2] of Tênkiểudữliệu ; Ở đây m1, m2 là hai hằ?g xác định phạm vi của chỉ số, chúng có chung một kiểu dữ liệu,?và m1? m2. Ví dụ: Cho khai báo dưới đây: Var A : Array[0..10] of Real; Hten: Array[1..5] of String[18]; B: Array[‘a’..’d’] of Integer; Theo khai báo trên, ta có ba mảng: Mảng thứ nhất tên là A, gồm 11 phần tử cùng kiểu Real, ứng với các chỉ số 0, 1, 2, ..., 10, đó là: A[0], A[1], A[2], ..., A[10] Mảng thứ hai tên là HTen gồm 5 phần tử cùng kiểu dữ liệu là String[18] ứng với các chỉ số từ 1 đến 5: Hten[1], Hten[2], Hten[3], Hten[4], Hten[5] Mảng thứ ba tên là B, gồm 4 phần tử cùng kiểu Integer ứng với các chỉ số ‘a’, ‘b’, ‘c’, ‘d’: B[‘a’], B[‘b’], B[‘c’], B[‘d’] Ðể có một hình ảnh về mảng, đối với mảng A, ta hình dung có một dãy nhà một tầng, tên gọi là dãy A, gồm 11 phòng liên tiếp giống hệt nhau được đánh số thứ tự từ 0,1, 2, ..., đến 10 : A0 A1 A2 A3 A4 A5 A6 A7 A8 A9 A10 Tương tự, mảng B cũng giống như dãy nhà B một tầng có 4 phòng được đánh số thứ tự là các chữ a, b, c, d : Ba Bb Bc Bd Cách 2 : Khai báo qua một kiểu dữ liệu mới, gồm hai bước: Bước 1: Ðịnh nghĩa kiểu dữ liệu mảng : TYPE Tênkiểumảng = Array[m1 . . m2] of Tênkiểudữliệu; Bước 2: Khai báo biến có kiểu dữ liệu là kiểu mảng: VAR Tênmảng : Tênkiểumảng ; Ví dụ, đối với các mảng A, B và Hten ở trên ta có thể khai báo theo cách 2, như sau: Type Mang1 = array[0..10] of Real; Mang2 = array[1..5] of String[18]; Mang3 = array[‘a’..’d’] of Integer; Var A : Mang1; Hten: Mang2; B: Mang3; Khai báo mảng có gán trị ban đầu: Pascal cho phép vừa khai báo mảng vừa gán gía trị ban đầu cho các phần tử mảng, chẳng hạn như dưới đây: Const X : array[1..5] of Integer = (12, 14, 16, 18, 20) ; Khi đó X là một mảng gồm 5 phần tử cùng kiểu nguyên và có giá trị X[1]=12, X[2]=14, X[3]=16, X?4]=18, X[5]=20. Mặc dù từ khóa ở đây là Const song X lại được dùng như là một biến mảng, tức là các phần tử của X có thể thay đổi gía trị được. Ví dụ, trong chương trình ta có thể gán: X[1]:= 2; X[2]:=5+20; 10.1.2. Truy xuất các phần tử mảng: Các xử lý trên mảng được quy về xử lý từng phần tử mảng. Ðể xác định một phần tử của mảng, ta dùng cách viết : Tênmảng[ chỉ số của phầ? tử ] Ví du : có thể gán : A[0]:= 15.8; A[1]:= 2*A[0]; Hten[3]:= ‘Nguyen Thi Loan’; B[‘a’]:=100; Chỉ số của một phần tử có thể là một biến, một hằng, hay một biểu thức. Ví dụ, cho i là biến kiểu nguyên, khi đó ta có thể dùng các lệnh: i:=6; A[i]:=100.25; Hai lệnh trên tương đương với một lệnh: A[6]:=100.25; Nếu biến i có giá trị là 6 thì lệnh : A[ i div 2 +1] := 4.5; tương đương với lệnh: A[4]:=4.5; vì biểu thức i div 2 +1 có gía trị là 4. Khi nhập dữ liệu cho các phần tử của một mảng , ta có thể dùng câu lệnh For, While hay Repeat. Ví dụ, nhập dữ liệu cho các phần tử của mảng A: For i:=0 to 10 do begin Write(‘Nhập phần tử thứ ‘ , i , ‘: ‘); Readln(A[i]); end; hoặc (dùng While) : i:=0; While i<= 10 do begin Write(‘Nhap phần tử thứ ‘, i, ‘: ‘); Readln(A[i]); i:=i+1; end; Tương tự để nhập dữ liệu cho các phần tử của mảng B, ta viết: For ch:=‘a’ to ‘d’ do begin Write(‘Nhap phần tử thứ ‘, ch, ‘: ‘); Readln(B[ch]); end; Ðể in các gía trị của mảng A lên màn hình, ta viết : For i:=0 to 10 do Write(A[i]:6:2); Các gía trị của mảng A sẽ được in liên tiếp nhau trên cùng một dòng. Còn nếu muốn in mỗi phần tử trên một dòng, ta thay lệnh Write bằ?g Writeln. Tương tự, mảng B được in lên màn hình bằng lệnh : For ch:=‘a’ to ‘d’ do Write(B[ch]); Chú ý : Turbo Pascal cho phép gán một mảng này cho một mảng khác. Nếu X, Y là hai biến mảng cùng một kiểu mảng thì lệnh: X := Y; có nghĩa là lấy gía trị của từng phần tử củ

Các file đính kèm theo tài liệu này:

  • pdfgiao_trinh_mon_thuat_toan.pdf
Tài liệu liên quan