Bài 12.5: Bài tập thực hành ứng dụng mảng 1 chiều trong C++

Bài 12.5: Bài tập thực hành ứng dụng mảng 1 chiều trong C++
Chào mừng bạn đến với bài thực hành quan trọng về mảng một chiều trong chuỗi bài học C++ của chúng ta! Sau khi đã nắm vững các khái niệm cơ bản về cách khai báo, truy cập và khởi tạo mảng, đây là lúc chúng ta áp dụng kiến thức đó vào các bài tập thực tế. Thực hành chính là cầu nối vững chắc giữa lý thuyết và khả năng giải quyết vấn đề thực tế trong lập trình.
Mảng một chiều là một trong những cấu trúc dữ liệu cơ bản nhất nhưng lại cực kỳ mạnh mẽ và được sử dụng rộng rãi. Việc thành thạo thao tác với mảng là nền tảng quan trọng cho việc học các cấu trúc dữ liệu phức tạp hơn sau này.
Bài tập 1: Nhập và Xuất mảng cơ bản
Yêu cầu bài toán: Viết chương trình C++ cho phép người dùng nhập vào số lượng phần tử n
, sau đó nhập n
số nguyên và lưu trữ chúng vào một mảng. Cuối cùng, in ra toàn bộ các phần tử của mảng vừa nhập.
Ý tưởng giải quyết: Chúng ta sẽ cần:
- Hỏi người dùng kích thước mảng.
- Khai báo một mảng (hoặc
vector
) với kích thước đó. - Sử dụng vòng lặp
for
để đọc từng phần tử từ người dùng và gán vào mảng. - Sử dụng một vòng lặp
for
khác để duyệt qua mảng và in từng phần tử ra màn hình.
Mã nguồn minh họa:
#include <iostream>
#include <vector>
int main() {
using namespace std;
int n;
cout << "Nhap so luong phan tu cua mang: ";
cin >> n;
vector<int> a(n);
cout << "Nhap " << n << " so nguyen vao mang:\n";
for (int i = 0; i < n; ++i) {
cout << "Phan tu thu " << i << ": ";
cin >> a[i];
}
cout << "\nCac phan tu trong mang la:\n";
for (int i = 0; i < n; ++i) {
cout << a[i] << " ";
}
cout << endl;
return 0;
}
Output ví dụ:
Nhap so luong phan tu cua mang: 3
Nhap 3 so nguyen vao mang:
Phan tu thu 0: 10
Phan tu thu 1: 20
Phan tu thu 2: 30
Cac phan tu trong mang la:
10 20 30
Giải thích code:
- Chúng ta bao gồm thư viện
<iostream>
cho nhập/xuất và<vector>
để sử dụngvector
.vector
giống như mảng nhưng linh hoạt hơn về kích thước. cout << "Nhap so luong phan tu..."
vàcin >> n;
để lấy kích thước mảng từ người dùng.vector<int> a(n);
khai báo một vector têna
chứa các số nguyên và có kích thước làn
.- Vòng lặp
for (int i = 0; i < n; ++i)
đầu tiên chạy từi = 0
đếnn-1
. Trong mỗi lần lặp,cin >> a[i];
đọc một số nguyên từ người dùng và lưu vào phần tử thứi
của vector. - Vòng lặp
for
thứ hai cũng chạy từi = 0
đếnn-1
. Trong mỗi lần lặp,cout << a[i] << " ";
in ra phần tử thứi
của vector, theo sau là một khoảng trắng để các số cách nhau. endl;
kết thúc dòng output cuối cùng.
Bài tập 2: Tính tổng và Trung bình cộng các phần tử
Yêu cầu bài toán: Cho một mảng các số nguyên. Tính tổng và trung bình cộng của tất cả các phần tử trong mảng đó.
Ý tưởng giải quyết:
- Duyệt qua tất cả các phần tử trong mảng.
- Sử dụng một biến để lưu trữ tổng. Cộng giá trị của từng phần tử vào biến tổng này.
- Sau khi duyệt xong, chia tổng cho số lượng phần tử để tính trung bình cộng. Cần cẩn thận với phép chia số nguyên.
Mã nguồn minh họa:
#include <iostream>
#include <vector>
int main() {
using namespace std;
vector<int> a = {10, 25, 5, 30, 15};
long long tong = 0;
for (size_t i = 0; i < a.size(); ++i) {
tong += a[i];
}
double tb = 0.0;
if (!a.empty()) {
tb = static_cast<double>(tong) / a.size();
}
cout << "Mang: ";
for (size_t i = 0; i < a.size(); ++i) {
cout << a[i] << (i == a.size() - 1 ? "" : " ");
}
cout << endl;
cout << "Tong cac phan tu: " << tong << endl;
cout << "Trung binh cong cac phan tu: " << tb << endl;
return 0;
}
Output ví dụ:
Mang: 10 25 5 30 15
Tong cac phan tu: 85
Trung binh cong cac phan tu: 17
Giải thích code:
- Chúng ta khai báo một
vector<int> a
với các giá trị mẫu. - Biến
tong
được khởi tạo bằng 0. Chúng ta sử dụng kiểulong long
chotong
để đảm bảo nó có thể chứa tổng lớn mà không bị tràn số (integer overflow). - Vòng lặp
for (size_t i = 0; i < a.size(); ++i)
duyệt qua từng phần tử.a.size()
trả về số lượng phần tử trong vector (kích thước mảng). Kiểusize_t
thường dùng cho kích thước và chỉ số. tong += a[i];
cộng giá trị của phần tử hiện tại (a[i]
) vàotong
.- Trước khi tính trung bình, chúng ta kiểm tra
!a.empty()
để đảm bảo mảng không rỗng, tránh lỗi chia cho 0. tb = static_cast<double>(tong) / a.size();
tính trung bình.static_cast<double>(tong)
ép kiểu tổng sang số thực trước khi chia, đảm bảo kết quả là số thực (trung bình cộng thường có phần thập phân).- Cuối cùng, in ra mảng, tổng và trung bình cộng. Vòng lặp in mảng sử dụng toán tử ba ngôi
(i == a.size() - 1 ? "" : " ")
để không in khoảng trắng sau phần tử cuối cùng.
Bài tập 3: Tìm phần tử lớn nhất và nhỏ nhất
Yêu cầu bài toán: Tìm giá trị phần tử lớn nhất và giá trị phần tử nhỏ nhất trong một mảng các số nguyên.
Ý tưởng giải quyết:
- Giả định rằng phần tử đầu tiên của mảng vừa là lớn nhất, vừa là nhỏ nhất ban đầu.
- Duyệt qua các phần tử còn lại của mảng (bắt đầu từ phần tử thứ hai).
- Trong mỗi lần lặp, so sánh phần tử hiện tại với giá trị lớn nhất và nhỏ nhất đã ghi nhận. Cập nhật nếu tìm thấy giá trị mới lớn hơn hoặc nhỏ hơn.
Mã nguồn minh họa:
#include <iostream>
#include <vector>
int main() {
using namespace std;
vector<int> a = {10, 4, 8, 20, 1, 15};
if (a.empty()) {
cout << "Mang rong, khong the tim max/min." << endl;
return 1;
}
int lonNhat = a[0];
int nhoNhat = a[0];
for (size_t i = 1; i < a.size(); ++i) {
if (a[i] > lonNhat) {
lonNhat = a[i];
}
if (a[i] < nhoNhat) {
nhoNhat = a[i];
}
}
cout << "Mang: ";
for (int gt : a) {
cout << gt << " ";
}
cout << endl;
cout << "Phan tu lon nhat: " << lonNhat << endl;
cout << "Phan tu nho nhat: " << nhoNhat << endl;
return 0;
}
Output ví dụ:
Mang: 10 4 8 20 1 15
Phan tu lon nhat: 20
Phan tu nho nhat: 1
Giải thích code:
- Chúng ta kiểm tra nếu
a.empty()
để tránh truy cập phần tử khi mảng rỗng. - Biến
lonNhat
vànhoNhat
được khởi tạo bằng giá trị của phần tử đầu tiêna[0]
. Đây là điểm bắt đầu so sánh. - Vòng lặp
for (size_t i = 1; i < a.size(); ++i)
bắt đầu từ chỉ số 1 (phần tử thứ hai) vì phần tử 0 đã được dùng để khởi tạo. - Trong vòng lặp, chúng ta so sánh
a[i]
vớilonNhat
vànhoNhat
. Nếua[i]
lớn hơnlonNhat
hiện tại,lonNhat
được cập nhật. Tương tự vớinhoNhat
. - Đoạn code in mảng sử dụng vòng lặp range-based for loop (
for (int gt : a)
), đây là cách gọn gàng để duyệt qua tất cả các phần tử của container nhưvector
.
Bài tập 4: Đếm số lần xuất hiện của một giá trị
Yêu cầu bài toán: Cho một mảng và một giá trị cụ thể. Đếm xem giá trị đó xuất hiện bao nhiêu lần trong mảng.
Ý tưởng giải quyết:
- Duyệt qua tất cả các phần tử trong mảng.
- Sử dụng một biến đếm, khởi tạo bằng 0.
- Trong mỗi lần lặp, so sánh phần tử hiện tại với giá trị cần đếm. Nếu chúng bằng nhau, tăng biến đếm lên 1.
Mã nguồn minh họa:
#include <iostream>
#include <vector>
int main() {
using namespace std;
vector<int> a = {1, 5, 3, 5, 2, 5, 8, 5};
int giaTri = 5;
int soLan = 0;
for (size_t i = 0; i < a.size(); ++i) {
if (a[i] == giaTri) {
soLan++;
}
}
cout << "Mang: ";
for (int gt : a) {
cout << gt << " ";
}
cout << endl;
cout << "So lan xuat hien cua gia tri " << giaTri << " la: " << soLan << endl;
return 0;
}
Output ví dụ:
Mang: 1 5 3 5 2 5 8 5
So lan xuat hien cua gia tri 5 la: 4
Giải thích code:
- Chúng ta khai báo
vector<int> a
và biếngiaTri
là giá trị chúng ta muốn đếm. - Biến
soLan
được khởi tạo bằng 0 để bắt đầu đếm. - Vòng lặp
for (size_t i = 0; i < a.size(); ++i)
duyệt qua từng phần tử. - Trong vòng lặp, điều kiện
if (a[i] == giaTri)
kiểm tra xem phần tử hiện tại có bằng giá trị mục tiêu không. - Nếu bằng,
soLan++
tăng biến đếm lên 1.
Bài tập 5: Sắp xếp mảng
Yêu cầu bài toán: Sắp xếp các phần tử trong mảng theo thứ tự tăng dần.
Ý tưởng giải quyết:
Mặc dù có nhiều thuật toán sắp xếp khác nhau (như Bubble Sort, Selection Sort, Merge Sort...), cách đơn giản nhất và hiệu quả nhất trong C++ là sử dụng hàm sắp xếp có sẵn trong thư viện chuẩn (sort
).
Mã nguồn minh họa:
#include <iostream>
#include <vector>
#include <algorithm>
int main() {
using namespace std;
vector<int> a = {12, 4, 9, 2, 18, 7};
cout << "Mang truoc khi sap xep: ";
for (int gt : a) {
cout << gt << " ";
}
cout << endl;
sort(a.begin(), a.end());
cout << "Mang sau khi sap xep tang dan: ";
for (int gt : a) {
cout << gt << " ";
}
cout << endl;
return 0;
}
Output ví dụ:
Mang truoc khi sap xep: 12 4 9 2 18 7
Mang sau khi sap xep tang dan: 2 4 7 9 12 18
Giải thích code:
- Chúng ta bao gồm thư viện
<algorithm>
chứa hàmsort
. sort(a.begin(), a.end());
là lời gọi hàm sắp xếp.a.begin()
vàa.end()
là các iterator xác định phạm vi cần sắp xếp (từ đầu đến cuối vector).- Mặc định,
sort
sắp xếp các phần tử theo thứ tự tăng dần. Nó thay đổi trực tiếp (in-place) vectora
. - Sau khi gọi
sort
, vectora
đã được sắp xếp. Vòng lặpfor-each
được sử dụng để in ra mảng đã sắp xếp.
Bài tập 6: Tìm kiếm một giá trị trong mảng (Linear Search)
Yêu cầu bài toán: Kiểm tra xem một giá trị cụ thể có tồn tại trong mảng hay không. Nếu có, cho biết nó xuất hiện lần đầu tiên tại chỉ số nào.
Ý tưởng giải quyết: Phương pháp tìm kiếm đơn giản nhất là tìm kiếm tuyến tính (Linear Search):
- Duyệt qua từng phần tử của mảng từ đầu đến cuối.
- So sánh phần tử hiện tại với giá trị cần tìm.
- Nếu tìm thấy, ta biết giá trị đó tồn tại và có thể trả về chỉ số hiện tại rồi kết thúc tìm kiếm.
- Nếu duyệt hết mảng mà không tìm thấy, giá trị đó không tồn tại trong mảng.
Mã nguồn minh họa:
#include <iostream>
#include <vector>
int main() {
using namespace std;
vector<int> a = {15, 8, 22, 10, 5, 22, 30};
int timGT = 22;
int khongCoGT = 99;
cout << "Mang: ";
for (int gt : a) {
cout << gt << " ";
}
cout << endl;
int viTri = -1;
for (size_t i = 0; i < a.size(); ++i) {
if (a[i] == timGT) {
viTri = i;
break;
}
}
if (viTri != -1) {
cout << "Gia tri " << timGT << " duoc tim thay lan dau tien tai chi so: " << viTri << endl;
} else {
cout << "Gia tri " << timGT << " khong ton tai trong mang." << endl;
}
viTri = -1; // Reset viTri cho lan tim kiem tiep theo
for (size_t i = 0; i < a.size(); ++i) {
if (a[i] == khongCoGT) {
viTri = i;
break;
}
}
if (viTri != -1) {
cout << "Gia tri " << khongCoGT << " duoc tim thay lan dau tien tai chi so: " << viTri << endl;
} else {
cout << "Gia tri " << khongCoGT << " khong ton tai trong mang." << endl;
}
return 0;
}
Output ví dụ:
Mang: 15 8 22 10 5 22 30
Gia tri 22 duoc tim thay lan dau tien tai chi so: 2
Gia tri 99 khong ton tai trong mang.
Giải thích code:
- Chúng ta khai báo
vector<int> a
,timGT
(giá trị tìm thấy) vàkhongCoGT
(giá trị không tìm thấy). - Biến
viTri
được khởi tạo bằng -1. Chúng ta dùng -1 như một chỉ báo rằng giá trị chưa được tìm thấy. - Vòng lặp
for (size_t i = 0; i < a.size(); ++i)
duyệt qua từng phần tử. if (a[i] == timGT)
kiểm tra xem phần tử hiện tại có bằng giá trị cần tìm không.- Nếu có, chúng ta gán
i
vàoviTri
và sử dụngbreak;
để thoát khỏi vòng lặp ngay lập tức (vì yêu cầu là tìm lần đầu tiên xuất hiện). Nếu không cóbreak;
, nó sẽ tiếp tục duyệt vàviTri
sẽ lưu chỉ số của lần xuất hiện cuối cùng. - Sau vòng lặp, chúng ta kiểm tra giá trị của
viTri
. Nếu nó vẫn là -1, tức là không tìm thấy. Ngược lại,viTri
chứa chỉ số của lần xuất hiện đầu tiên. - Đoạn code được lặp lại để minh họa cả trường hợp tìm thấy và không tìm thấy giá trị.
Comments