Blog Origin: https://blog.csdn.net/sunshinewave/article/details/8067862
Detailed usage of map:
Map is an associative container of STL, which provides one-to-one data processing capability (the first can be called keyword, each keyword can only appear once in the map, and the second may be called the value of the keyword). Because of this feature, it completes the task of providing fast programming channels when we process one-to-one data. Let's talk about the organization of data in map. A red-black tree (a non-strictly balanced binary tree) is built in map. This tree has the function of sorting data automatically. So all data in map are orderly. We will see the benefits of ordering later.
The following example illustrates what a one-to-one data mapping is. For example, in a class, there is a one-to-one mapping relationship between each student's school number and his name. This model can be easily described by map. It is obvious that the school number is described by int and the name is described by string.
map<int, string> mapStudent;
1. The Constructive Function of Map
Map provides a total of six constructors. This one involves memory allocators. Skipping the list, we will touch on some map construction methods below. Here we will say that we usually construct a map by the following methods:
map<int, string> mapStudent;
2. Data insertion
After constructing the map container, we can insert data into it. Here are three ways to insert data:
The first is insert function to insert pair data. Here is an example. (Although the following code is handwritten, it should be compiled and passed under VC and GCC. You can run it to see what effect. Please add this statement under VC to shield 4786 warning # pragma warning (disable:4786).)
#include <map> #include <string> #include <iostream> using namespace std; int main() { map<int, string> mapStudent;//pair<int,string>p;p=make_pair(v1,v2); mapStudent.insert(pair<int, string>(1, "student_one")); mapStudent.insert(pair<int, string>(2, "student_two")); mapStudent.insert(pair<int, string>(3, "student_three")); map<int, string>::iterator iter; for(iter = mapStudent.begin(); iter != mapStudent.end(); iter++) { cout<<iter->first<<" "<<iter->second<<endl; } }
make_pair()// Return type is the corresponding pair type
A pair object can be generated without writing out the category
Example:
make_pair(1,'@')
It doesn't take much effort to write.
pair<int ,char>(1,'@')
The second is insert function to insert value_type data.
#include <map> #include <string> #include <iostream> using namespace std; int main() { map<int, string> mapStudent; mapStudent.insert(map<int, string>::value_type (1, "student_one")); mapStudent.insert(map<int, string>::value_type (2, "student_two")); mapStudent.insert(map<int, string>::value_type (3, "student_three")); map<int, string>::iterator iter; for(iter = mapStudent.begin(); iter != mapStudent.end(); iter++) { cout<<iter->first<<" "<<iter->second<<endl; } }
The third is to insert data in an array. Here's an example
#include <map> #include <string> #include <iostream> using namespace std; int main() { map<int, string> mapStudent; mapStudent[1] = "student_one"; mapStudent[2] = "student_two"; mapStudent[3] = "student_three"; map<int, string>::iterator iter; for(iter = mapStudent.begin(); iter != mapStudent.end(); iter++) { cout<<iter->first<<" "<<iter->second<<endl; } }
Although the above three usages can be used to insert data, they are different. Of course, the first one and the second are the same in effect. The insert function is used to insert data. The concept of uniqueness of the set is involved in the insertion of data. That is, when there is a key word in map, insert operation is not able to insert data, but it is not possible to insert data in array mode. Similarly, it can override the corresponding value of the previous keyword, which is explained by the program.
mapStudent.insert(map<int, string>::value_type (1, "student_one")); mapStudent.insert(map<int, string>::value_type (1, "student_two"));
After the above two statements are executed, the value of the keyword 1 in the map corresponds to "student_one", and the second statement does not take effect. This involves how we know whether insert statement is inserted successfully. We can use pair to achieve successful insert. The program is as follows.
Pair<map<int, string>::iterator, bool> Insert_Pair; Insert_Pair = mapStudent.insert(map<int, string>::value_type (1, "student_one"));
We know whether the insertion is successful by using the second variable of pair. Its first variable returns an iterator of map. If the insertion is successful, Insert_Pair.second should be true, otherwise false.
Here is the completion code to demonstrate whether the insertion is successful or not.
#include <map> #include <string> #include <iostream> using namespace std; int main() { map<int, string> mapStudent; Pair<map<int, string>::iterator, bool> Insert_Pair; Insert_Pair = mapStudent.insert(pair<int, string>(1, "student_one")); If(Insert_Pair.second == true) { cout<<"Insert Successfully"<<endl; } Else { cout<<"Insert Failure"<<endl; } Insert_Pair = mapStudent.insert(pair<int, string>(1, "student_two")); If(Insert_Pair.second == true) { cout<<"Insert Successfully"<<endl; } Else { cout<<"Insert Failure"<<endl; } map<int, string>::iterator iter; for(iter = mapStudent.begin(); iter != mapStudent.end(); iter++) { cout<<iter->first<<" "<<iter->second<<endl; } }
You can use the following program to see the effect of inserting arrays into data coverage
#include <map> #include <string> #include <iostream> using namespace std; int main() { map<int, string> mapStudent; mapStudent[1] = "student_one"; mapStudent[1] = "student_two"; mapStudent[2] = "student_three"; map<int, string>::iterator iter; for(iter = mapStudent.begin(); iter != mapStudent.end(); iter++) { cout<<iter->first<<" "<<iter->second<<endl; } }
3. The size of map
How do we know how many data have been inserted into the map? We can use the size function. The usage is as follows:
int nSize = mapStudent.size();
4. Data traversal
There are also three ways to traverse the map
The first is to use forward iterators, which are everywhere in the examples above.
The second one is the application of inverted iterator. The following example shows that in order to realize the effect, please run the program by yourself.
#include <map> #include <string> #include <iostream> using namespace std; int main() { map<int, string> mapStudent; mapStudent.insert(pair<int, string>(1, "student_one")); mapStudent.insert(pair<int, string>(2, "student_two")); mapStudent.insert(pair<int, string>(3, "student_three")); map<int, string>::reverse_iterator iter; for(iter = mapStudent.rbegin(); iter != mapStudent.rend(); iter++) { cout<<iter->first<<" "<<iter->second<<endl; } }
The third way is to use an array. The program is described as follows.
#include <map> #include <string> #include <iostream> using namespace std; int main() { map<int, string> mapStudent; mapStudent.insert(pair<int, string>(1, "student_one")); mapStudent.insert(pair<int, string>(2, "student_two")); mapStudent.insert(pair<int, string>(3, "student_three")); int nSize = mapStudent.size() //The error here should be for (int nIndex = 1; nIndex <= nSize; nIndex ++) //by rainfish for(int nIndex = 0; nIndex < nSize; nIndex++) { cout<<mapStudent[nIndex]<<end; } }
5. Data lookup (including determining whether the keyword appears in the map)
Here we will see the benefits of keeping map in order when inserting data.
There are many ways to determine whether a data (keyword) appears in a map. Although the title here is data search, there will be a lot of basic map usage interspersed here.
Three methods of data search are given here.
The first is to use the count function to determine whether the keyword appears or not. The disadvantage is that it can not locate the location of the data. Because of the characteristics of map and the one-to-one mapping relationship, it determines that the return value of the count function is only two, either 0 or 1.
The second is to use find function to locate the location of data occurrence. It returns an iterator. When data appears, it returns an iterator of the location of data. If there is no data to be looked up in map, it returns an iterator equal to the iterator returned by end function.
Third: It's a bit clumsy to use this method to determine whether data appears or not, but I'm going to explain it here.
Lower_bound function, which returns the lower bound of the keyword to be looked up (an iterator)
Usage of the Upper_bound function, which returns the upper bound of the keyword to be looked up (an iterator)
For example, if 1, 2, 3, 4 has been inserted into the map, 2 is returned if lower_bound(2), and 3 is returned if upper-bound (2).
The Equal_range function returns a pair. The first variable in pair is the iterator returned by Lower_bound, and the second iterator in pair is the iterator returned by Upper_bound.
#include <map> #include <string> #include <iostream> using namespace std; int main() { map<int, string> mapStudent; mapStudent[1] = "student_one"; mapStudent[3] = "student_three"; mapStudent[5] = "student_five"; map<int, string>::iterator iter; iter = mapStudent.lower_bound(2); { //Returns an iterator with lower bound 3 cout<<iter->second<<endl; } iter = mapStudent.lower_bound(3); { //Returns an iterator with lower bound 3 cout<<iter->second<<endl; } iter = mapStudent.upper_bound(2); { //Returns an iterator for upper bound 3 cout<<iter->second<<endl; } iter = mapStudent.upper_bound(3); { //Returns an iterator for upper bound 5 cout<<iter->second<<endl; } Pair<map<int, string>::iterator, map<int, string>::iterator> mapPair; mapPair = mapStudent.equal_range(2); if(mapPair.first == mapPair.second) { cout<<"Do not Find"<<endl; } Else { cout<<"Find"<<endl; } mapPair = mapStudent.equal_range(3); if(mapPair.first == mapPair.second) { cout<<"Do not Find"<<endl; } Else { cout<<"Find"<<endl; } }
6. Data clearance and blanking
Clearing up the data in the map can use the clear() function to determine whether there is data in the map can use the empty() function, and returning true means that it is empty map.
7. Data deletion
The erase function, which has three overloaded functions, is used here. Here's how to use them in detail in an example
#include <map> #include <string> #include <iostream> using namespace std; int main() { map<int, string> mapStudent; mapStudent.insert(pair<int, string>(1, "student_one")); mapStudent.insert(pair<int, string>(2, "student_two")); mapStudent.insert(pair<int, string>(3, "student_three")); //If you want to demonstrate the output effect, please choose one of the following. You will see better results. //If you want to delete 1, use iterator to delete map<int, string>::iterator iter; iter = mapStudent.find(1); mapStudent.erase(iter); //If you want to delete 1, delete it with keywords int n = mapStudent.erase(1);//If deleted, 1 will be returned, otherwise 0 will be returned. //With iterator, delete in pieces //Clear the whole map with one code mapStudent.earse(mapStudent.begin(), mapStudent.end()); //It is also a feature of STL to delete fragments. The deletion interval is a set of front-closed and back-opened fragments. //Add traversal code and print out }
8. Use of other functions
Here are swap,key_comp,value_comp,get_allocator and other functions. I feel that these functions are not used very much in programming. If you are interested, you can study them by yourself.
9. ranking
Here we want to talk about a more advanced usage, sorting problem, STL default is to use less than sign sorting, the above code in sorting is not any problem, because the above keyword is int, it itself supports less than sign operation, in some special cases, such as keywords are a structure, involving sorting will be a problem, because it is not less than sign. Number operation, insert and other functions can not pass the compilation time. Here are two ways to solve this problem.
The first kind: less than the number of overload, procedures for example
#include <map> #include <string> uing namespace std; Typedef struct tagStudentInfo { int nID; String strName; }StudentInfo, *PStudentInfo; //Student information int main() { int nSize; //Mapping Scores with Student Information map<StudentInfo, int>mapStudent; map<StudentInfo, int>::iterator iter; StudentInfo studentInfo; studentInfo.nID = 1; studentInfo.strName = "student_one" mapStudent.insert(pair<StudentInfo, int>(studentInfo, 90)); studentInfo.nID = 2; studentInfo.strName = "student_two"; mapStudent.insert(pair<StudentInfo, int>(studentInfo, 80)); for (iter=mapStudent.begin(); iter!=mapStudent.end(); iter++) cout<<iter->first.nID<<endl<<iter->first.strName<<endl<<iter->second<<endl; }
The above program can not be compiled and passed, as long as the overload is less than sign, then OK, as follows:
Typedef struct tagStudentInfo { int nID; String strName; Bool operator < (tagStudentInfo const& _A) const { //This function specifies the sorting strategy, sorted by nID, and if nID is equal, sorted by strName If(nID < _A.nID) return true; If(nID == _A.nID) return strName.compare(_A.strName) < 0; Return false; } }StudentInfo, *PStudentInfo; //Student information
The second is the application of imitation function. At this time, there is no direct less than sign overload in the structure.
#include <map> #include <string> using namespace std; Typedef struct tagStudentInfo { int nID; String strName; }StudentInfo, *PStudentInfo; //Student information class sort { Public: Bool operator() (StudentInfo const &_A, StudentInfo const &_B) const { If(_A.nID < _B.nID) return true; If(_A.nID == _B.nID) return _A.strName.compare(_B.strName) < 0; Return false; } }; int main() { //Mapping Scores with Student Information map<StudentInfo, int, sort>mapStudent; StudentInfo studentInfo; studentInfo.nID = 1; studentInfo.strName = "student_one"; mapStudent.insert(pair<StudentInfo, int>(studentInfo, 90)); studentInfo.nID = 2; studentInfo.strName = "student_two"; mapStudent.insert(pair<StudentInfo, int>(studentInfo, 80)); }
10. other
Because STL is a unified whole, many uses of map are combined with other things in STL. For example, in sorting, the default is less than sign, that is less <>. If you want to sort from big to small, there are many things involved here, which can not be explained one by one.
It is also pointed out that because of its orderly interior and guaranteed by red-black tree, the time complexity of many functions in map is log2N. If the function can be realized by map function, and STL Algorithm can also complete the function, it is suggested that map function be used with higher efficiency.
Let's talk about the spatial characteristics of map. Otherwise, it's estimated that you will sometimes be depressed when you use it. Because each data of map corresponds to a node on a red-black tree, this node occupies 16 bytes when you don't save your data, a parent node pointer, a left-right child pointer, and an enumeration value (red-black, equivalent to a balanced binary tree). Balance factor), I think you should know that these places are very memory-intensive.
Blog Origin: https://blog.csdn.net/sunshinewave/article/details/8067862