Tải bản đầy đủ (.docx) (14 trang)

De HSG Hay20162017 71

Bạn đang xem bản rút gọn của tài liệu. Xem và tải ngay bản đầy đủ của tài liệu tại đây (186.82 KB, 14 trang )

<span class='text_page_counter'>(1)</span>MẢNG MỘT CHIỀU 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ỉ số 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ên kiểu dữ liệu ; Ở đây m1, m2 là hai hằng 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ên kiểu mảng = Array[m1 . . m2] of Tên kiểu dữ 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;.

<span class='text_page_counter'>(2)</span> 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; 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ần 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);.

<span class='text_page_counter'>(3)</span> 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ủa mảng Y gán cho phần tử tương ứng trong mảng X. Ví dụ, cho khai báo: Var X, Y : Array[1..10] of Real; Khi đó, lệnh: X := Y; tương đương với lệnh : For i:=1 to 10 do X[i] :=Y[i]; 3. Các bài toán cơ bản về mảng : Ví dụ 10.1: Ðếm số lần xuất hiện của gía trị x trong dãy A1, A2, ..., An . Ví dụ gía trị x=6 xuất hiện 3 lần trong dãy 6 7 1 2 6 0 6 1. Ta dùng biến Dem kiểu nguyên để đếm số lần xuất hiện của x. Ðầu tiên ta gán Dem:=0, sau đó duyệt từng phần tử A1, A2, ..., An, mỗi khi có một phần tử bằng x thì tăng biến Dem lên một đơn vị. Kết qủa là biến Dem có gía trị đúng bằng số phần tử bằng x. Hai lệnh chính của thuật toán là: Dem:=0; For i:=1 to N do If A[i]=x then Dem:=Dem+1; Ví dụ, đếm trong dãy số A có bao nhiêu số 0, ta viết: Dem:=0; For i:=1 to N do if A[i]=0 then Dem:=Dem+1; Writeln(‘ Có ‘, Dem , ‘ số không ‘); Nhận xét: Ðẳng thức A[i]=x ( hay A[i]=0 ) là điều kiện để biến Dem được tăng thêm 1, vậy bài toán trên có thể mở rộng là: hãy đếm số phần tử của mảng A thỏa mãn một điều kiện cho trước. Trong lệnh For ở trên, khi thay đẳng thức A[i]=x bằng A[i] thỏa điều kiện , ta được thuật toán tổng quát hơn : Dem:=0; For i:=1 to N do If A[i] thỏa điều kiện then Dem:=Dem+1; Chương trình sau nhập một mảng A có N phần tử, in mảng A lên màn hình, và đếm xem mảng A có bao nhiêu số dương : PROGRAM VIDU101; { Ðếm số dương trong mảng} Type Kmang = Array[1..20] of Real; Var A: Kmang; i, N, Dem : Integer; Begin Repeat Write(‘ Nhập số phần tử N : ‘); Readln(N); Until (N>0) and ( N<21); { nhập mảng } For i:=1 to N do begin Write(‘Nhập A[‘ , i , ‘ ]: ‘); Readln( A[i] ); end; { In mảng A}.

<span class='text_page_counter'>(4)</span> Writeln(‘ Mảng A là : ’); For i:=1 to N do Write(A[i]:3:0); Writeln; { đếm số dương } Dem:=0; For i:=1 to N do If A[i]>0 then Dem:=Dem+1; Writeln(‘ Số số dương = ‘ , Dem ); Readln; End. Ví dụ 10.2: Tìm số lớn nhất của dãy A1, A2, ..., An. Trong bài 8, ta đã chỉ ra cách tìm số lớn nhất của hai số, của ba số. Có thể mở rộng thuật toán đó để tìm số lớn nhất của n số : Gọi Max là biến chứa số lớn nhất phải tìm, thế thì : Bước 1: Gán Max:=A[1]; Bước 2: Nếu Max<A[2] thì gán Max:=A[2]; Bước 3: Nếu Max<A[3] thì gán Max:=A[3]; ... Bước n: Nếu Max<A[n] thì gán Max:=A[n]; Khởi đầu, Max được gán giá trị A[1]. Sang bước 2, Max được so sánh với A[2] để chọn ra số lớn nhất giữa A[1], A[2] và lưu vào biến Max. Sang bước 3, Max được tiếp tục so sánh với A[3] để tìm ra số lớn nhất giữa A[1], A[2], A[3], .v.v. Kết qủa, sau bước n, biến Max sẽ chứa số lớn nhất của dãy A[1], A[2], ..., A[n]. Quá trình trên được mô tả bằng hai lệnh: Max:=A[1]; For i:=2 to n do if Max<A[i] then Max:=A[i]; Nhận xét: Trong lệnh For trên, biến i chạy bắt đầu từ 2, nhưng kết qủa vẫn đúng nếu cho i chạy bắt đầu từ 1. Không nhất thiết phải gán giá trị ban đầu cho Max là A[1], mà có thể gán cho Max một phần tử tùy ý trong mảng, ví dụ phần tử A[n] chẳng hạn, nhưng khi đó biến i trong lệnh For phải chạy bắt đầu từ 1. Ví dụ 10.3: Bài toán sắp xếp mảng tăng dần (hay giảm dần) Cho dãy A[1], A[2],..., A[n], nói rằng A là một dãy tăng nếu A[1] <= A[2]<= ...<= A[n], tương tự, A là dãy giảm nếu A[1] >=A[2] >= ... >=A[n]. Dãy đồng nhất A[1]=A[2]= ... =A[n] là trường hợp đặc biệt, vừa là dãy tăng, vừa là dãy giảm. Ví dụ: Dãy 1 3 3 5 5 6 6 6 là dãy tăng Dãy 9 9 8 5 5 4 0 0 là dãy giảm Dãy 1 3 3 2 5 4 6 6 là dãy không tăng không giảm. Bài toán đặt ra là: cho một dãy A[1], A[2], ..., A[n] bất kỳ, hãy thực hiện các hoán đổi các gía trị của các phần tử trong mảng A để A lập thành một dãy tăng. Ví dụ, cho dãy A có 5 phần tử A[1]=9, A[2]=7, A[3]=5, A[4]=8, và A[5]= 2, cần thực hiện các hoán đổi như thế nào để có A[1]=2, A[2]=5, A[3]=7, A[4]=8 và A[5]=9. Có những phương pháp sắp xếp mảng khác nhau, ở đây chỉ xin giới thiệu một phương pháp, tuy chưa phải là hay nhưng đơn giản và dễ hiểu cho những người mới lập trình, đó là phương pháp lựa chọn trực tiếp (Straight selection sort). Ý tưởng của phương pháp là như sau: Bước 1: Tìm số nhỏ nhất trong các phần tử A[1], A[2],.., A[n] và để vào vị trí đầu tiên A[1]. Bước 2: Tìm số nhỏ nhất trong các phần tử A[2], A[3],.., A[n] và để vào vị trí thứ hai A[2]. .v.v. Bước n-1: Tìm số nhỏ nhất trong hai phần tử A[n-1], A[n] và để vào vị trí n-1. Sau bước này thì A[n] sẽ là gía trị lớn nhất. Chẳng hạn, xét dãy A có 4 phần tử: {5,3,4,1}: Bước 1: Nếu A[1]>A[2] thì đổi A[1] với A[2], được: {3,5,4,1} Nếu A[1]>A[3] thì đổi A[1] với A[3]: không đổi.

<span class='text_page_counter'>(5)</span> Nếu A[1]>A[4] thì đổi A[1] với A[4], được: {1,5,4,3} Bước 2: Nếu A[2]>A[3] thì đổi A[2] với A[3], được: {1,4,5,3} Nếu A[2]>A[4] thì đổi A[2] với A[4], được: {1,3,5,4} Bước 3: Nếu A[3]>A[4] thì đổi A[3] với A[4], được: {1,3,4,5} Sau ba bước, dãy A đã được sắp xếp xong. Tại bước thứ i (i chạy từ 1 đến 3 ), ta phải so sánh A[i] lần lượt với A[j] (j chạy từ i+1 đến 4), nếu A[i]>A[j] thì hoán đổi các gía trị của A[i] và A[j], nói cho gọn là đổi chỗ A[i] với A[j]. Qúa trình trên được thể hiện bằng hai vòng lặp For : For i:=1 to 3 do For j:=i+1 to 4 do if A[i]>A[j] then Ðổi chỗ A[i] và A[j] ; Mảng A ở trên chỉ có 4 phần tử, trong trường hợp tổng quát khi mảng A có N phần tử thì lệnh For thứ nhất sẽ có biến i chạy từ 1 đến N-1, và lệnh For thứ hai sẽ có biến j chạy từ i+1 đến N, tức là : For i:=1 to N-1 do For j:=i+1 to N do if A[i]>A[j] then Ðổi chỗ A[i] và A[j] ; Việc đổi chỗ các gía trị trong A[i] và A[j] được tiến hành bằng cách dùng một biến Z trung gian cùng kiểu dữ liệu với A[i] và A[j]. Ðầu tiên gởi tạm gía trị của A[i] vào biến Z, sau đó đưa gía trị của A[j] vào A[i], và cuối cùng đưa gía trị trong Z vào A[j], tức là phải làm ba lệnh : Z:=A[i]; A[i]:=A[j]; A[j]:=Z; Tóm lại, thuật toán sắp xếp dãy A tăng được viết như sau: For i:=1 to N-1 do For j:=i+1 to N do if A[i]>A[j] then begin { Ðổi chỗ A[i] và A[j] } Z:=A[i]; A[i]:=A[j]; A[j]:=Z; end; Trong đó N là số phần tử của dãy A còn Z là một biến trung gian có cùng kiểu dữ liệu với các phần tử của mảng A. Chương trình dưới đây tìm số lớn nhất của mảng A và sắp dãy A tăng dần: PROGRAM VIDU103; { Tìm Max và sắp dãy A tăng dần } Uses CRT; Type Kmang = array[1..20] of Real; Var i, j, N : Integer; A: Kmang; z, Max : Real; Begin Clrscr; Repeat Write(‘ Nhập số phần tử N : ‘); Readln(N); Until (N>0) and ( N<21); For i:=1 to N do { nhập mảng } begin Write(‘Nhập A[‘, i, ‘]: ‘);.

<span class='text_page_counter'>(6)</span> Readln(A[i]); end; { Tìm số lớn nhất } Max :=A[1]; For i :=1 to N do if Max< A[i] then Max:=A[i]; Writeln(‘ Số lớn nhất là: ’ , Max : 4:1); { sắp xếp dãy tăng } For i:=1 to N-1 do For j:=i+1 to N do If A[i]>A[j] then {23} begin { đổi chỗ A[i] và A[j] } z:=A[i]; A[i]:=A[j]; A[j]:=z; end; Writeln(‘ Dãy đã?sắp tăng là : ‘); For i:=1 to N do Write(A[i]:3:0); Readln; End. Chú ý 1: Muốn sắp dãy A giảm dần thì trong chương trình trên chỉ cần thay dòng {23}: If A[i] > A[j] then ... bằng dòng : If A[i] < A[j] then ... Tức là thay dấu lớn hơn > bằng dấu nhỏ hơn < . Chú ý 2 : Sắp xếp một bộ phận của dãy. Gọi m và h là hai số nguyên sao cho 1<= m< h<= N, khi đó A[m], A[m+1], ..., A[h] là một dãy con của dãy A. Muốn sắp dãy con A[m], A[m+1], ..., A[h] tăng (hay giảm) mà không làm ảnh hưởng đến các phần còn lại của dãy A, ta dùng lệnh sau: For i:= m to h-1 do For j:=i+1 to h do if A[i]>A[j] then begin { Ðổi chỗ A[i] và A[j] } Z:=A[i]; A[i]:=A[j]; A[j]:=Z; end; Ví dụ 10.4: Kiểm tra mảng có thỏa một tính chất không. Ta thường gặp bài toán kiểm tra xem mọi phần tử của mảng A có thỏa mãn một điều kiện không, ví dụ mảng A có phải là dãy tăng không, có phải là dãy đối xứng không, có phải là một cấp số cộng không, ... Mảng A thỏa tính chất đang xét nếu mọi phần tử của nó thỏa một điều kiện xác định nào đó, ngược lại, mảng A không thỏa tính chất đang xét nếu có một phần tử của nó không thỏa điều kiện này. Hai trạng thái thỏa hay không thỏa được thể hiện bằng hai gía trị TRUE hay FALSE của một biến Kiemtra kiểu lôgic. Ðầu tiên ta gán giả định Kiemtra:= TRUE, sau đó ta xét từng phần tử của A, chỉ cần có một phần tử không thỏa điều kiện thì gán ngay Kiemtra:=FALSE . Vậy hai lệnh cần dùng là: Kiemtra:=TRUE; For i:=1 to N do if A[i] không thỏa điều kiện then Kiemtra:= FALSE; Việc xác định điều kiện là tùy từng bài toán cụ thể. Ví dụ: Kiểm tra xem A có phải là một dãy đối xứng không ? Dãy 1 3 5 4 5 3 1 là đối xứng. Dãy 1 3 5 4 2 3 1 là không đối xứng vì A[3] khác A[5]..

<span class='text_page_counter'>(7)</span> Như vậy, dãy N phần tử A1, A2, ..., An là đối xứng nếu A1=An, A2=An-1, ..., An=A1, tức Ai = An-i+1 với mọi i=1, 2, ..., n. Ðẳng thức : Ai = An-i+1 chính là điều kiện mà mọi phần tử của dãy A phải thỏa để A là một dãy đối xứng. Giả thiết biến Kiemtra đã được khai báo kiểu Boolean. Trong chương trình ta dùng các lệnh sau: Kiemtra:=TRUE; For i:=1 to N do if A[i]<>A[N-i+1] then Kiemtra:=FALSE; If Kiemtra=TRUE then writeln(‘ Dãy A đối xứng’) else Writeln( ‘Dãy A không đối xứng ‘); Trong thuật toán trên, lệnh For có thể thay bằng lệnh While, tốc độ sẽ nhanh hơn song cũng khó hiểu hơn: Kiemtra:=TRUE; i:=1; While ( i <=N ) and ( Kiemtra=TRUE) do if A[i]<>A[N-i+1] then Kiemtra:=FALSE else i:=i+1; If Kiemtra=TRUE then writeln(‘ Dãy A đối xứng’) else Writeln( ‘Dãy A không đối xứng ‘); Bạn đọc hãy viết chương trình cho ví dụ này. Chú ý Câu lệnh : If Kiemtra=TRUE then writeln(‘ Dãy A đối xứng’) else Writeln( ‘Dãy A không đối xứng ‘); hoàn toàn tương đương với lệnh : If Kiemtra then writeln(‘ Dãy A đối xứng’) else Writeln( ‘Dãy A không đối xứng ‘);.

<span class='text_page_counter'>(8)</span> MẢNG HAI CHIỀU (MA TRẬN) 1. Khai báo mảng hai chiều: Mảng hai chiều, còn gọi là ma trận, là sự mở rộng trực tiếp của mảng một chiều. Ta cũng có hai cách khai báo. Cách 1: Khai báo trực tiếp : VAR Tênmảng : Array[n1..n2 , m1..m2] of Tên kiểu dữ liệu; Trong đó n1, n2 là các hằng có cùng kiểu dữ liệu và n1<=n2, chúng xác định phạm vi của chỉ số thứ nhất, gọi là chỉ số dòng. Tương tự m1, m2 là các hằng có cùng kiểu dữ liệu và m1<=m2, chúng xác định phạm vi của chỉ số thứ hai, gọi là chỉ số cột. Giống như mảng một chiều, kiểu dữ liệu của các chỉ số chỉ có thể là kiểu đếm được: nguyên, ký tự, lô gic, liệt kê hay đoạn con, không được là kiểu thực hay chuỗi. Ví dụ, cho khai báo : Var X : array[1..2, 1..3] of Real; Y : array[‘a’..’c’ , 1..3] of String[15]; Kết quả ta nhận được hai mảng hai chiều: Mảng X gồm 6 phần tử cùng kiểu dữ liệu thực: X[1,1], X[1,2], X[1,3] X[2,1], X[2,2], X[2,3] Mảng Y gồm 9 phần tử cùng kiểu chuỗi String[15] : Y[‘a’,1], Y[‘a’,2], Y[‘a’, 3] Y[‘b’,1], Y[‘b’,2], Y[‘b’, 3] Y[‘c’,1], Y[‘c’,2], Y[‘c’, 3] Có thể ví X là một nhà hai tầng, mỗi tầng có ba phòng giống nhau. Các tầng được đánh số từ 1 đến 2, trong mỗi tầng, các phòng được đánh số từ 1 đến 3. Tương tự, Y là một nhà ba tầng, các tầng được đánh số lần lượt là ‘a’, ‘b’, ‘c’, mỗi tầng có ba phòng được đánh số lần lượt là 1, 2, 3. Cách 2: Biến mảng được khai báo thông qua một kiểu mảng đã được định nghĩa trước đó bằng từ khóa TYPE, tức là: TYPE Tênkiểumảng= Array[n1..n2 , m1..m2] of Tênkiểudliệu; VAR Tênmảng : Tênkiểumảng ; Ví dụ: Hai mảng X và Y nói trên có thể được khai báo theo hai bước sau: Type Kmang1 = array[1..2, 1..3] of Real; Kmang2 = array[‘a’..’c’ , 1..3] of String[15]; Var X : Kmang1; Y : Kmang2; Chú ý: - Có thể xem mảng hai chiề? là mảng một chiều mà mỗi phần tử của nó lại là một mảng một chiều. Hai mảng X, Y nói trên có thể khai báo như sau: Type Kmang1 = array[1..2] of array[1..3] of Real; Kmang2 = array[‘a’..’c’] of array[1..3] of String[15]; Var X : Kmang1; Y : Kmang2; Hiểu theo cách này thì X là một mảng gồm hai phần tử X[1] và X[2] mà mỗi phần tử này lại là một mảng gồm 3 phần tử : X[1] là mảng có 3 phần tử kiểu thực X[1][1], X[1][2], X[1][3] X[2] là mảng có 3 phần tử kiểu thực X[2][1], X[2][2], X[2][3] Ðiều tương tự cũng áp dụng cho biến mảng Y. Hai cách viết X[i][j] và X[i,j] cùng chỉ một phần tử..

<span class='text_page_counter'>(9)</span> Khai báo và gán giá trị ban đầu: Có thể khai báo và gán giá trị ngay cho một mảng hai chiều, chẳng hạn: Type Kmang1 = array[1..2, 1..3] of Real; Const X : Kmang1 = ( (1.5, 2.5, 3.5), (5.0, 6.5, 7.0) ); Khi đó X là một mảng hai chiều có 6 phần tử cùng kiểu thực và có giá trị là: X[1,1]=1.5, X[1,2]=2.5, X[1,3]=3.5 X[2,1]=5.0, X[2,2]=6.5, X[2,3]=7.0 Cần nhấn mạnh rằng mặc dù từ khóa ở đây là Const song X và các phần tử của X có thể dùng như các biến, tức là các phần tử của X có thể thay đổi giá trị được. 2. Các thao tác trên ma trận : Ðể xác định một phần tử trong mảng hai chiề?, ta viết: Tênbiếnmảng[chỉ số 1, chỉ số 2] Ví dụ: X[1,1]:=12.5; X[2,1]:=X[1,1]+15; Y[‘a’,1]:=‘Tran Thi Mai’; Ðể nhập dữ liệu cho một mảng hai chiều, ta phải dùng hai vòng lặp duyệt theo hai chỉ số, chẳng hạn muốn nhập dữ liệu cho mảng X, ta viết: For i:=1 to 2 do For j:=1 to 3 do begin Write(‘nhập phần tử hàng ‘, i, ‘ cột ‘, j , ‘: ‘); Readln(X[i, j]); end; Tương tự, lệnh nhập dữ liệu cho mảng Y được viết là: For ch:=‘a’ to ‘c’ do For j:=1 to 3 do begin Write(‘nhập phần tử hàng ‘, ch , ‘ cột ‘, j , ‘: ‘); Readln(X[ch, j]); end; trong đó ch là biến kiểu ký tự, còn i và j là các biến nguyên. Ðể in mảng X lên màn hình, trình bày giống như cách viết ma trận, mỗi hàng in trên một dòng, ta dùng lệnh : For i:=1 to 2 do begin For j:=1 to 3 do write(X[i, j]:3:1); { in hàng thứ i} Writeln; { xuống dòng, chuẩn bị in hàng tiếp theo } end; 3. Các ví dụ về ma trận : Vì ma trận là mảng một chiều của các mảng một chiều nên nhiều bài toán về mảng được mở rộng tự nhiên cho ma trận. Ví dụ 10.6: Tính tổng của hai ma trận Nhập vào hai ma trận A, B cấp NxM. Tính ma trận C là tổng của hai ma trận A và B, in ma trận C lên màn hình. Công thức tính các phần tử của ma trận C= A+B : C[i,j ] = A[i, j] + B[i, j] với i=1,..., N, và j=1,..., M Chương trình như sau: PROGRAM VIDU106;.

<span class='text_page_counter'>(10)</span> { Tính tổng hai ma trận } Uses CRT; Var A, B, C : Array[1..10, 1..10] of Real; i, j , N, M : Integer; Begin Clrscr; Repeat Write(‘Nhập số hàng N, số cột M : ‘); Readln(N, M); Until ( N>0) and ( N<11) and ( M>0) and (M<11); For i:=1 to N do For j:=1 to M do begin Write(‘Nhập A[‘ , i, ‘,’ , j , ‘]: ‘); Readln(A[i,j]); end; { nhập B và tính C luôn} For i:=1 to N do For j:=1 to M do begin Write(‘Nhập B[‘ , i, ‘,’ , j , ‘]: ‘); Readln(B[i,j]); C[i, j]:=A[i, j] + B[i, j]; end; { In ma trân A lên màn hình } Writeln(‘ Ma tran A la :’); For i:=1 to N do begin For j:=1 to M do write(A[i, j]:3:0); Writeln; end; { In ma trân B lên màn hình } Writeln(‘ Ma tran B la :’); For i:=1 to N do begin For j:=1 to M do write(B[i, j]:3:0); Writeln; end; { In ma trân C lên màn hình } Writeln(‘ Ma tran C la :’); For i:=1 to N do begin For j:=1 to M do write(C[i, j]:3:0); Writeln; end; Readln; End. Ví dụ 10.7: Tìm số lớn nhất (số nhỏ nhất) trong ma trận A: Giả sử A là ma trận N hàng, M cột, và Max là biến chứa số lớn nhất phải tìm. Khởi đầ u ta gán A[1,1] cho Max, sau đó duyệt tất cả các phần tử của ma trận, nếu phần tử nào lớn hơn Max thì lưu nó vào Max, tức là: Max:=A[1,1];.

<span class='text_page_counter'>(11)</span> For i:=1 to N do For j:=1 to M do if Max< A[i, j] then Max:=A[i, j]; Writeln(‘ Số lớn nhất là ’, Max); Ví dụ 10.8 : Tìm số lớn nhất (hay số nhỏ nhất) trong từng hàng (hay từng cột) của ma trận A: Hàng i ( 1<= i<= N ) của ma trận A có dạng : A[i,1], A[i,2], ..., A[i,M] Nếu xem i là cố định thì đó là mảng một chiều có M phần tử, nên số lớn nhất của hàng i được tìm bằng các lệnh: Max:=A[i, 1]; For j:=1 to M do if Max< A[i, j] then Max:=A[i, j]; Writeln(‘Sln của hàng ‘, i, ‘ là: ‘, Max) ; Vì có cả thảy N hàng nên công việc trên phải làm N lần ứng với i=1, 2, ..., N, tức là: For i:=1 to N do begin { tìm số lớn nhất của hàng i } Max:=A[i, 1]; For j:=1 to M do if Max< A[i, j] then Max:=A[i, j]; Writeln(‘Sln của hàng ‘, i, ‘ là: ‘, Max) ; end; Ví dụ 10.9: Kiểm tra ma trận vuông A có đối xứng không ?. Ma trận vuông A gọi là đối xứng nếu nó không thay đổi khi ta đổi cột thành hàng và đổi hàng thành cột. Nói cách khác, ma trận A là đối xứng khi và chỉ khi A[i,j] =A[j,i] với mọi i=1, ..., N và với mọi j=1, .., N. Ví dụ, cho hai ma trận dưới đâỵ:. thì A là đối xứng, còn B không đối xứng vì B[1,2] <> B[2,1]. Chỉ cần có một cặp i, j sao cho A[i,j]<>A[j,i] thì A là ma trận không đối xứng. Vậy các lệnh kiểm tra tính đối xứng của ma trận A là: Kiemtra := TRUE; For i:=1 to N do For j:=1 to N do if A[i, j]<>A[j, i] then Kiemtra:=FALSE ; If Kiemtra=TRUE then writeln(‘ Ðối xứng ‘) else writeln(‘ Không đối xứng ‘); Trong đó Kiemtra là một biến kiểu lôgic. Nhận xét rằng hai lệnh For ở trên quét qua tất cả các phần tử của ma trận nên có hơn nửa số lần lặp là thừa. Thật vậy, đường chéo chính chia ma trận ra làm hai phần: nửa trái và nửa phải. Các phần tử trên đường chéo chính thì đối xứng với chính nó nên không cần phải kiểm tra. Nếu mỗi phầ? tử ở nửa bên trái đều bằng phần tử đối xứng với nó ở nửa bên phải thì ma trận rõ ràng là đối xứng. Vì vậy chỉ cần duyệt kiểm tra các phần tử ở nửa bên trái đường chéo chính là đủ (vùng tam giác).. Thuật toán tốt hơn được đề nghị là : Kiemtra := TRUE; For i:=2 to N do.

<span class='text_page_counter'>(12)</span> For j:=1 to i-1 do if A[i, j]<>A[j, i] then Kiemtra:=FALSE ; If Kiemtra=TRUE then writeln(‘ Ðối xứng ‘) else writeln(‘ Không đối xứng ‘); Hai câu lệnh For trên vẫn còn một nhược điểm là: khi xảy ra A[i,j]<>A[j, i] rồi, lẽ ra có thể dừng lại và kết luận không đối xứng ngay thì các vòng For vẫn tiếp tục, i chạy đến N và j đến i-1. Sử dụng câu lệnh While sẽ khắc phục được nhược điểm này. Chỉ cần xảy ra A[i,j]<>A[j,i] một lần là biến Kiemtra được gán ngay gía trị FALSE, khi đó điều kiện Kiemtra=TRUE bị sai và cả hai vòng lặp đều kết thúc . Kiemtra:=TRUE; i:=2; While (Kiemtra=TRUE) and (i<= N) do begin j:=1; While ( Kiemtra=TRUE) and ( j<=i-1) do if A[i, j] <> A[j, i] then Kiemtra:=FALSE else j:=j+1; i:=i+1; end; If Kiemtra=TRUE then writeln(‘ Ðối xứng ‘) else writeln(‘ Không đối xứng ‘); Chương trình dưới đây thực hiện các công việc sau: Nhập vào ma trận vuông A cấp N và in ma trận A lên màn hình Ðếm trong ma trận A có bao nhiêu số 0 Tìm số lớn nhất trong A Tìm số nhỏ nhất trong từng hàng của A Kiểm tra xem A có phải là ma trận đối xứng không. PROGRAM VIDU109; Uses CRT; Type Matran = Array[1..10, 1..10] of Real; Var A : Matran; i, j , N, Dem : Integer; Max, Min : Real; Kiemtra: Boolean; Begin Clrscr; Repeat Write(‘Nhập cấp N : ‘); Readln(N); Until ( N>0) and ( N<11) ; For i:=1 to N do For j:=1 to N do begin Write(‘Nhập A[‘, i, ‘,’ , j , ‘]: ‘); Readln(A[i,j]); end; { In ma trân A lên màn hình } Writeln(‘ Ma tran A la : ’);.

<span class='text_page_counter'>(13)</span> For i:=1 to N do begin For j:=1 to N do write(A[i, j]: 3 :0); Writeln; end; { Ðếm số số 0 } Dem:=0; For i:=1 to N do For j:=1 to N do if A[i, j]=0 then Inc(Dem); Writeln(‘ Có ‘, Dem, ‘ số không’); { Tìm số lớn nhất của ma trận } Max:=A[1,1]; For i:=1 to N do For j:=1 to N do if Max < A[i,j] then Max:=A[i,j]; Writeln(‘ Số lớn nhất của ma trận= ‘, Max : 4:1); { Tìm số nhỏ nhất trong từng hàng của ma trận } For i:=1 to N do begin Min:=A[i,1]; For j:=1 to N do if Min > A[i,j] then Min:=A[i,j]; Writeln(‘ Số nhỏ nhất của hàng ‘, i , ‘ là: ‘, Min : 4:1); end; { Kiểm tra ma trận có đối xứng không} Kiemtra:=True; For i:=1 to N do For j:=1 to i-1 do if A[i ,j]<>A[j ,i] then Kiemtra:=False; If Kiemtra=True then Writeln(‘ Ðối xứng’) else Writeln(‘ Không đối xứng’) ; Readln; End..

<span class='text_page_counter'>(14)</span> BÀI TẬP Câu 1) Nhập số tự nhiên n và một dãy số thực x1, x2, ..., xn. Tìm số lớn nhất và số nhỏ nhất của dãy Ðếm trong dãy có bao nhiêu số dương, bao nhiêu số âm, bao nhiêu số 0 ? Loại nào nhiều nhất ? Câu 2) Nhập một dãy số nguyên x1, x2, ..., xn. In riêng các số chẵn và các số lẻ, mỗi loại trên một dòng. Câu 3) Nhập một số nguyên dương N, xây dựng dãy số nguyên x 0, x1, ..., xn trong đó xi là số Fibonaci thứ i: x 0=1, x1=1, xi =xi-1 + xi-2 với mọi i > 2. In dãy x lên màn hình. Câu 4) Nhập hai dãy số bất kỳ x1, x2,..., xn và y1, y2,..., yn. Xây dựng dãy thứ ba z1, z2, .., zn là tổng của hai dãy trên (zi= xi + yi), in ba dãy lên màn hình, mỗi dãy trên một dòng. Câu 5) Nhập một dãy số bất kỳ x 1, x2,..., xn , cho biết dãy thuộc loại nào: tăng, giảm hay không tăng, không giảm ? Câu 6) Nhập một dãy số nguyên dương x1, x2,..., xn . Tách dãy x thành hai dãy: dãy A gồm các số chẵn, dãy B gồm các số lẻ, sắp xếp dãy A tăng dần, dãy B giảm dần, in hai dãy A và B trên hai dòng khác nhau. Nối hai dãy A và B theo thứ tự đó thành một dãy duy nhất và gán trở lại vào dãy x, in dãy x. Ví dụ nhập dãy x={ 5, 7, 0, 2, 1, 6, 4, 9 } thì dãy A={ 0, 2, 4, 6}, dãy B={ 9, 7, 5, 1}, và x={ 0, 2, 4, 6, 9, 7, 5, 1}. Câu 7) Nhập hai số m, n và hai ma trận Am,n và Bm,n . In các ma trận A, B, C=A+2B và D=A-B lên màn hình. Câu 8) Nhập và in ma trận Am,n . Tìm số nhỏ nhất và số lớn nhất trong ma trận . Tính tổng của tất cả các phần tử trong ma trận. Ðếm trong ma trận có bao nhiêu số dương, bao nhiêu số 0, bao nhiêu số âm. Câu 9) Nhập và in ma trận Am,n Tìm và in số lớn nhất trong từng hàng của ma trận. Tìm và in số lớn nhất trong từng cột của ma trận. Tìm và in số nhỏ nhất trên đường chéo chính của ma trận. Câu 10) Nhập và in ma trận vuông An,n . A có phải là ma trận đối xứng không A có phải là ma trận đơn vị không? (A là đối xứng nếu Aij=Aji với mọi i,j =1,..., n. A là ma trận đơn vị nếu tất cả các phần tử trên đường chéo chính đều bằng 1 và các phần tử còn lại đều bằng 0)..

<span class='text_page_counter'>(15)</span>

Tài liệu bạn tìm kiếm đã sẵn sàng tải về

Tải bản đầy đủ ngay
×