Trong C++, cho phép viết các hàm có đối số là mảng nh sác đối số thông thờng. Tuy nhiên, khi truyền tham số là mảng, ta thờng truyền thêm cả các biến là kích thớc của mảng.
VD1: Viết chơng trình thực hiện việc nhập một dãy số nguyên, tính tổng các phần tử lẻ và in kết quả đó lên màn hình.
#include “stdio.h”
…
long Tong(int a[100], int n) {
long T=0;
for (int i=0; i<n; i++) if(a[i]%2==0) T+=a[i]; return T; } void main() { int b[100]; int n; cout<<”Nhập n”; cin>>n;
for(int i=0; i<n; i++) {
cout<<”Nhập b[“<<i<<”]”; cin>>b[i];
cout<<”Tổng các phần tử lẻ “<<Tong(b, n); getch(); } VD2: Viết chơng trình nhập một ma trận n hàng, m cột. Tìm phần tử lớn nhất của ma trận và in ma trận vừa nhập cùng phần tử lớn nhất ra màn hình. #include… …
double Max(double a[100][100], n, m) {
Max = a[0][0]; for(int i=0; i<n; i++) for(int j=0; j<m; j++) if (a[i][j]>Max) Max=a[i][j]; return Max; } void main() { double b[100][100]; int m, n; cout<<”Nhập n”; cin>>n; cout<<”Nhập m”; cin>>m; for(int i=0; i<n; i++)
for(int j=0; j<m; j++) { cout<<”b[“<<i<<”]= “; cin>>b[i][j]; } cout<<”Ma trận vừa nhập là “; for(int i=0; i<n; i++)
for(int j=0; j<m; j++)
cout<<”b[“<<i<<”]= “<<b[i][j];
cout<<”Phần tử lớn nhất : “<<Max(b, n, m); getch();
}
3. Các bài toán cơ bản về mảng1. Bài toán trên mảng một chiều. 1. Bài toán trên mảng một chiều.
Bài 1: Viết chơng trình nhập vào mảng n số nguyên và một số
nguyên c. Cho biết có bao nhiêu số nguyên c trong mảng và vị trí của nó.
Bài 2: Viết chơng trình nhập vào một mảng n phần tử nguyên. tính
tổng các phần tử lẻ, chẵn, chia hết cho 3 trong mảng.
Biên soạn: Nguyễn Mạnh Cờng Trang 5 4
2. Bài toán trên mảng hai chiều.
Bài 1: Viết chơng trình nhập vào 2 ma trận A, B cùng kích thớc m
x n các số nguyên. Tính và in ma trận C = A+B.
Bài 2: Ma trận B gọi là ma trận chuyển vị của A nếu B[i][j] = A[j][i].
Viết chơng trình nhập vào một ma trận A có n dòng, m cột các phần tử thực. Tính và in ra ma trận chuyển vị của A.
4. Các giải thuật tìm kiếm, sắp xếp trên mảng
Bài toán tìm kiếm cơ bản đợc phát biểu nh sau:
- Cho một mảng a gồm n phần tử và một khoá c. Hãy cho biết
khoá c có xuất hiện trong a không? Nếu có, hãy chỉ ra một vị trí của c trong a.
Bài toán sắp xếp đợc phát biểu rất đơn giản:
- Cho một mảng a gồm n phần tử. Hãy sắp xếp mảng a theo
thứ tự tăng dần (hoặc giảm dần).
Với hai bài toán đặc thù trên mảng nh trên, việc tìm ra các phơng pháp khác nhau để giải quyết là rất quan trọng. Sau đây sẽ lần lợt trình bày một số giải thuật cơ bản để giải quyết hai bài toán trên.
1. Tìm kiếm tuần tự
Một phơng pháp đơn giản nhất để giải quyết bài toán tìm kiếm là tìm kiếm tuần tự. Theo phơng pháp này, ta chỉ cần duyệt từ đầu đến cuối mảng. Nếu gặp khoá c, sẽ in ra vị trí của c (tức là chỉ số của phần tử c trong mảng). Ngợc lại, khi duyệt hết mảng mà không tìm thấy c, tức là c không xuất hiện trong mảng. Nh vậy, độ phức tạp của thuật giải là O(n).
int d=0;
ìor (i =0; i< n; i++) if (a[i]==c) { cout<<” Vị trí tìm đợc c “<<i+1; d++; } if (d==0)
Đôi khi, cần phải nắm đợc tất cả các vị trí xuất hiện c, ta sử dụng một mảng VT[] đồng hành để lu các vị trí đã tìm đợc c. Nh vậy, thay bằng việc in vị trí tìm đợc ra màn hình, ta lu vị trí đó trong mảng VT:
VT[d] = i+1;
2. Tìm kiếm nhị phân trên mảng đợc sắp
Phơng pháp này chỉ áp dụng trên mảng đã đợc sắp. ý tởng có thể hình dung nh sau:
Giả sử ta cần tìm kiếm c trong một đoạn từ vị trí L tới vị trí R trên một mảng a đợc sắp:
Khi đó, ta chia mảng a làm hai phần bởi điểm chia M: M = (L+R)/ 2
Ta áp dụng tìm kiếm trên 2 nửa của a. Tuy nhiên, do a đã đợc sắp nên chỉ có thể sảy ra 3 trờng hợp sau:
[1]. Nếu a[M] = c thì ta đã tìm đợc c trong mảng. Vị trí của c là M. [2]. Nếu a[M] > c thì c thuộc về nửa trái của mảng a. Khi đó ta áp dụng tìm kiếm trên nửa trái, tức là từ vị trí L tới M-1.
[3]. Nếu a[M] < c thì c thuộc về nửa phải của mảng a. Khi đó ta áp dụng tìm kiếm trên nửa phải, tức là từ vị trí M+1 tới R.
Việc tìm kiếm trên các nửa của a cũng áp dụng phơng pháp chia đôi tơng tự nh trên. Nh vậy, ngay từ đầu ta áp dụng tìm kiếm nhị phân trên toàn mảng a (L=0; R=n-1). Hàm tìm kiếm nhị phân lặp sau đây trả về giá trị -1 nếu không tìm thấy c trong a; ngợc lại, nó trả về vị trí của c trong a.
int TKNP_Lap(int a[100], int n, int c) { int L, R, M; L =0; R = n-1; do { M = (L+R)/2;
Biên soạn: Nguyễn Mạnh Cờng Trang 5 6
L mảng a R
if (a[M] < c) R = M-1; }
while (L<R && a[M]!=c);
if (a[M] ==c) return M; else
return -1; }
Rõ ràng là trong trờng hợp này, việc áp dụng đệ quy là rất phù hợp. Sau đây ta xem xét khả năng áp dụng đệ quy với thiết kế sau:
B1: Suy biến trong trờng hợp L > R hoặc a[M] = c. Khi đó - Nếu L > R thì không tìm đợc c trong a.
- Nếu a[M] = c thì trả về M là vị trí của c trong a.Ngợc lại, trong trờng hợp L <= R và a[M] ! = c. Khi đó: Ngợc lại, trong trờng hợp L <= R và a[M] ! = c. Khi đó: