Bài tập mảng 2 chiều C/C++ có lời giải – Lập trình C – phanmemdohoa.com
Xin chào các bạn! Hôm nay, chúng ta sẽ cùng tìm hiểu về một trong những cấu trúc dữ liệu quan trọng trong lập trình C/C++ – mảng 2 chiều. Đây là kiến thức nền tảng cực kỳ quan trọng cho những ai đang học lập trình. Bài viết này sẽ cung cấp cho bạn hiểu biết sâu sắc cùng với các bài tập thực hành có lời giải chi tiết.
Mảng 2 chiều là gì?
Mảng 2 chiều (hay ma trận) là một cấu trúc dữ liệu lưu trữ các phần tử theo dạng lưới gồm hàng và cột. Về bản chất, đây là “mảng của các mảng” – mỗi phần tử được xác định bởi hai chỉ số: chỉ số hàng và chỉ số cột.
“Mảng 2 chiều trong C/C++ là nền tảng quan trọng cho nhiều ứng dụng thực tế từ xử lý ảnh, các trò chơi như cờ vua, đến các phép tính toán ma trận trong toán học.”
Các ứng dụng phổ biến của mảng 2 chiều bao gồm:
- Lưu trữ hình ảnh dưới dạng pixel
- Biểu diễn bàn cờ trong các trò chơi như cờ vua, cờ ca-rô
- Thực hiện các phép toán ma trận
- Quản lý dữ liệu bảng tính
Khai báo và khởi tạo mảng 2 chiều
Cú pháp khai báo mảng 2 chiều trong C/C++ như sau:
kiểu_dữ_liệu tên_mảng[số_hàng][số_cột];
Ví dụ:
int matrix[3][4]; // Khai báo mảng 2 chiều có 3 hàng và 4 cột
// Khởi tạo mảng 2 chiều
int arr[3][3] = {
{1, 2, 3}, // Hàng 0
{4, 5, 6}, // Hàng 1
{7, 8, 9} // Hàng 2
};
Truy xuất và duyệt mảng 2 chiều
Để truy xuất một phần tử trong mảng 2 chiều, ta sử dụng cú pháp:
tên_mảng[chỉ_số_hàng][chỉ_số_cột]
Để duyệt toàn bộ mảng 2 chiều, ta thường sử dụng vòng lặp lồng nhau:
// In ra tất cả các phần tử trong mảng 2 chiều
for (int i = 0; i < số_hàng; i++) {
for (int j = 0; j < số_cột; j++) {
printf("%d ", arr[i][j]);
}
printf("n"); // Xuống dòng sau khi in xong một hàng
}
Truyền mảng 2 chiều vào hàm
Khi truyền mảng 2 chiều vào hàm trong C/C++, chúng ta cần chỉ định kích thước cột của mảng (số cột là bắt buộc):
void printMatrix(int matrix[][3], int rows) {
for (int i = 0; i < rows; i++) {
for (int j = 0; j < 3; j++) {
printf("%d ", matrix[i][j]);
}
printf("n");
}
}
Lưu ý: Trong C++, bạn cũng có thể sử dụng vector để tạo mảng 2 chiều với kích thước động:
#include <vector>
using namespace std;
vector<vector<int>> matrix(rows, vector<int>(cols, 0)); // Khởi tạo ma trận rows x cols với giá trị 0
10 Bài tập mảng 2 chiều C/C++ có lời giải chi tiết
Bài tập 1: Tìm phần tử lớn nhất trong mảng 2 chiều
#include <stdio.h>
int main() {
int rows, cols;
printf("Nhập số hàng và số cột: ");
scanf("%d %d", &rows, &cols);
int arr[50][50];
printf("Nhập các phần tử của mảng:n");
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
scanf("%d", &arr[i][j]);
}
}
int max = arr[0][0];
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if (arr[i][j] > max) {
max = arr[i][j];
}
}
}
printf("Phần tử lớn nhất trong mảng là: %dn", max);
return 0;
}
Bài tập 2: Tính tổng các phần tử trên đường chéo chính
#include <stdio.h>
int main() {
int n;
printf("Nhập kích thước ma trận vuông: ");
scanf("%d", &n);
int arr[50][50];
printf("Nhập các phần tử của ma trận:n");
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
scanf("%d", &arr[i][j]);
}
}
int sum = 0;
for (int i = 0; i < n; i++) {
sum += arr[i][i]; // Các phần tử trên đường chéo chính có i = j
}
printf("Tổng các phần tử trên đường chéo chính là: %dn", sum);
return 0;
}
Bài tập 3: Đếm số lượng số chẵn trong mảng
#include <stdio.h>
int main() {
int rows, cols;
printf("Nhập số hàng và số cột: ");
scanf("%d %d", &rows, &cols);
int arr[50][50];
printf("Nhập các phần tử của mảng:n");
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
scanf("%d", &arr[i][j]);
}
}
int count = 0;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
if (arr[i][j] % 2 == 0) {
count++;
}
}
}
printf("Số lượng số chẵn trong mảng là: %dn", count);
return 0;
}
Bạn có thể tham khảo thêm về mảng 2 chiều tại Wikipedia để hiểu rõ hơn về cấu trúc dữ liệu này.
Bài tập 4: Tính tổng các phần tử trên đường viền của ma trận
#include <stdio.h>
int main() {
int rows, cols;
printf("Nhập số hàng và số cột: ");
scanf("%d %d", &rows, &cols);
int arr[50][50];
printf("Nhập các phần tử của mảng:n");
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
scanf("%d", &arr[i][j]);
}
}
int sum = 0;
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
// Kiểm tra phần tử có nằm trên viền không
if (i == 0 || j == 0 || i == rows-1 || j == cols-1) {
sum += arr[i][j];
}
}
}
printf("Tổng các phần tử trên viền ma trận là: %dn", sum);
return 0;
}
Bài tập 5: Sắp xếp các hàng của ma trận theo thứ tự tăng dần
#include <stdio.h>
int main() {
int rows, cols;
printf("Nhập số hàng và số cột: ");
scanf("%d %d", &rows, &cols);
int arr[50][50];
printf("Nhập các phần tử của mảng:n");
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
scanf("%d", &arr[i][j]);
}
}
// Sắp xếp từng hàng
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols-1; j++) {
for (int k = j+1; k < cols; k++) {
if (arr[i][j] > arr[i][k]) {
// Hoán đổi giá trị
int temp = arr[i][j];
arr[i][j] = arr[i][k];
arr[i][k] = temp;
}
}
}
}
printf("Ma trận sau khi sắp xếp mỗi hàng:n");
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
printf("%d ", arr[i][j]);
}
printf("n");
}
return 0;
}
Để hiểu thêm về các thuật toán sắp xếp, bạn có thể tham khảo tại Moz - Algorithm Guide.
Bài tập 6: Kiểm tra ma trận có phải ma trận đơn vị không
#include <stdio.h>
int main() {
int n;
printf("Nhập kích thước ma trận vuông: ");
scanf("%d", &n);
int arr[50][50];
printf("Nhập các phần tử của ma trận:n");
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
scanf("%d", &arr[i][j]);
}
}
int isIdentity = 1; // Giả sử là ma trận đơn vị
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if ((i == j && arr[i][j] != 1) || (i != j && arr[i][j] != 0)) {
isIdentity = 0;
break;
}
}
if (!isIdentity) break;
}
if (isIdentity) {
printf("Đây là ma trận đơn vị.n");
} else {
printf("Đây không phải ma trận đơn vị.n");
}
return 0;
}
Bài tập 7: Tìm giá trị nhỏ nhất trên mỗi hàng của ma trận
#include <stdio.h>
#include <limits.h>
int main() {
int rows, cols;
printf("Nhập số hàng và số cột: ");
scanf("%d %d", &rows, &cols);
int arr[50][50];
printf("Nhập các phần tử của mảng:n");
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
scanf("%d", &arr[i][j]);
}
}
printf("Giá trị nhỏ nhất trên mỗi hàng:n");
for (int i = 0; i < rows; i++) {
int minInRow = INT_MAX;
for (int j = 0; j < cols; j++) {
if (arr[i][j] < minInRow) {
minInRow = arr[i][j];
}
}
printf("Hàng %d: %dn", i, minInRow);
}
return 0;
}
Bài tập 8: Tính tổng hai ma trận
#include <stdio.h>
int main() {
int rows, cols;
printf("Nhập số hàng và số cột của hai ma trận: ");
scanf("%d %d", &rows, &cols);
int A[50][50], B[50][50], C[50][50];
printf("Nhập các phần tử của ma trận A:n");
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
scanf("%d", &A[i][j]);
}
}
printf("Nhập các phần tử của ma trận B:n");
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
scanf("%d", &B[i][j]);
}
}
// Tính tổng hai ma trận
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
C[i][j] = A[i][j] + B[i][j];
}
}
printf("Ma trận tổng C = A + B là:n");
for (int i = 0; i < rows; i++) {
for (int j = 0; j < cols; j++) {
printf("%d ", C[i][j]);
}
printf("n");
}
return 0;
}
Để tìm hiểu thêm về các phép toán ma trận khác, bạn có thể xem hướng dẫn của Photoshop về cách sử dụng ma trận trong xử lý ảnh.
Bài tập 9: Kiểm tra ma trận có đối xứng qua đường chéo chính không
#include <stdio.h>
int main() {
int n;
printf("Nhập kích thước ma trận vuông: ");
scanf("%d", &n);
int arr[50][50];
printf("Nhập các phần tử của ma trận:n");
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
scanf("%d", &arr[i][j]);
}
}
int isSymmetric = 1; // Giả sử ma trận đối xứng
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
if (arr[i][j] != arr[j][i]) {
isSymmetric = 0;
break;
}
}
if (!isSymmetric) break;
}
if (isSymmetric) {
printf("Ma trận đối xứng qua đường chéo chính.n");
} else {
printf("Ma trận không đối xứng qua đường chéo chính.n");
}
return 0;
}
Bài tập 10: Tính tích hai ma trận
#include <stdio.h>
int main() {
int rowsA, colsA, rowsB, colsB;
printf("Nhập số hàng và số cột của ma trận A: ");
scanf("%d %d", &rowsA, &colsA);
printf("Nhập số hàng và số cột của ma trận B: ");
scanf("%d %d", &rowsB, &colsB);
if (colsA != rowsB) {
printf("Không thể nhân hai ma trận này!n");
return 1;
}
int A[50][50], B[50][50], C[50][50];
printf("Nhập các phần tử của ma trận A:n");
for (int i = 0; i < rowsA; i++) {
for (int j = 0; j < colsA; j++) {
scanf("%d", &A[i][j]);
}
}
printf("Nhập các phần tử của ma trận B:n");
for (int i = 0; i < rowsB; i++) {
for (int j = 0; j < colsB; j++) {
scanf("%d", &B[i][j]);
}
}
// Khởi tạo ma trận kết quả C với giá trị 0
for (int i = 0; i < rowsA; i++) {
for (int j = 0; j < colsB; j++) {
C[i][j] = 0;
}
}
// Tính tích hai ma trận
for (int i = 0; i < rowsA; i++) {
for (int j = 0; j < colsB; j++) {
for (int k = 0; k < colsA; k++) {
C[i][j] += A[i][k] * B[k][j];
}
}
}
printf("Ma trận tích C = A * B là:n");
for (int i = 0; i < rowsA; i++) {
for (int j = 0; j < colsB; j++) {
printf("%d ", C[i][j]);
}
printf("n");
}
return 0;
}
So sánh mảng 1 chiều và mảng 2 chiều
Đặc điểm | Mảng 1 chiều | Mảng 2 chiều |
---|---|---|
Cấu trúc | Tuyến tính | Ma trận (hàng x cột) |
Khai báo | dataType arrayName[size]; | dataType arrayName[rows][cols]; |
Truy xuất | arrayName[index] | arrayName |
Bộ nhớ | Liên tục | Liên tục theo hàng |
Ứng dụng | Danh sách, dãy số | Bảng dữ liệu, ma trận, hình ảnh |
Câu hỏi thường gặp về mảng 2 chiều ❓
- Mảng 2 chiều được lưu trữ như thế nào trong bộ nhớ?
Trong C/C++, mảng 2 chiều được lưu trữ theo thứ tự hàng (row-major order). Điều này có nghĩa là các phần tử của hàng đầu tiên được lưu trữ liên tiếp, sau đó đến các phần tử của hàng thứ hai, và cứ thế. - Làm thế nào để cấp phát động mảng 2 chiều trong C?
Sử dụng con trỏ đến con trỏ và hàm malloc() hoặc calloc():int **matrix = (int **)malloc(rows * sizeof(int *)); for (int i = 0; i < rows; i++) { matrix[i] = (int *)malloc(cols * sizeof(int)); }
- Có thể truyền mảng 2 chiều với kích thước bất kỳ vào hàm không?
Trong C, khi truyền mảng 2 chiều vào hàm, bạn phải chỉ định ít nhất số cột. Trong C++ hiện đại, bạn có thể sử dụng vector> để truyền mảng 2 chiều với kích thước bất kỳ.
Kết luận
Mảng 2 chiều là một cấu trúc dữ liệu cực kỳ quan trọng trong lập trình C/C++, đặc biệt cho những ứng dụng liên quan đến ma trận, xử lý ảnh, trò chơi, và nhiều lĩnh vực khác. Qua bài viết này, chúng ta đã tìm hiểu về cách khai báo, khởi tạo, truy xuất và thao tác với mảng 2 chiều, cùng với 10 bài tập thực hành có lời giải chi tiết.
Hãy thực hành đều đặn với các bài tập này để nắm vững kiến thức. Nếu bạn cần tìm hiểu thêm về các công cụ thiết kế đồ họa, đừng quên ghé thăm Phần mềm đồ họa để tìm hiểu về 3DS MAX, Autocad, Illustrator và nhiều phần mềm đồ họa khác. Chúc các bạn học tập hiệu quả!