MẢNG HAI CHIỀU

Một phần của tài liệu Bài Giảng Kỹ Thuật Lập Trình (Trang 92)

Để thuận tiện trong việc biểu diễn các loại dữ liệu phức tạp như ma trận hoặc các bảng biểu có nhiều chỉ tiêu, C++ đưa ra kiểu dữ liệu mảng nhiều chiều. Tuy nhiên, việc sử dụng mảng nhiều chiều rất khó lập trình vì vậy trong mục này chúng ta chỉ bàn đến mảng hai chiều. Đối với mảng một chiều m thành phần, nếu mỗi thành phần của nó lại là mảng một chiều n phần tử thì ta gọi mảng là hai chiều với số phần tử (hay kích thước) mỗi chiều là m và n. Ma trận là một minh hoạ cho hình ảnh của mảng hai chiều, nó gồm m dòng và n cột, tức chứa m x n phần tử, và hiển nhiên các phần tử này có cùng kiểu. Tuy nhiên, về mặt bản chất mảng hai chiều không phải là một tập hợp với m x n phần tử cùng kiểu mà là tập hợp với m thành phần, trong đó mỗi thành phần là một mảng một chiều với n phần tử. Điểm nhấn mạnh này sẽ được giải thích cụ thể hơn trong các phần trình bày về con trỏ của chương sau.

- - 0 - 1 - 2 - 3 -0 - 4 5 - 4 - 8 - 6 -1 - 9 - 5 4 - 2 2 - 9 0 -2 - 1 1 - 2 - 1 1 - 3 3 Hình trên minh hoạ hình thức một mảng hai chiều với 3 dòng, 4 cột. Thực chất trong bộ nhớ tất cả 12 phần tử của mảng được sắp liên tiếp theo từng dòng

của mảng như minh hoạ trong hình dưới đây. - D òng 0 - D òng 1 - D òng 2 - 4 5 - 4 - 8 - 6 - 9 - 5 4 - 2 2 - 9 0 - 1 1 - 2 - 1 1 - 3 3 a. Khai báo <kiểu thành phần > <tên mảng>[m][n] ; − m, n là số hàng, số cột của mảng.

− Kiểu thành phần là kiểu của m x n phần tử trong mảng.

− Trong khai báo cũng có thể được khởi tạo bằng dãy các dòng giá trị, các dòng cách nhau bởi dấu phẩy, mỗi dòng được bao bởi cặp ngoặc {} và toàn bộ giá trị khởi tạo nằm trong cặp dấu {}.

b. Sử dụng

• Tương tự mảng một chiều các chiều trong mảng cũng được đánh số từ 0. • Không sử dụng các thao tác trên toàn bộ mảng mà phải thực hiện thông qua từng phần tử của mảng.

• Để truy nhập phần tử của mảng ta sử dụng tên mảng kèm theo 2 chỉ số chỉ vị trí hàng và cột của phần tử. Các chỉ số này có thể là các biểu thức thực, khi đó C++ sẽ tự chuyển kiểu sang nguyên.

Ví dụ:

− Khai báo 2 ma trận 4 hàng 5 cột A, B chứa các số nguyên: int A[3][4], B[3][4] ;

− Khai báo có khởi tạo:

int A[3][4] = { {1,2,3,4}, {3,2,1,4}, {0,1,1,0} }; với khởi tạo này ta có ma trận:

- - 0 - 1 - 2 - 3

- 0 - 1 - 2 - 3 - 4

- 1 - 3 - 2 - 1 - 4

- 2 - 0 - 1 - 1 - 0

− Trong khai báo có thể vắng số hàng (không được vắng số cột), số hàng này được xác định thông qua khởi tạo.

float A[][3] = { {1,2,3}, {0,1,0} } ;

trong khai báo này chương trình tự động xác định số hàng là 2. − Phép khai báo và khởi tạo sau đây là cũng hợp lệ:

float A[][3] = { {1,2}, {0} } ;

Chương trình cũng xác định số hàng là 2 và số cột (bắt buộc phải khai báo) là 3 mặc dù trong khởi tạo không thể xác định được số cột. Các phần tử chưa khởi tạo sẽ chưa được xác định cho đến khi nào nó được nhập hoặc gán giá trị cụ thể. Trong ví dụ trên các phần tử A[0][2], A[1][1] và A[1][2] là chưa được xác định. c. Ví dụ minh hoạ Ví dụ 1 : Nhập, in và tìm phần tử lớn nhất của một ma trận. Bài làm ở dạng sử dụng một hàm main() #include <iostream.h> #include <iomanip.h> #include <conio.h> main() { float a[10][10] ; int m, n ; // số hàng, cột của ma trận int i, j ; // các chỉ số trong vòng lặp

int amax, imax, jmax// số lớn nhất và chỉ số của nó

clrscr(); cout << "Nhập số hàng và cột: " ; cin >> m >> n ; for (i=0; i<m; i++)

for (j=0; j<n; j++) {

cout << "a[" << i << "," << j << "] = " ; cin >> a[i][j] ; }

for (i=0; i<m; i++) for (j=0; j<n; j++) if (amax < a[i][j]) {

amax = a[i][j]; imax = i; jmax = j; }

cout << "Ma trận đã nhập\n" ;

cout << setiosflags(ios::showpoint) << setprecision(1) ; for (i=0; i<m; i++)

for (j=0; j<n; j++) {

if (j==0) cout << endl; cout << setw(6) << a[i][j] ; }

cout << "Số lớn nhất là " << setw(6) << amax << endl; cout << "tại vị trí (" << imax << "," << jmax << ")" ; getch();

}

Cách 2 : Xây dựng chương trình dưới dạng các hàm #include<iostream.h>

#include<conio.h>

void nhap(int a[100][100], int &sh, int &sc) {

cout<<"nhap so hang cua ma tran: "; cin>>sh;

cout<<"nhap so cot cua ma tran: "; cin>>sc;

for(int i=0; i<sh;i++) for(int j=0; j<sh;j++) {

cout<<"a["<<i<<"]["<<j<<"]= "; cin>>a[i][j]; }

}

void hthi(int a[100][100], int sh, int sc) { for(int i=0;i<sh;i++) { for(int j=0;j<sc;j++) cout<<a[i][j]<<" "; cout<<"\n"; } }

//tim phan tu lon nhat trong mang //ham tra ve giá tri lon nhat tim duoc //tham so x, y luu vi tri cua phan tu tim dc

int max(int a[100][100], int sh, int sc, int *x, int *y) {

int im=0,jm=0 ;//vi tri cua phan tu lon nhat int m=a[0][0];//luu tam thoi gia tri lon nhat for(int i=0; i<sh;i++)

for(int j=0; j<sc;j++) if(m<a[i][j])

{

m=a[i][j]; im=i; jm=j; }

*x=im;//vi tri cua so lon nhat *y=jm;//vi tri cua so lon nhat return m;//so lon nhat

}

{ int a[100][100]; int n, m;

nhap(a,n, m);

cout<<"\nMang ban dau la"<<endl; hthi(a,n, m);

int x, y;

int ln=max(a,n, m,&x, &y);

cout<<"So lon nhat = "<<ln<<" vi tri: hang "<<x<<" cot "<<y; }

Ghi chú: Khi làm việc với mảng (1 chiều, 2 chiều) do thói quen chúng ta thường tính chỉ số từ 1 (thay vì 0), do vậy trong mảng ta có thể bỏ qua hàng 0, cột 0 bằng cách khai báo số hàng và cột tăng lên 1 so với số hàng, cột thực tế của mảng và từ đó có thể làm việc từ hàng 1, cột 1 trở đi.

Ví dụ 2 : Nhân 2 ma trận. Cho 2 ma trận A (m x n) và B (n x p). Tính ma trận C = A*B, trong đó C có kích thước là m x p. Ta lập vòng lặp tính từng phần tử của C. Giá rị của phần tử C tại hàng i, cột j chính là tích vô hướng của hàng i ma trận A với cột j a trận B. Để tránh nhầm lẫn ta qui ước bỏ các hàng, cột 0 của các ma trận A, B, C (tức các chỉ số được tính từ 1 trở đi).

#include <iostream.h> #include <iomanip.h> #include <conio.h> main() { float A[10][10], B[10][10], C[10][10] ; int m, n, p ; int i, j, k ; clrscr();

cout << "Nhập số hàng và cột của 2 ma trận: " ; cin >> m >> n >> p; // Nhập ma trận A

for (j=0; j<n; j++) {

cout << "A[" << i << "," << j << "] = " ; cin >> A[i][j] ; }

// Nhập ma trận B for (i=0; i<n; i++) for (j=0; j<p; j++) {

cout << "B[" << i << "," << j << "] = " ; cin >> B[i][j] ; }

// Tính ma trận C = A x B for (i=0; i<m; i++)

for (j=0; j<p; j++) {

C[i][j] = 0; for (k=0; k<n; k++) C[i][j] += A[i][k]*B[k][j] ; }

// In kết quả

cout << "Ma trận kết quả\n" ;

cout << setiosflags(ios::showpoint) << setprecision(2) ; for (i=0; i<m; i++)

{

for (j=0 j<n; j++)

cout << setw(6) << a[i][j] ; cout << endl;

}

getch(); }

Bài tập: Xây dựng chương trình trên tổ chức dưới dạng các hàm.

Một phần của tài liệu Bài Giảng Kỹ Thuật Lập Trình (Trang 92)