Map - Ánh xạ Key-Value
📖 Giới thiệu
Map lưu trữ các cặp key-value, trong đó mỗi key là duy nhất và được sắp xếp tự động. Được implement bằng cây cân bằng, cung cấp truy cập O(log n).
Ví dụ đơn giản đầu tiên
cpp
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main() {
map<string, int> scores;
// Thêm cặp key-value
scores["Alice"] = 95;
scores["Bob"] = 87;
scores["Charlie"] = 92;
// Truy cập value thông qua key
cout << "Điểm của Alice: " << scores["Alice"] << endl;
// Duyệt map (tự động sắp xếp theo key)
cout << "Bảng điểm:" << endl;
for (const auto& pair : scores) {
cout << pair.first << ": " << pair.second << endl;
}
return 0;
}🔧 Cú pháp
Khai báo Map
cpp
#include <map>
map<string, int> string_to_int; // Map string → int
map<int, string> int_to_string; // Map int → string
map<string, vector<int>> groups; // Map string → vector
multimap<string, int> duplicates; // Cho phép key trùng lặpCác phương thức chính
cpp
// Thêm/sửa
map[key] = value; // Insert hoặc update
map.insert({key, value}); // Insert pair
map.emplace(key, value); // Construct in-place
// Truy cập
map[key]; // Truy cập (tạo nếu chưa có)
map.at(key); // Truy cập an toàn (throw nếu không tồn tại)
// Tìm kiếm/xóa
map.find(key); // Trả về iterator
map.count(key); // 0 hoặc 1
map.erase(key); // Xóa theo key
map.contains(key); // C++20: true/false💻 Ví dụ minh họa
Ví dụ 1: Hệ thống quản lý sinh viên
cpp
#include <iostream>
#include <map>
#include <string>
#include <vector>
#include <iomanip>
using namespace std;
struct ThongTinSinhVien {
string ho_ten;
int tuoi;
string khoa;
vector<double> diem_so;
ThongTinSinhVien() = default;
ThongTinSinhVien(string ten, int t, string k)
: ho_ten(ten), tuoi(t), khoa(k) {}
double tinh_diem_trung_binh() const {
if (diem_so.empty()) return 0.0;
double tong = 0;
for (double diem : diem_so) {
tong += diem;
}
return tong / diem_so.size();
}
void hien_thi() const {
cout << " Họ tên: " << ho_ten << endl;
cout << " Tuổi: " << tuoi << endl;
cout << " Khoa: " << khoa << endl;
cout << " Điểm: ";
for (double diem : diem_so) {
cout << fixed << setprecision(1) << diem << " ";
}
cout << endl;
cout << " Điểm TB: " << fixed << setprecision(2) << tinh_diem_trung_binh() << endl;
}
};
class QuanLySinhVien {
private:
map<string, ThongTinSinhVien> sinh_vien_database;
map<string, vector<string>> sinh_vien_theo_khoa;
map<string, int> thong_ke_khoa;
public:
void them_sinh_vien(const string& ma_sv, const string& ho_ten, int tuoi, const string& khoa) {
if (sinh_vien_database.find(ma_sv) != sinh_vien_database.end()) {
cout << "❌ Sinh viên với mã " << ma_sv << " đã tồn tại!" << endl;
return;
}
sinh_vien_database[ma_sv] = ThongTinSinhVien(ho_ten, tuoi, khoa);
sinh_vien_theo_khoa[khoa].push_back(ma_sv);
thong_ke_khoa[khoa]++;
cout << "✅ Đã thêm sinh viên: " << ho_ten << " (Mã: " << ma_sv << ")" << endl;
}
void them_diem(const string& ma_sv, double diem) {
auto it = sinh_vien_database.find(ma_sv);
if (it == sinh_vien_database.end()) {
cout << "❌ Không tìm thấy sinh viên với mã: " << ma_sv << endl;
return;
}
if (diem < 0 || diem > 10) {
cout << "❌ Điểm không hợp lệ! (0-10)" << endl;
return;
}
it->second.diem_so.push_back(diem);
cout << "✅ Đã thêm điểm " << diem << " cho sinh viên " << ma_sv << endl;
}
void xem_thong_tin_sinh_vien(const string& ma_sv) {
auto it = sinh_vien_database.find(ma_sv);
if (it == sinh_vien_database.end()) {
cout << "❌ Không tìm thấy sinh viên với mã: " << ma_sv << endl;
return;
}
cout << "\n📋 THÔNG TIN SINH VIÊN " << ma_sv << ":" << endl;
it->second.hien_thi();
}
void xem_sinh_vien_theo_khoa(const string& khoa) {
auto it = sinh_vien_theo_khoa.find(khoa);
if (it == sinh_vien_theo_khoa.end() || it->second.empty()) {
cout << "❌ Không có sinh viên nào trong khoa: " << khoa << endl;
return;
}
cout << "\n📚 SINH VIÊN KHOA " << khoa << " (" << it->second.size() << " sinh viên):" << endl;
cout << string(60, '-') << endl;
for (const string& ma_sv : it->second) {
auto sv_it = sinh_vien_database.find(ma_sv);
if (sv_it != sinh_vien_database.end()) {
cout << "Mã SV: " << ma_sv << " | " << sv_it->second.ho_ten
<< " | ĐTB: " << fixed << setprecision(2)
<< sv_it->second.tinh_diem_trung_binh() << endl;
}
}
cout << string(60, '-') << endl;
}
void xep_hang_theo_diem() {
if (sinh_vien_database.empty()) {
cout << "📊 Không có dữ liệu sinh viên!" << endl;
return;
}
// Tạo vector để sắp xếp
vector<pair<double, string>> xep_hang;
for (const auto& pair : sinh_vien_database) {
double dtb = pair.second.tinh_diem_trung_binh();
if (dtb > 0) { // Chỉ xếp hạng những SV có điểm
xep_hang.push_back({dtb, pair.first});
}
}
// Sắp xếp theo điểm giảm dần
sort(xep_hang.rbegin(), xep_hang.rend());
cout << "\n🏆 XẾP HẠNG SINH VIÊN THEO ĐIỂM TRUNG BÌNH:" << endl;
cout << string(70, '=') << endl;
cout << setw(5) << "Hạng" << setw(10) << "Mã SV" << setw(20) << "Họ tên"
<< setw(15) << "Khoa" << setw(10) << "ĐTB" << endl;
cout << string(70, '-') << endl;
for (int i = 0; i < xep_hang.size(); i++) {
const string& ma_sv = xep_hang[i].second;
auto sv_it = sinh_vien_database.find(ma_sv);
if (sv_it != sinh_vien_database.end()) {
cout << setw(5) << (i + 1)
<< setw(10) << ma_sv
<< setw(20) << sv_it->second.ho_ten
<< setw(15) << sv_it->second.khoa
<< setw(10) << fixed << setprecision(2) << xep_hang[i].first << endl;
}
}
cout << string(70, '=') << endl;
}
void thong_ke_tong_quan() {
cout << "\n📊 THỐNG KÊ TỔNG QUAN:" << endl;
cout << "Tổng số sinh viên: " << sinh_vien_database.size() << endl;
cout << "Số khoa: " << thong_ke_khoa.size() << endl;
cout << "\nPhân bố sinh viên theo khoa:" << endl;
for (const auto& pair : thong_ke_khoa) {
cout << " " << pair.first << ": " << pair.second << " sinh viên" << endl;
}
// Thống kê điểm
double tong_diem = 0;
int so_sv_co_diem = 0;
double diem_cao_nhat = 0;
double diem_thap_nhat = 10;
for (const auto& pair : sinh_vien_database) {
double dtb = pair.second.tinh_diem_trung_binh();
if (dtb > 0) {
tong_diem += dtb;
so_sv_co_diem++;
diem_cao_nhat = max(diem_cao_nhat, dtb);
diem_thap_nhat = min(diem_thap_nhat, dtb);
}
}
if (so_sv_co_diem > 0) {
cout << "\nThống kê điểm:" << endl;
cout << " Điểm trung bình chung: " << fixed << setprecision(2)
<< (tong_diem / so_sv_co_diem) << endl;
cout << " Điểm cao nhất: " << diem_cao_nhat << endl;
cout << " Điểm thấp nhất: " << diem_thap_nhat << endl;
}
}
void tim_sinh_vien_theo_ten(const string& tu_khoa) {
cout << "\n🔍 TÌM KIẾM SINH VIÊN THEO TÊN: \"" << tu_khoa << "\"" << endl;
bool tim_thay = false;
for (const auto& pair : sinh_vien_database) {
if (pair.second.ho_ten.find(tu_khoa) != string::npos) {
cout << " Mã SV: " << pair.first << " | " << pair.second.ho_ten
<< " | Khoa: " << pair.second.khoa << endl;
tim_thay = true;
}
}
if (!tim_thay) {
cout << " Không tìm thấy sinh viên nào!" << endl;
}
}
void xoa_sinh_vien(const string& ma_sv) {
auto it = sinh_vien_database.find(ma_sv);
if (it == sinh_vien_database.end()) {
cout << "❌ Không tìm thấy sinh viên với mã: " << ma_sv << endl;
return;
}
string khoa = it->second.khoa;
string ho_ten = it->second.ho_ten;
// Xóa khỏi database chính
sinh_vien_database.erase(it);
// Xóa khỏi danh sách theo khoa
auto& danh_sach_khoa = sinh_vien_theo_khoa[khoa];
danh_sach_khoa.erase(remove(danh_sach_khoa.begin(), danh_sach_khoa.end(), ma_sv),
danh_sach_khoa.end());
// Cập nhật thống kê
thong_ke_khoa[khoa]--;
if (thong_ke_khoa[khoa] == 0) {
thong_ke_khoa.erase(khoa);
sinh_vien_theo_khoa.erase(khoa);
}
cout << "🗑️ Đã xóa sinh viên: " << ho_ten << " (Mã: " << ma_sv << ")" << endl;
}
size_t so_luong_sinh_vien() const {
return sinh_vien_database.size();
}
};
int main() {
cout << "=== HỆ THỐNG QUẢN LÝ SINH VIÊN ===" << endl;
QuanLySinhVien ql;
// Thêm sinh viên
cout << "\n--- Thêm sinh viên ---" << endl;
ql.them_sinh_vien("SV001", "Nguyễn Văn A", 20, "Công nghệ thông tin");
ql.them_sinh_vien("SV002", "Trần Thị B", 19, "Kinh tế");
ql.them_sinh_vien("SV003", "Lê Văn C", 21, "Công nghệ thông tin");
ql.them_sinh_vien("SV004", "Phạm Thị D", 20, "Luật");
ql.them_sinh_vien("SV005", "Hoàng Văn E", 22, "Công nghệ thông tin");
// Thêm điểm
cout << "\n--- Thêm điểm ---" << endl;
ql.them_diem("SV001", 8.5);
ql.them_diem("SV001", 7.8);
ql.them_diem("SV001", 9.2);
ql.them_diem("SV002", 7.5);
ql.them_diem("SV002", 8.0);
ql.them_diem("SV003", 9.0);
ql.them_diem("SV003", 8.8);
ql.them_diem("SV003", 9.5);
ql.them_diem("SV004", 6.5);
ql.them_diem("SV004", 7.0);
// Xem thông tin
ql.xem_thong_tin_sinh_vien("SV001");
// Xem theo khoa
ql.xem_sinh_vien_theo_khoa("Công nghệ thông tin");
// Xếp hạng
ql.xep_hang_theo_diem();
// Thống kê
ql.thong_ke_tong_quan();
// Tìm kiếm
ql.tim_sinh_vien_theo_ten("Nguyễn");
return 0;
}🏋️ Thực hành
Bài tập 1: Word Frequency Counter
Đếm tần suất xuất hiện của từ trong text
Bài tập 2: Phone Book System
Hệ thống danh bạ với tìm kiếm multiple criteria
Bài tập 3: Cache System
LRU Cache implementation với map
📋 Tóm tắt
- Map: Key-value pairs, keys duy nhất và sorted
- Complexity: Insert/Find/Erase O(log n)
- Multimap: Cho phép duplicate keys
- Unordered_map: Hash-based, O(1) average
Bài tiếp theo: Algorithms - STL algorithm functions.