Common usage of map in C++

Map is an associative container of STL that provides data one-to-one (where the first may be called a key, each key can only appear once in the map, and the second may be called the value of that key) Processing power, thanks to this feature, it is possible to provide a fast-track programmatically when we process one-to-one data. Let’s talk about the organization of the internal data of the map. A red-black tree (a non-strict balanced binary tree) is built inside the map. This tree has the function of automatically sorting the data, so all the data in the map is Orderly, we will see the benefits of order later.

The following example illustrates what is one-to-one data mapping. For example, in a class, there is a one-to-one mapping relationship between each student's student number and his name. This model can be easily described by map. Obviously, the student number is described by int, and the name is described by string (in this article Instead of using char * to describe strings, use strings in STL to describe them), and the map description code is given below:

Map<int, string> mapStudent;

1. Map constructor

Map provides a total of 6 constructors. This block involves the memory allocator, which is not listed. We will touch on some map construction methods below. What I want to say here is that we usually construct a map in the following way. map:

Map<int, string> mapStudent;

2. Insertion of data

After constructing the map container, we can insert data into it. Here are three ways to insert data:

The first one: use the insert function to insert pair data. The following example illustrates (although the following code is handwritten, it should be able to be compiled and passed under VC and GCC. You can run it to see the effect. Please add this statement under VC. Shield 4786 warning #pragma warning (disable:4786) )

#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>::iterator  iter;

       for(iter = mapStudent.begin(); iter != mapStudent.end(); iter++)

{

       Cout<<iter->first<<”   ”<<iter->second<<end;

}

}

The second: use the insert function to insert value_type data, the following example illustrates

#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<<end;

}

}

The third: insert data in an array, the following example illustrates

#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<<end;

}

}

The above three usages can realize data insertion, but they are different. Of course, the first and the second are the same in effect. Using the insert function to insert data involves the insertion of data. The concept of the uniqueness of the set, that is, when there is this keyword in the map, the insert operation cannot insert data, but the array method is different, it can overwrite the previous value corresponding to the keyword, and use the program to explain

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 corresponding to the keyword 1 in the map is "student_one", and the second statement does not take effect, so this involves how we know whether the insert statement is successfully inserted. You can use pair To get whether the insertion is successful, the procedure 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 through the second variable of the pair. Its first variable returns an iterator of a map. If the insertion is successful, Insert_Pair.second should be true, otherwise false.

The completion code is given below 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<<end;

}

}

You can use the following program to see the effect of inserting an array on the data overlay

#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<<end;

}

}

3. The size of the map

After inserting data into the map, how do we know how much data has been inserted currently? We can use the size function, which is used as follows:

Int nSize = mapStudent.size();

4. Traversal of data

Three methods are also provided here to traverse the map

The first type: apply forward iterators, which are everywhere in the above example program, skipping it does not show

The second: apply the inverse iterator, the following is an example, to experience 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<<end;

}

}

The third: use the array method, the program description is 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()

//There is an error here, it should be for(int nIndex = 1; nIndex <= nSize; nIndex++)


//by rainfish

       for(int nIndex = 0; nIndex < nSize; nIndex++)

{

       Cout<<mapStudent[nIndex]<<end;

}

}

5. Data search (including determining whether this keyword appears in the map)

Here we will appreciate the benefits of map ensuring ordering when data is inserted.

There are many ways to determine whether a data (keyword) appears in the map. Although the title here is the data search, there will be a lot of basic map usages interspersed here.

Here are three data search methods

The first one: use the count function to determine whether the keyword appears. The disadvantage is that the location of the data cannot be located. Due to the characteristics of the map and the one-to-one mapping relationship, it is determined that the count function has only two return values, either 0. , or 1, in case of occurrence, of course, it returns 1

The second: use the find function to locate the location of the data. It returns an iterator. When the data appears, it returns the iterator of the location of the data. If there is no data to be found in the map, the iterator it returns is equal to end Iterator returned by the function, program description

#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>::iterator iter;

       iter = mapStudent.find(1);

if(iter != mapStudent.end())

{

       Cout<<”Find, the value is ”<<iter->second<<endl;

}

Else

{

       Cout<<”Do not Find”<<endl;

}

}

The third: This method is used to determine whether the data appears, which is a bit stupid, but I plan to explain it here

Lower_bound function usage, this function is used to return the lower bound of the keyword to be searched (is an iterator)

Upper_bound function usage, this function is used to return the upper bound of the keyword to be searched (it is an iterator)

For example: if 1, 2, 3, and 4 have been inserted into the map, if lower_bound(2), it will return 2, and if upper-bound(2), it will return 3

The Equal_range function returns a pair. The first variable in the pair is the iterator returned by Lower_bound, and the second iterator in the pair is the iterator returned by Upper_bound. If the two iterators are equal, this key does not appear in the map word, program description

#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 of lower bound 3

       Cout<<iter->second<<endl;

}

iter = mapStudent.lower_bound(3);

{

       //returns an iterator of lower bound 3

       Cout<<iter->second<<endl;

}

 

iter = mapStudent.upper_bound(2);

{

       //returns an iterator of upper bound 3

       Cout<<iter->second<<endl;

}

iter = mapStudent.upper_bound(3);

{

       //returns an iterator of 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 Empty and Empty

To clear the data in the map, you can use the clear() function, to determine whether there is data in the map, you can use the empty() function. If it returns true, it means that the map is empty.

7. Deletion of data

The erase function is used here. It has three overloaded functions. The following is a detailed description of their usage in the 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, the effect you will see will be better

       //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 the keyword

       Int n = mapStudent.erase(1);//If deleted, it will return 1, otherwise it will return 0

 

       //Use iterator, delete into pieces

       //The following code clears the entire map

       mapStudent.earse(mapStudent.begin(), mapStudent.end());

       //It should be noted that when deleting a piece, it is also a feature of STL. The deletion interval is a set that is closed before and then opened.

 

       //Add the traversal code by yourself and print the output

}

8. Some other function usage

There are functions such as swap, key_comp, value_comp, get_allocator, etc. I feel that these functions are not used a lot in programming. I skip it and do not list them. If you are interested, you can do your own research.

9. Sort

What I want to talk about here is a bit more advanced usage, sorting problem, the default in STL is to use less than sign to sort, the above code does not have any problem in sorting, because the above keyword is int type, which itself supports Less than sign operation, in some special cases, such as the keyword is a structure, there will be problems when it comes to sorting, because it does not have less than sign operation, and functions such as insert can't get through during compilation. Two methods are given below to solve this problem.

The first type: overloaded less than sign, program example

#include <map>

#include <string>

Using namespace std;

Typedef struct tagStudentInfo

{

       Int nID;

       String   strName;

}StudentInfo, *PStudentInfo; //Student Information

 

Int main()

{

    int nSize;

       // Map 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 cannot be compiled and passed, as long as the less than sign is overloaded, it is OK, as follows:

Typedef struct tagStudentInfo

{

       Int nID;

       String   strName;

       Bool operator < (tagStudentInfo const& _A) const

       {

              //This function specifies the sorting strategy, sort by nID, if nID is equal, sort 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 type: the application of the functor. At this time, there is no direct overload of the less than sign in the structure. The program description

#include <map>

#include <string>

Using namespace std;

Typedef struct tagStudentInfo

{

       Int nID;

       String   strName;

}StudentInfo, *PStudentInfo; //Student Information

 

Classs 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()

{

       // Map 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. In addition

Since STL is a unified whole, many uses of map are combined with other things in STL. For example, in sorting, the less-than sign is used by default, that is, less<>. If you want to sort from big to small, There are many things involved here that cannot be explained here.

It should also be noted that the map is internally ordered and guaranteed by the red-black tree, so the time complexity of many functions execution is log2N. If you use the map function to achieve the function, and STL Algorithm can also complete this function , it is recommended to use map's own function, which is more efficient.

Let's talk about the characteristics of map in space. Otherwise, it is estimated that you will sometimes feel depressed when you use it. Since each data of map corresponds to a node on the red-black tree, when this node does not save your data, It occupies 16 bytes, a parent node pointer, left and right child pointers, and an enumeration value (marked in red and black, which is equivalent to the balance factor in a balanced binary tree), I think everyone should know that these places are very memory-intensive Well, let's not talk about it...

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325981172&siteId=291194637