46
Chương 4 MNG (Array)

CHƯƠNG 3 CÁC CẤU TRÚC ĐIỀU KHIỂN (Control structures) · 2011-10-03 · Mảng một chiều 3. ... Mỗi phần tử mảng là một . bi. ... 7. 2. M ảng một chiều

  • Upload
    dotu

  • View
    214

  • Download
    0

Embed Size (px)

Citation preview

Chương 4MẢNG(Array)

Nội dung trình bày

1. Khái niệm2. Mảng một chiều3. Một số bài toán trên mảng một chiều4. Mảng hai chiều5. Một số bài toán trên mảng hai chiều

2

1. Khái niệm

Mảng là một tập hợp các biến có cùng kiểu dữliệu nằm liên tiếp nhau trong bộ nhớ và có mộttên chung gọi là tên mảng

Mỗi phần tử của mảng được đánh chỉ mục(index): phần tử đầu tiên được đánh số là 0,…

Nếu mảng có n phần tử thì phần tử đầu tiên cóchỉ mục là 0 và phần tử cuối có chỉ mục là n-1

a

3

1. Khái niệm (tt)

Muốn truy cập phần tử nào của mảng thì phải dựavào chỉ mục của nó, cú pháp: tên_mảng[chỉ mục]

◦ Ví dụ: a[0] = 10;

cout<<a[1];

Số phần tử trong mảng được gọi là kích thước củamảng, luôn cố định, phải được xác định trước vàkhông đổi trong suốt chương trình

Có hai loại mảng thông dụng: 1 chiều, 2 chiều4

Nội dung trình bày

1. Khái niệm2. Mảng một chiều3. Một số bài toán trên mảng một chiều4. Mảng hai chiều5. Một số bài toán trên mảng hai chiều

5

2. Mảng một chiều: Khai báo

Khi khai báo mảng phải cho biết kích thước mảng Cú pháp khai báo mảng:

◦ type: kiểu dữ liệu của mảng◦ arrayName: tên mảng◦ size: số phần tử tối đa trong mảngVí dụ: int a[5];

float ds[100];char st[50];

aa[0] a[1] a[2] a[3] a[4]

type arrayName[size];

6

2. Mảng một chiều: Sử dụng

Mỗi phần tử mảng là một biến thông thườngVí dụ:int num[3];

num[0] = 2; // gán 2 cho phần tử num[0]

num[1] = num[0] + 3 // num[1] có giá trị 5

num[2] = num[0] + num[1]; //num[2] có giá trị 7

cout<< num[0]<<"\t"<<num[1]<<"\t"<<num[2];

cout<<"Nhap vao phan tu dau tien";

cin>>num[0];

cout<< num[0];

7

2. Mảng một chiều: Tính số bytes

Kích thước (tính bằng byte) của mảng được tính theo công thức:

Total_size = sizeof(type) * NumOfElements

Ví dụ:

int num[100];

Giả sử int chiếm 2 bytes, mảng num có kích thước là:

sizeof(int)*100 = 2 bytes * 100 = 200 bytes

8

2. Mảng một chiều: Khai báo và khởi tạo

Cú pháp khai báo và khởi tạo mảng:

◦ Lưu ý:

Không khai báo kích thước mảng

Kích thước mảng được xác định bởi các giá trị trong cặp dấu ngoặc {}, được phân cách nhau bởi dấu phẩy

type arrayName[]= {value1, value2, ..., valuen};

9

2. Mảng một chiều: Khai báo và khởi tạo (tt)

Ví dụ 1:

int soChan[] = {2, 4, 6, 8, 10};

Mảng soChan có 5 phần tử số nguyên, lần lượt là:

soChan[0] có giá trị là 2 soChan[1] có giá trị là 4 ... soChan[4] có giá trị là 10

Ví dụ 2:char st[] = {'h', 'e', 'l', 'l', 'o'};

10

2. Mảng một chiều: Ví dụ 1

Tạo một mảng số nguyên có 10 phần tử. Mỗi phần tử có giá trị làchỉ mục của nó. In mảng ra màn hình.#include <iostream.h>#include <conio.h> #define N 10 // kich thuoc toi da cua mangvoid main() {

int a[N]; // nhập mảngfor( int i=0; i<N; i++ )

a[i] = i ; // xuất mảngcout<< "In mang:\n"; for( int i=0; i<N; i++ )

cout<< a[i]<<"\t"; }

11

Viết hàm nhập, xuất mảng 1 chiều

#include <iostream.h>#include <conio.h> #define N 20 // kich thuoc toi davoid NhapMang( int a[ ], int n );void XuatMang( int a[ ], int n );void main() {

int sl, a[N];cout<<“Nhap so luong phan tu:”;cin>>sl;// gọi hàm để nhập mảngNhapMang(a, sl);// gọi hàm để xuất mảngcout<< "In mang:\n"; XuatMang(a, sl);

}

void NhapMang( int a[ ], int n ){

for( int i=0; i<N; i++ ) {

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

}}void XuatMang( int a[ ], int n ){

for( int i=0; i<N; i++ ) cout<< a[i]<< "\t";

}12

2. Mảng một chiều: Ví dụ 2

Đổi một số nguyên dương thập phân thành số nhị phân.void main(){

int i, j=0, n, np[20];cout<<"n="; cin>>n;do{

np[j]= n%2;j++;n = n/2;

}while(n>0);cout<<"dang nhi phan: ";for( i=j-1; i>0 ; i-- )

cout<<setw(3)<<np[i];}

n=46 2

1

0 225

231111

2

2

1 2

10 2

0

np

n%2

np[j]

0 1 1 1 0 1

13

Sử dụng hàm tạo số ngẫu nhiên (c1)

Để tạo ra số ngẫu nhiên, sử dụng hàm random

Cú pháp:

int random(int n)◦ Kết quả của hàm là tạo ra số nguyên ngẫu nhiên có

giá trị trong đoạn [0, n-1]

Để tránh lặp lại bộ số giống nhau mỗi lần chạy chương trình, phải dùng thêm hàm randomizeĐể sử dụng các hàm trên thì trong chương trình phải khai báo thư viện <stdlib.h>

14

Ví dụ: Sử dụng hàm tạo số ngẫu nhiên

#include <iostream.h>#include <conio.h> #include <stdlib.h>#define N 20 // kich thuoc toi davoid NhapMang( int a[], int n );void XuatMang( int a[], int n );void main() {

int sl, a[N];cout<<“Nhap so luong phan tu:”;cin>>sl;// gọi hàm để nhập mảngNhapMang(a, sl);// gọi hàm để xuất mảngcout<< "In mang:\n"; XuatMang(a, sl);

}

void NhapMang( int a[], int n ){

randomize();for( int i=0; i<N; i++ )

a[i] = random(100);}void XuatMang( int a[], int n ){

for( int i=0; i<N; i++ ) cout<< a[i]<<"\t";

}

15

Sử dụng hàm tạo số ngẫu nhiên (c2)

Sử dụng hàm rand(), trong thư viện <stdlib.h>

Hàm rand() trả về 1 số nguyên ngẫu nhiên có giá trị trong đoạn [0, RAND_MAX]

◦ RAND_MAX là một hằng số được định nghĩa trong tập tin cstdlib, nhưng ít nhất bằng 32767

Để tránh phát sinh số quá lớn, thường dùng:

◦ rand()% 100 phát sinh số thuộc [0, 99]rand()% 100 + 1 phát sinh số thuộc [1, 100]rand()% 30 + 1985 phát sinh số thuộc [1985, 2014]

Để tránh lặp lại bộ số giống nhau mỗi lần chạy chương trình, dùng thêm lệnh: srand ( time(NULL) ), hàm time thuộc thư viện <time.h>

16

Ví dụ: Sử dụng hàm tạo số ngẫu nhiên

#include <iostream.h>#include <conio.h> #include <stdlib.h>#include <time.h>#define N 20 // kich thuoc toi davoid NhapMang( int a[], int n );void XuatMang( int a[], int n );void main() {

int sl, a[N];cout<<“Nhap so luong phan tu:”;cin>>sl;// gọi hàm để nhập mảngNhapMang(a, sl);// gọi hàm để xuất mảngcout<< "In mang:\n"; XuatMang(a, sl);

}

void NhapMang( int a[], int n ){

srand ( time(NULL) );for( int i=0; i<N; i++ )

a[i] = rand()%10;}void XuatMang( int a[], int n ){

for( int i=0; i<N; i++ ) cout<< a[i]<<"\t";

}

17

Nội dung trình bày

1. Khái niệm2. Mảng một chiều3. Một số bài toán trên mảng một chiều4. Mảng hai chiều5. Một số bài toán trên mảng hai chiều

18

3. Một số bài toán trên mảng 1 chiều

Tính tổng, tích các phần tử mảng

Tìm kiếm trên mảng theo điều kiện cho trước

Đếm số phần tử mảng theo điều kiện cho trước

Tìm phần tử lớn nhất, nhỏ nhất của mảng

Sắp xếp mảng tăng dần, giảm dần

19

Tính tổng, tích giá trị các phần tử

Giả sử a là tên mảng, n là số phần tử, s là giá trị cần tínhTổng giá trị các phần tử trong mảng:

Tích giá trị các phần tử trong mảng:

int s=0;for( int i=0; i<n; i++ )

s+=a[i];

int s=1;for( int i=0; i<n; i++ )

s*=a[i];

4 7 9 2 1a

s=0

i=0 s=4

i=1 s=11

i=2 s=20

i=3 s=22

i=4 s=23

20

Tìm kiếm trên mảng theo điều kiện cho trước

Giả sử a là tên mảng, n là số phần tử, k là giá trị muốn tìm

Ví dụ:◦ Tìm xem trong mảng có giá trị nào bằng k cho trước

không◦ Tìm xem trong mảng có số âm nào không◦ Kiểm tra xem mảng có phải tự tăng dần không

int flag=0;

for( int i=0; i<n; i++ )

if (a[i] == k) flag=1;

21

Minh họa: tìm kiếm

22

5Giá trị tìm

7 13 5 21 6 2 8 150 1 2 3 4 5 6 7

Vị trí = 2

Tìm thành công

Số lần so sánh: 3

a

Minh họa: tìm kiếm

23

9

7 13 5 21 6 2 8 150 1 2 3 4 5 6 7

Không tìm thấy

Số lần so sánh: 8

Giá trị tìm

a

Đếm số phần tử mảng theo điều kiện cho trước

Giả sử a là tên mảng, n là số phần tử, k là giá trị muốn đếm

Ví dụ:◦ Đếm số phần tử bằng giá trị cho trước◦ Đếm số phần tử chẵn trong mảng◦ Đếm số phần tử dương trong mảng

int dem=0;for( int i=0; i<n; i++ )

if (a[i] == k) dem++;

7 13 5 21 6 2 8 150 1 2 3 4 5 6 7

a

24

Tìm phần tử lớn nhất mảng

Giả sử a là tên mảng, n là số phần tử, m là giá trị lớn nhất tìm được

int m=a[0];

for( int i=0; i<n; i++ )

if (m<a[i]) m=a[i];

7 13 5 21 6 2 8 150 1 2 3 4 5 6 7

a

m 7132125

Sắp xếp mảng tăng dần: Minh họa

26

2 8 5 1 6 4 1512

1 2 3 4 5 6 70

i

j

1

Nếu a[i] > a[j] thì đổi chỗ a[i], a[j]

12 8 5 2 6 4 151

1 2 3 4 5 6 70

i

j

2

Nếu a[i] > a[j] thì đổi chỗ a[i], a[j]

Sắp xếp mảng tăng dần: Minh họa

27

Sắp xếp mảng tăng dần: Minh họa

28

2 12 8 5 6 4 151

1 2 3 4 5 6 70

i

j

4

Nếu a[i] > a[j] thì đổi chỗ a[i], a[j]

Sắp xếp mảng tăng dần: Minh họa

29

2 4 12 8 6 5 151

1 2 3 4 5 6 70

i

j

5

Nếu a[i] > a[j] thì đổi chỗ a[i], a[j]

Sắp xếp mảng tăng dần: Minh họa

30

2 4 5 6 8 12 151

1 2 3 4 5 6 70

Nếu a[i] > a[j] thì đổi chỗ a[i], a[j]

Sắp xếp mảng tăng dần

Giả sử a là tên mảng, n là số phần tử

for ( int i = 0; i < n - 1; i++ ) for ( int j = i + 1; j < n; j++ )

if ( a[i] > a[j] ) {

t = a[i] ; a[i] = a[j]; a[j ] = t ;

}

31

Nội dung trình bày

1. Khái niệm2. Mảng một chiều3. Một số bài toán trên mảng một chiều4. Mảng hai chiều5. Một số bài toán trên mảng hai chiều

32

4. Mảng hai chiều: Giới thiệu

C/C++ hỗ trợ mảng nhiều chiều

Dạng đơn giản nhất của mảng nhiều chiều làmảng hai chiều

Mảng hai chiều thực chất là mảng của nhữngmảng một chiều

Có thể xem mảng hai chiều là một ma trận gồmcác dòng và các cột

33

4. Mảng hai chiều: Khai báo

Cú pháp khai báo mảng:

◦ rowSize: số dòng◦ columnSize: số cột

Ví dụ:int a[3][4];

type arrayName[rowSize][columnSize];

34

4. Mảng hai chiều: Lưu ý

Mảng phải được khai báo tường minh số dòng, số cột

Để truy cập phần tử mảng tại dòng i cột j, sử dụng cú pháp: tên_mảng[i][j]

Để duyệt tất cả các phần tử trong mảng hai chiều, thường dùng 2 vòng lặp for:

for( int i=0; i<dong; i++ )

for( int j=0; j<cot; j++ )

//…

35

4. Mảng hai chiều: Khai báo và khởi tạo

Cú pháp khai báo và khởi tạo:

Ví dụ:int a[][4] = {{1,2,3,4}, {5,6,7,8},{9,10,11,12}};

type arrayName[][columnSize] = { {value1,value2,...,valueN},{value1,value2,...,valueN},{...},{value1,value2,...,valueN}};

36

4. Mảng hai chiều: Chú ý

Chú ý khi khai báo và khởi tạo mảng 2 chiều:

◦ Số dòng để trống

◦ Số dòng của mảng được xác định dựa vào số dòngtrong phần khởi tạo

◦ Số phần tử của mỗi dòng phải bằng nhau

◦ Giá trị các phần tử trong mỗi dòng được đặt trongcặp {}, các hàng phân cách nhau bằng một dấuphẩy

37

Viết hàm nhập, xuất mảng 2 chiều (1)

#include <iostream.h>#include <conio.h> #define M 20 // so dong toi da#define N 10 // so cot toi davoid NhapMang( int a[][N], int d, int c);void XuatMang( int a[][N], int d, int c);void main() {

int d, c, a[M][N];cout<<“Nhap so luong dong:”;cin>>d;cout<<“Nhap so luong cot:”;cin>>c;// gọi hàm để nhập mảngNhapMang(a, d, c);// gọi hàm để xuất mảngcout<< "In mang:\n";

XuatMang(a, d, c);}void NhapMang( int a[][N], int d, int c ){

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

cout<<“a[”<<i<<“][”<<j<<“]=”;cin>>a[i][j];

}}void XuatMang( int a[][N], int d, int c ){

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

cout<< a[i][j]<<"\t";cout<<endl;

}} 38

Viết hàm nhập, xuất mảng 2 chiều (2)

#include <iostream.h>#include <conio.h> #include <time.h>#include <stdlib.h>#define M 20#define N 10void NhapMang( int a[][N], int d, int c );void XuatMang( int a[][N], int d, int c );void main() {

int d, c, a[M][N];cout<<“Nhap so luong dong:”;cin>>d;cout<<“Nhap so luong cot:”;cin>>c;// gọi hàm để nhập mảngNhapMang(a, d, c);// gọi hàm để xuất mảng

cout<< "In mang:\n"; XuatMang(a, d, c);

}void NhapMang( int a[][N], int d, int c ){ srand(time(NULL));

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

a[i][j]= rand()%10;}

}void XuatMang( int a[][N], int d, int c ){

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

cout<< a[i][j]<<"\t";cout<<endl;

}}

39

Nội dung trình bày

1. Khái niệm2. Mảng một chiều3. Một số bài toán trên mảng một chiều4. Mảng hai chiều5. Một số bài toán trên mảng hai chiều

40

5. Một số bài toán trên mảng hai chiều

Tính tổng, tích các phần tử mảng

Tìm kiếm trên mảng theo điều kiện cho trước

Đếm số phần tử mảng theo điều kiện cho trước

Tìm phần tử lớn nhất, nhỏ nhất của mảng

Duyệt mảng hai chiều theo dòng hoặc cột

Duyệt mảng hai chiều theo đường chéo chính hoặc đường chéo phụ

41

Duyệt mảng hai chiều theo dòng

Ví dụ: Xuất các số trên dòng thứ 2:for (int i=0; i<c; i++) // c: số cột

cout<<a[1][i]<<“\t”;Ví dụ: Tính tổng các số trên dòng thứ 1:int t=0;for (int i=0; i<c; i++) // c: số cột

s+=a[0][i];Ví dụ: Tính tổng các số trên dòng thứ k:int t=0;for (int i=0; i<c; i++) // c: số cột

s+=a[k][i];

1 2 3

5 8 13

21 34 55

89 10 2042

Duyệt mảng hai chiều theo cột

Ví dụ: Xuất các số trên cột thứ 2:for (int i=0; i<d; i++) // d: số dòng

cout<<a[i][1]<<“\t”;Ví dụ: Tính tổng các số trên dòng thứ 1:int t=0;for (int i=0; i<d; i++) // d: số dòng

s+=a[i][0];Ví dụ: Tính tổng các số trên cột thứ k:int t=0;for (int i=0; i<d; i++) // d: số dòng

s+=a[i][k];

1 2 3

5 8 13

21 34 55

89 10 2043

Duyệt mảng hai chiều theo đường chéo chính, chéo phụ

Điều kiện: số dòng phải bằng số cột

Các phần tử nằm trên đường chéo chính thỏa điều kiện j=i

Các phần tử nằm trên đường chéo phụ thỏa điều kiện j=n-i-1

1 2 0 3

5 8 2 13

21 34 99 55

2 5 7 0

j=ij=n-i-1

0 1 2 3

0

1

2

3

44

Ví dụ: Tổng giá trị trên đường chéo chính#include <iostream.h> #include <conio.h> void main() {

int a[][4] = {{1,2,3,4},{5,6,7,8},{9,10,11,12},{13,14,15,16}};

int sum=0;for(int i=0; i<4; i++)

for(int j=0; j<4; j++)if (j==i) sum += a[i][j];

cout<< “Tong duong cheo chinh la: ”<< sum;}

45

Bài tập

Tính tổng các giá trị bên trên đường chéo chính (bao gồm cả đường chéo chính)Đếm số lượng số âm trong phần tam giác bên dưới đường chéo chínhIn hình tam giác bên dưới đường chéo chính

46