L5. Mảng (Array) trong C++
Phần 1: Mảng Một Chiều
1. Giới Thiệu Về Mảng
Đặt vấn đề:
// Cần lưu trữ 3 số thực
float a, b, c; // OK
// Cần lưu trữ 10 số thực
float a1, a2, a3, ..., a10; // Khó quản lý
// Cần lưu trữ 100 hoặc 1000 số thực
// → Không thể khai báo 100 hoặc 1000 biến!
Giải pháp: Sử dụng MẢNG
┌────┬────┬────┬────┬────┬────┬────┬────┬────┬────┐
│1.3 │9.4 │2.7 │6.2 │4.9 │7.7 │3.5 │8.6 │0.1 │5.4 │
└────┴────┴────┴────┴────┴────┴────┴────┴────┴────┘
0 1 2 3 4 5 6 7 8 92. Khái Niệm Mảng
Định nghĩa:
Mảng là một dãy các phần tử có cùng kiểu dữ liệu, mỗi phần tử biểu diễn một giá trị.
Đặc điểm:
- Kích thước mảng được xác định ngay khi khai báo và không thay đổi
- Là kiểu dữ liệu có cấu trúc do người lập trình định nghĩa
- C++ luôn chỉ định một khối nhớ liên tục cho mảng
Ví dụ minh họa:
Mảng 1 chiều:
┌───┬───┬───┬───┬───┬───┬───┬───┬───┐
│ 5 │ T │ 8 │ B │ 2 │ R │ 7 │ K │ 1 │
└───┴───┴───┴───┴───┴───┴───┴───┴───┘
Mảng 2 chiều (Ma trận):
┌───┬───┐ ┌───┬───┬───┐ ┌───┬───┐
│ 3 │ 7 │ │ 3 │ 7 │ 8 │ │ 6 │ 7 │
├───┼───┤ ├───┼───┼───┤ ├───┼───┤
│ 6 │ 1 │ │ 6 │ 1 │ 4 │ │ 1 │ 1 │
└───┴───┘ └───┴───┴───┘ ├───┼───┤
2×2 (vuông) 2×3 (dòng<cột) │ 6 │ 3 │
└───┴───┘
3×2 (dòng>cột)3. Các Yếu Tố Xác Định Mảng
Một mảng được xác định bởi 4 yếu tố:
graph TD
A[Mảng] --> B[1. Tên mảng]
A --> C[2. Kiểu dữ liệu]
A --> D[3. Số chiều]
A --> E[4. Kích thước]
Ví dụ 1:
char MangKyTu[4];- Tên mảng:
MangKyTu - Kiểu mảng:
char - Số chiều: 1 chiều
- Kích thước: 4 phần tử
Ví dụ 2:
int MangSoNguyen[3][2];- Tên mảng:
MangSoNguyen - Kiểu mảng:
int - Số chiều: 2 chiều
- Kích thước: 3 dòng × 2 cột
4. Mảng Một Chiều
4.1. Khai Báo Mảng 1 Chiều
Cú pháp:
<Kiểu_dữ_liệu> <Tên_biến_mảng>[<Số_phần_tử>];Ví dụ:
char A[10];
// Kiểu dữ liệu: char
// Tên biến mảng: A
// Số phần tử: 10
int Mang1Chieu[30];
// Kiểu dữ liệu: int
// Tên biến mảng: Mang1Chieu
// Số phần tử: 30
4.2. Khởi Tạo Mảng 1 Chiều
Cách 1: Khởi tạo đầy đủ
int A[4] = {29, 137, 50, 4};┌────┬─────┬────┬───┐
│ 29 │ 137 │ 50 │ 4 │
└────┴─────┴────┴───┘
0 1 2 3Cách 2: Khởi tạo một phần
int B[4] = {91, 106};┌────┬─────┬───┬───┐
│ 91 │ 106 │ 0 │ 0 │ ← Phần còn lại = 0
└────┴─────┴───┴───┘
0 1 2 3Cách 3: Khởi tạo tất cả = 0
int a[4] = {0};┌───┬───┬───┬───┐
│ 0 │ 0 │ 0 │ 0 │
└───┴───┴───┴───┘
0 1 2 3Cách 4: Tự động xác định kích thước
int a[] = {22, 16, 56, 19};
// Tự động tạo mảng 4 phần tử
┌────┬────┬────┬────┐
│ 22 │ 16 │ 56 │ 19 │
└────┴────┴────┴────┘
0 1 2 34.3. Chỉ Số Mảng
Đặc điểm:
- Chỉ số mảng là giá trị số nguyên
int - Chỉ số bắt đầu từ 0
- Chỉ số tối đa = Số phần tử - 1
int A[5];Các chỉ số hợp lệ: 0, 1, 2, 3, 4
┌────┬────┬────┬────┬────┐
│ 99 │ 17 │ 50 │ 43 │ 72 │
└────┴────┴────┴────┴────┘
0 1 2 3 4
↑ ↑
Chỉ số đầu Chỉ số cuốiSố lượng chỉ số = Số phần tử = 5
4.4. Truy Xuất Phần Tử Mảng
Cú pháp:
<Tên_biến_mảng>[<chỉ_số>]Ví dụ:
int A[4] = {29, 137, 50, 4};
// Truy xuất hợp lệ
A[0] // = 29
A[1] // = 137
A[2] // = 50
A[3] // = 4
// Truy xuất KHÔNG hợp lệ
A[-1] // SAI: chỉ số âm
A[4] // SAI: vượt quá giới hạn
A[5] // SAI: vượt quá giới hạn
┌────┬─────┬────┬───┐
│ 29 │ 137 │ 50 │ 4 │
└────┴─────┴────┴───┘
0 1 2 3
↑
A[0] = 294.5. Địa Chỉ Các Phần Tử Mảng
Cú pháp:
&<Tên_biến_mảng>[<chỉ_số>];Ví dụ:
int A[4] = {29, 137, 50, 4};
// Địa chỉ các phần tử
&A[0] // Địa chỉ phần tử thứ 0
&A[1] // Địa chỉ phần tử thứ 1
&A[2] // Địa chỉ phần tử thứ 2
&A[3] // Địa chỉ phần tử thứ 3
┌────┬─────┬────┬───┐
Giá trị: │ 29 │ 137 │ 50 │ 4 │
└────┴─────┴────┴───┘
Địa chỉ: 0x10 0x14 0x18 0x1C
Chỉ số: 0 1 2 34.6. Truyền Mảng Cho Hàm
Khai báo tham số:
void SapXep(int A[100], int n);
// Tên hàm: SapXep
// Tham số: mảng số nguyên A và số lượng phần tử n
// Giá trị trả về: void
int TinhTong(int A[100], int n);
// Tên hàm: TinhTong
// Tham số: mảng số nguyên A và số lượng phần tử n
// Giá trị trả về: int
Ví dụ đầy đủ:
#include <stdio.h>
#include <conio.h>
void Nhap(int A[], int &N); // Nhập mảng
void Xuat(int A[], int N); // Xuất mảng
int TinhTong(int A[], int N); // Tính tổng
void main() {
int a[100], n, S;
Nhap(a, n);
Xuat(a, n);
S = TinhTong(a, n);
cout << "Tong cac phan tu trong mang: " << S;
}5. Các Tác Vụ Trên Mảng 1 Chiều
5.1. Nhập Mảng
void nhapmang(int A[], int N) {
for (int i = 0; i < N; i++) {
cout << "Nhap phan tu thu " << i << ": ";
cin >> A[i];
}
}5.2. Xuất Mảng
void xuatmang(int A[], int N) {
for (int i = 0; i < N; i++) {
cout << A[i] << " ";
}
}5.3. Tìm Kiếm Phần Tử
int TimKiem(int a[], int n, int x) {
for (int vt = 0; vt < n; vt++) {
if (a[vt] == x)
return vt; // Trả về vị trí tìm thấy
}
return -1; // Không tìm thấy
}5.4. Tìm Giá Trị Lớn Nhất
int Max(int a[], int n) {
int Max = a[0]; // Giả sử phần tử đầu là lớn nhất
for (int i = 1; i < n; i++) {
if (Max < a[i]) // Áp dụng kỹ thuật lính canh
Max = a[i];
}
return Max;
}5.5. Kiểm Tra Tính Chất Mảng
Yêu cầu: Kiểm tra mảng có toàn số nguyên tố không?
Ý tưởng 1: Đếm số lượng số nguyên tố, nếu = n thì toàn nguyên tố
// Hàm kiểm tra số nguyên tố
int LaSNT(int n) {
if (n < 2) return 0;
for (int i = 2; i < n; i++) {
if (n % i == 0)
return 0; // Không phải SNT
}
return 1; // Là SNT
}
// Ý tưởng 1
int KiemTra_YT1(int a[], int n) {
int dem = 0;
for (int i = 0; i < n; i++) {
if (LaSNT(a[i]) == 1)
dem++;
}
if (dem == n)
return 1; // Toàn SNT
return 0;
}Ý tưởng 2: Đếm số không phải nguyên tố, nếu = 0 thì toàn nguyên tố
int KiemTra_YT2(int a[], int n) {
int dem = 0;
for (int i = 0; i < n; i++) {
if (LaSNT(a[i]) == 0)
dem++;
}
if (dem == 0)
return 1; // Toàn SNT
return 0;
}Ý tưởng 3: Tìm phần tử không phải nguyên tố (Tối ưu nhất)
int KiemTra_YT3(int a[], int n) {
for (int i = 0; i < n; i++) {
if (LaSNT(a[i]) == 0)
return 0; // Tìm thấy số không phải SNT
}
return 1; // Không tìm thấy số nào không phải SNT
}5.6. Đếm Số Lượng Phần Tử Chẵn
int DemChan(int A[], int N) {
int DC = 0;
for (int i = 0; i < n; i++) {
if (A[i] % 2 == 0)
DC++;
}
return DC;
}Sử dụng:
int main() {
int a[100], n, DC;
nhap(a, n);
xuat(a, n);
DC = DemChan(a, n);
printf("So ptu chan la %d", DC);
}5.7. Tính Tổng Các Phần Tử Chẵn
int TongChan(int A[], int N) {
int TC = 0;
for (int i = 0; i < n; i++) {
if (A[i] % 2 == 0)
TC = TC + A[i];
}
return TC;
}Sử dụng:
int main() {
int a[100], n, TC;
nhap(a, n);
xuat(a, n);
TC = TongChan(a, n);
printf("Tong ptu chan la %d", TC);
}