Map là gì?
Các lớp vector, list thuộc cấu trúc Sequence Containers (cấu trúc tuần tự), riêng với lớp map
thuộc 1 cấu trúc khác đó là Associative Containers (cấu trúc liên kết), là kiểu dữ liệu cho phép quản lý 1 cặp key/value
- khóa và giá trị, nghĩa là muốn xác định được nội dung value
thì phải biết được vị trí key
mà map
đang quản lý.
Nội dung
Nếu như lớp map
quản lý cặp đối tượng key/value
, vậy đối tượng nào sinh ra được cặp đối tượng đó. Để sinh ra cặp đối tượng key/value
cần sử dụng lớp pair
, lớp pair
nằm trong thư viện utility
. Trước khi tìm hiểu về lớp map
cần biết về lớp pair
.
[A] Lớp pair
pair
cho phép gộp 2 đối tượng thành 1 cặp, 2 đối tượng có thẻ cùng kiểu hoặc khác kiểu, với thuộc tính first
là key
và second
là value
.
Cú pháp khai báo: pair<valueType1, valueType2> variableName;
Ví dụ: pair<string, string> dictionary;
pair
có các constructor như:
- default constructor
- copy constructor
- initialization constructor
Ví dụ:
// default constructor pair<int, char*> defaultPair;
// initialization constructor pair<int, char*> initPair(0, "a");
// copy constructor pair<int, char*> copyPair(pair1);
Lớp pair
có các thuộc tính first
và second
cho phép lấy dữ liệu
pair<string, string> word("eat", "an"); cout << word.first << " " << word.second;
[B] Lớp map
Lớp map
nằm trong thư viện map
vì vậy muốn sử dụng trước tiên phải #include <map>
.
Cú pháp khai báo: map<valueType1, valueType2> variableName;
Ví dụ:
map<string, string> dictionary; dictionary["eat"] = "an"; dictionary["sleep"] = "ngu";
Biến dictionary
được khai báo với cặp dữ liệu là <string, string>
, vì vậy:
key
củadictionary
phải là kiểustring
-"eat"
"sleep"
...value
củadictionary
phải là kiểustring
-"an"
"ngu"
...
Lớp map
cũng giống như những lớp vector
, list
đều được định nghĩa các hàm thành viên hỗ trợ cho việc truy xuất, lấy kích thước, các constructor đã được override, …
Các phương thức thường dùng trong map
Constructor
Cũng giống với những lớp vector
, list
đều có:
- default constructor
- ranger constructor
- copy constructor.
Các hàm thành viên này hoạt động hoàn toàn giống với lớp vector
, list
.
Ví dụ:
// default constructor map<char, int> character0; character0['a'] = 97; character0['b'] = 98; character0['c'] = 99; character0['d'] = 100; // range constructor map<char, int> character1(character0.begin(), character0.end()); // copy constructor map<char, int> character2(character1);
Ngoài ra còn có operator=
cho phép các lớp map
có thể sao chép nội dung cấu trúc dữ liệu với nhau.
map<int, char*> map0, map1; map0[0] = "a"; map0[1] = "b"; map1 = map0;
Duyệt map
Lớp map
quản lý value
bằng key
, nếu trường hợp quên map
thì làm sao có thể truy xuất để lấy dữ liệu value
. Để giải quyết vấn đề trên trong lớp map
định nghĩa thao tác iterators cho phép truy xuất đến phần tử trong map
để lấy dữ liệu value
và key
cần thiết. Có các iterators đã được cung cấp như: begin()
, end()
, rbegin()
, rend()
, ... chúng hoạt động như nhau nhưng chỉ khác phần tử truy cập ở vị trí nào trong lớp map
.
Ví dụ:
map<int, char*> texes; texts[0] = "ab"; texts[1] = "bc"; texts[0] = "cd"; map<int, char*>::iterator i; for (i = texts.begin(); i != texts.end(); i++) cout << *i << endl;
// output (0, "cd"), (1, "bc")
Kết quả tại sao không phải là: (0, "ab") (1, "bc")
hay (0, "ab") (1, "bc") (0, "cd")
, ... đó là do trong lớp map
quy định key
chỉ được tồn tại duy nhất (không được trùng), vì vậy khi khai báo ở dòng texts[0] = "cd";
sẽ làm thay đổi dữ liệu của texts[0]
từ "ab"
thành "cd"
.
Lấy kích thước của map
size()
cho phép lấy kích thước của map
.
Ví dụ:
map<int, char*> mymap, copymymap; mymap[0] = "a"; mymap[1] = "b"; mymap[0] = "c"; cout << mymap.size();
Kiểm tra map có rỗng hay không?
empty()
cho phép kiểm tra map
có rỗng hay không?
Ví dụ:
map<int, char*> mymap, copymymap; mymap[0] = "a"; mymap[1] = "b"; mymap[0] = "c"; if (copymymap.empty()) cout << "copymymap is empty";
Truy xuất theo chỉ số
[index]
hay at(index)
cho phép truy xuất trực tiếp đến key
của từng phần tử.
map<int, char*> mymap, copymymap; mymap[0] = "a"; mymap[1] = "b"; cout << mymap[1] << " " << mymap.at(0);
Thêm dữ liệu vào map
insert()
cho phép chèn thêm 1 đối tượng.
Ví dụ:
map<int, char*> mymap, copymymap; mymap[0] = "a"; mymap[1] = "b"; mymap[5] = "c"; // chèn vào copymymap cặp đối tượng (10, "c") copymymap.insert(pair<int, char*>(10, "c"));
// chèn (-1, "d") vào copymymap từ vị trí bắt đầu của copymymap copymymap.insert(copymymap.begin(), pair<int, char*>(-1, "d"));
// chèn mymap vào copymymap copymymap.insert(mymap.begin(), mymap.end());
// => copymymap = {(-1,"d"),(0,"a"),(1,"b"),(5,"c"),(10,"c")}
Lưu ý việc chèn ở vị trí nào thật ra là vô nghĩa, vì vị trí của nó phụ thuộc vào key
trong cặp đối tượng "key/ value", trong ví dụ trên thì "key" là kiểu số nguyên vì vậy vị trí của các cặp đối tượng key/value
sẽ được xác định theo các key
sắp xếp tăng dần.
Tìm kiếm phần tử
find()
cho phép tìm kiếm theo key của cặp giá trị key/value
Ví dụ:
map<int, char*> mymap; mymap[0] = "a"; mymap[1] = "b"; mymap[5] = "c"; mymap[9] = "e"; map<int, char*>::iterator var = mymap.find(5); // var -> (5,"c")
Xóa bỏ 1 phần tử trong map
erase()
cho phép xóa 1 phần tử.
Ví dụ:
map<int, char*> mymap, copymymap; mymap[0] = "a"; mymap[1] = "b"; mymap[5] = "c"; mymap[7] = "d"; mymap[9] = "e"; // xóa cặp đối tượng với "key" là 5 mymap.erase(5); // => mymap = {(0,"a"),(1,"b"),(7,"d"),(9,"e")} map<int, char*>::iterator var = mymap.begin(); // xóa cặp đối tượng mà var đang truy cập mymap.erase(var); // => mymap = {(1,"b"),(7,"d"),(9,"e")} var = mymap.find(7); // => var truy cập đến (7,"d") // xóa từ vị trí var đang truy cập cho đến (9,"e") mymap.erase(var, mymap.end()); // => mymap = {(1,"b")}
Xóa tất cả phần tử trong map
clear()
cho phép xóa tất cả phần tử.
Ví dụ:
map<int, char*> mymap; mymap[0] = "a"; mymap[1] = "b"; mymap[5] = "c"; mymap[7] = "d"; mymap[9] = "e"; mymap.clear(); // => mymap = {}
Hoán đổi nội dung 2 map
swap()
cho phép hoán đổi nội dung của 2 map
.
Ví dụ:
map<char,int> map1, map2; map1['x'] = 100; map1['y'] = 200; map2['a'] = 11; map2['b'] = 22; map2['c'] = 33; map1.swap(map2); // => map1 = {("x",11),("b",22),("c",33)} // => map2 = {("x",100),("y",200)}