STL容器之map

【1】map容器ios

map 是關聯容器。容器中的每個元素都是由一個鍵值和一個數據值組成的。數組

set 是一個集合它以其元素做爲鍵值(同一個鍵值只能出現一次),且默認以升序排列。less

list 是一個順序容器。函數

【2】map容器使用方法以及實例spa

(1)定義、插入數據方法實例指針

 1 // map容器定義、插入數據方式代碼
 2 #include<map>
 3 #include<string>
 4 #include<iostream>
 5 using namespace std;
 6 
 7 // 打印map容器數據
 8 void print(map<int, string>& mapStu, int nValue)
 9 {
10     cout << "mapStu" << nValue << "數據信息:" << endl;
11     cout << "size: " << mapStu.size() << endl;
12     map<int, string>::iterator iter = mapStu.begin();
13     for (; iter != mapStu.end(); ++iter)
14     {
15         cout << "key: " << iter->first << " value: " << iter->second << endl;
16     }
17     cout << endl;
18 }
19 
20 void main()
21 {
22     // 第一種定義map的方法
23     map<int, string> mapStu1;
24     // 第二種定義map的方法
25     typedef map<int, string> mapType;
26     mapType mapStu2, mapStu3, mapStu4;
27 
28     // 第一種插入數據方法:用insert函數插入value_type數據
29     mapStu1.insert(map<int, string>::value_type(1, "Qin"));
30     mapStu1.insert(map<int, string>::value_type(2, "Sun"));
31     mapStu1.insert(map<int, string>::value_type(3, "Wang"));
32     mapStu1.insert(map<int, string>::value_type(2, "Zhao"));
33     print(mapStu1, 1);
34     // 第二種插入數據方法:用insert函數插入pair數據
35     mapStu2.insert(pair<int, string>(1, "Qin"));
36     mapStu2.insert(pair<int, string>(2, "Sun"));
37     mapStu2.insert(pair<int, string>(3, "Wang"));
38     mapStu2.insert(pair<int, string>(2, "Zhao"));
39     print(mapStu2, 2);
40     // 第三種插入數據方法:用insert函數插入make_pair數據
41     mapStu3.insert(make_pair<int, string>(1, "Qin"));
42     mapStu3.insert(make_pair<int, string>(2, "Sun"));
43     mapStu3.insert(make_pair<int, string>(3, "Wang"));
44     mapStu3.insert(make_pair<int, string>(2, "Zhao"));
45     print(mapStu3, 3);
46     // 第四種插入數據方法:數組插入法
47     mapStu4[1] = "Qin";
48     mapStu4[2] = "Sun";
49     mapStu4[3] = "Wang";
50     mapStu4[2] = "Zhao";
51     print(mapStu4, 4);
52 
53     pair<map<int, string>::iterator, bool> iter_pair;
54     iter_pair = mapStu1.insert(map<int, string>::value_type(3, "Li"));
55     cout << "插入成功與否:" << iter_pair.second << endl;
56 
57     system("pause");
58 }
59 
60 // run out
61 /*
62 mapStu1數據信息:
63 size: 3
64 key: 1 value: Qin
65 key: 2 value: Sun
66 key: 3 value: Wang
67 
68 mapStu2數據信息:
69 size: 3
70 key: 1 value: Qin
71 key: 2 value: Sun
72 key: 3 value: Wang
73 
74 mapStu3數據信息:
75 size: 3
76 key: 1 value: Qin
77 key: 2 value: Sun
78 key: 3 value: Wang
79 
80 mapStu4數據信息:
81 size: 3
82 key: 1 value: Qin
83 key: 2 value: Zhao
84 key: 3 value: Wang
85 
86 插入成功與否:0
87 請按任意鍵繼續. . .
88 */

分析總結:code

以上四種用法,雖然均可以實現數據的插入,可是它們是有區別的。blog

固然,第1、2、三種在效果上是徹底同樣的,用insert函數插入數據,在數據的插入過程當中涉及到集合的惟一性這個概念:排序

即當map中有這個關鍵字時,insert操做再插入數據是不會成功的。編譯器

可是,用數組(第四種)方式就不一樣了,它能夠覆蓋之前該關鍵字對應的值,用程序說明以下:

mapStu1.insert(map<int, string>::value_type(2, "Sun"));

mapStu1.insert(map<int, string>::value_type(2, "Zhao"));

上面這兩條語句執行後,mapStu1中2這個關鍵字對應的值是「Sun」,第二條語句並無生效。

那麼,這就涉及到咱們怎麼知道insert語句是否插入成功的問題?能夠用pair來得到是否插入成功,程序以下:

pair<map<int, string>::iterator, bool> iter_pair;

iter_pair = mapStu1.insert(map<int, string>::value_type(3, "Li"));

咱們經過pair的第二個變量來判斷是否插入成功,它的第一個變量返回的是一個map的迭代器,

若是插入成功的話迭代器的變量iter_pair.second應該是true,不然爲false。

(2)遍歷map容器的三種方式

程序代碼以下:

 1 #include <map>
 2 #include <iostream>
 3 #include <string>
 4 using namespace std;
 5 
 6 // 第一種方式
 7 void print1(map<int, string>& mapStu)
 8 {
 9     cout << "第一種遍歷方式:" << endl;
10     cout << "size: " << mapStu.size() << endl;
11     // 迭代map容器中的數據
12     map<int, string>::iterator iter = mapStu.begin();
13     for (; iter != mapStu.end(); ++iter)
14     {
15         cout << "key: " << iter->first << " value: " << iter->second << endl;
16     }
17     cout << endl;
18 }
19 
20 // 第二種方式
21 void print2(map<int, string>& mapStu)
22 {
23     cout << "第二種遍歷方式:" << endl;
24     cout << "size: " << mapStu.size() << endl;
25     // 迭代map容器中的數據
26     map<int, string>::reverse_iterator iter = mapStu.rbegin();
27     for (; iter != mapStu.rend(); ++iter)
28     {
29         cout << "key: " << iter->first << " value: " << iter->second << endl;
30     }
31 
32     cout << endl;
33 }
34 
35 // 第三種方式
36 void print3(map<int, string>& mapStu)
37 {
38     cout << "第三種遍歷方式:" << endl;
39     int nSize = mapStu.size();
40     cout << "size: " << mapStu.size() << endl;
41     // 迭代map容器中的數據
42     for(int nIndex = 1; nIndex < nSize + 1; ++nIndex)
43     {
44         cout << "<" << nIndex << " :: " << mapStu[nIndex] << ">" << endl;
45     }
46 }
47 
48 void main()
49 {
50     typedef map<int, string> mapType;
51     mapType mapStu;
52 
53     // 用insert函數插入value_type數據
54     mapStu.insert(map<int, string>::value_type(1, "Qin"));
55     mapStu.insert(map<int, string>::value_type(2, "Sun"));
56     mapStu.insert(map<int, string>::value_type(3, "Wang"));
57     mapStu.insert(map<int, string>::value_type(4, "Zhao"));
58     print1(mapStu);  // 第一種方式
59     print2(mapStu);  // 第二種方式
60     print3(mapStu);  // 第三種方式
61 
62     system("pause");
63 }
64 // run out:
65 /*
66 第一種遍歷方式:
67 size: 4
68 key: 1 value: Qin
69 key: 2 value: Sun
70 key: 3 value: Wang
71 key: 4 value: Zhao
72 
73 第二種遍歷方式:
74 size: 4
75 key: 4 value: Zhao
76 key: 3 value: Wang
77 key: 2 value: Sun
78 key: 1 value: Qin
79 
80 第三種遍歷方式:
81 size: 4
82 <1 :: Qin>
83 <2 :: Sun>
84 <3 :: Wang>
85 <4 :: Zhao>
86 請按任意鍵繼續. . .
87 */

(3)查找數據的三種方式

應用實例代碼以下:

  1 // 三種查找數據的方式
  2 #include <map>
  3 #include <iostream>
  4 #include <string>
  5 using namespace std;
  6 
  7 // 第一種方式
  8 void print1(map<int, string>& mapStu)
  9 {
 10     cout << "遍歷容器數據:" << endl;
 11     cout << "size: " << mapStu.size() << endl;
 12     // 迭代map容器中的數據
 13     map<int, string>::iterator iter = mapStu.begin();
 14     for (; iter != mapStu.end(); ++iter)
 15     {
 16         cout << "key: " << iter->first << " value: " << iter->second << endl;
 17     }
 18 }
 19 
 20 void main()
 21 {
 22     typedef map<int, string> mapType;
 23     mapType mapStu;
 24 
 25     // 用insert函數插入value_type數據
 26     mapStu.insert(map<int, string>::value_type(1, "Qin"));
 27     mapStu.insert(map<int, string>::value_type(2, "Sun"));
 28     mapStu.insert(map<int, string>::value_type(3, "Wang"));
 29     mapStu.insert(map<int, string>::value_type(4, "Zhao"));
 30     // 第一種查找數據方式
 31     // count函數求的是關鍵字key的個數?key是不能重複的,因此返回只有0和1兩種結果。
 32     cout << "查找關鍵字3的結果 : " << mapStu.count(1) << endl;
 33     cout << "查找關鍵字5的結果:  " << mapStu.count(5) << endl;
 34     // 第二種查找數據方式
 35     map<int, string>::iterator iter;
 36     iter = mapStu.find(1);
 37     if (iter != mapStu.end())
 38     {
 39         cout << "Find, the value is " << iter->second << endl;
 40     }
 41     else
 42     {
 43          cout << "Do not Find !" << endl;
 44     }
 45     // 第三種查找數據方式
 46     print1(mapStu);
 47     iter = mapStu.lower_bound(2);
 48     {
 49         cout << "lower_bound(2) :: (不小於2) " << iter->second << endl;
 50     }
 51 
 52     iter = mapStu.lower_bound(3);
 53     {
 54        cout << "lower_bound(3) :: (不小於3) " << iter->second << endl;
 55     }
 56 
 57     iter = mapStu.upper_bound(2);
 58     {
 59        cout << "upper_bound(2) :: (大於2) " << iter->second << endl;
 60     }
 61 
 62     iter = mapStu.upper_bound(3);
 63     {
 64        cout << "upper_bound(3) :: (大於3) " << iter->second << endl;
 65     }
 66 
 67     pair<map<int, string>::iterator, map<int, string>::iterator> mapPair;
 68     mapPair = mapStu.equal_range(2);
 69     if (mapPair.first == mapPair.second)
 70     {
 71         cout << "equal_range(2) :: Do not Find!" << endl;
 72     }
 73     else
 74     {
 75         cout << "equal_range(2) :: Find!" << endl;
 76     }
 77 
 78     mapPair = mapStu.equal_range(5);
 79     if (mapPair.first == mapPair.second)
 80     {
 81        cout << "equal_range(5) :: Do not Find!" << endl;
 82     }
 83     else
 84     {
 85         cout << "equal_range(5) :: Find!" << endl;
 86     }
 87 
 88     system("pause");
 89 }
 90 // run out:
 91 /*
 92 查找關鍵字3的結果 : 1
 93 查找關鍵字5的結果:  0
 94 Find, the value is Qin
 95 遍歷容器數據:
 96 size: 4
 97 key: 1 value: Qin
 98 key: 2 value: Sun
 99 key: 3 value: Wang
100 key: 4 value: Zhao
101 lower_bound(2) :: (不小於2) Sun
102 lower_bound(3) :: (不小於3) Wang
103 upper_bound(2) :: (大於2) Wang
104 upper_bound(3) :: (大於3) Zhao
105 equal_range(2) :: Find!
106 equal_range(5) :: Do not Find!
107 請按任意鍵繼續. . .
108 */

注意:

lower_bound(x)不是下界,而是大於等於x的最小值。

upper_bound(x) 大於x的最小值。

(4)查詢、修改、刪除、大小、比較、清空、判空等等方法。

應用實例代碼以下:

  1 #include <map>
  2 #include <string>
  3 #include <iostream>
  4 using namespace std;
  5 
  6 // 打印map容器數據
  7 void print(map<int, string>& mapStu)
  8 {
  9     cout << "size: " << mapStu.size() << endl;
 10     // 迭代map容器中的數據
 11     map<int, string>::iterator iter = mapStu.begin();
 12     for (; iter != mapStu.end(); ++iter)
 13     {
 14         cout << "key: " << iter->first << " value: " << iter->second << endl;
 15     }
 16     cout << endl;
 17 }
 18 
 19 void main()
 20 {
 21     typedef map<int, string> mapType;
 22     mapType mapStu1;
 23 
 24     // 用insert函數插入value_type數據
 25     mapStu1.insert(map<int, string>::value_type(1, "Qin"));
 26     mapStu1.insert(map<int, string>::value_type(2, "Sun"));
 27     mapStu1.insert(map<int, string>::value_type(3, "Wang"));
 28     mapStu1.insert(map<int, string>::value_type(2, "Zhao"));
 29     print(mapStu1);
 30     // 查找數據的兩種方式:
 31     // 方式1:
 32     string str2 = mapStu1[2];
 33     cout << str2 << endl;
 34     // 方式2:
 35     mapType::iterator my_Iter;
 36     my_Iter = mapStu1.find(3);
 37     string str3 = my_Iter->second;
 38     cout << str3 << endl << endl;
 39     // 修改數據的兩種方式:
 40     // 方式1:
 41     mapStu1[2] = "Ma";
 42     // 方式2:
 43     my_Iter->second = "Yuan";
 44     print(mapStu1);
 45     // size 函數 和 empty函數
 46     cout << "size() :: " << mapStu1.size() << endl;
 47     cout << "empty() :: " << mapStu1.empty() << endl;
 48     mapStu1.clear();
 49     cout << "size() :: " << mapStu1.size() << endl;
 50     cout << "empty() :: " << mapStu1.empty() << endl;
 51     // 比較 ==、>=、<=、!=
 52     mapType mapStu2;
 53     cout << "mapStu1 == mapStu2 :: " << (mapStu1 == mapStu2) << endl; 
 54     cout << "mapStu1 >= mapStu2 :: " << (mapStu1 >= mapStu2) << endl;
 55     cout << "mapStu1 <= mapStu2 :: " << (mapStu1 <= mapStu2) << endl;
 56     cout << "mapStu1 != mapStu2 :: " << (mapStu1 != mapStu2) << endl << endl;
 57 
 58     mapStu1.insert(map<int, string>::value_type(1, "Qin"));
 59     mapStu1.insert(map<int, string>::value_type(2, "Sun"));
 60     mapStu1.insert(map<int, string>::value_type(3, "Wang"));
 61     mapStu1.insert(map<int, string>::value_type(4, "Qiang"));
 62     mapStu1.insert(map<int, string>::value_type(5, "Huang"));
 63     mapStu1.insert(map<int, string>::value_type(6, "Li"));
 64     mapStu1.insert(map<int, string>::value_type(7, "Hou"));
 65     mapStu1.insert(map<int, string>::value_type(8, "Lin"));
 66     mapStu1.insert(map<int, string>::value_type(9, "Li"));
 67 
 68     // 刪除操做
 69     cout << "刪除前打印數據信息:" << endl;
 70     print(mapStu1);
 71     mapType::iterator iter;
 72     // 第一種刪除(代碼1)
 73     for (iter = mapStu1.begin(); iter != mapStu1.end();)
 74     {
 75         if (5 == iter->first) 
 76         {
 77             iter = mapStu1.erase(iter);
 78         }
 79         else
 80         {
 81             ++iter;
 82         }
 83     }
 84 
 85     // 第一種刪除(代碼2)(注意代碼層面的差別)
 86     for (iter = mapStu1.begin(); iter != mapStu1.end();)
 87     {
 88         if ("Li" == iter->second) 
 89         {
 90             mapStu1.erase(iter++);
 91         }
 92         else
 93         {
 94             ++iter;
 95         }
 96     }
 97     cout << "刪除關鍵字5 以及 值「Li」後: " << endl;
 98     print(mapStu1);
 99 
100     // 第一種刪除(代碼3)(注意代碼層面的差別)
101     my_Iter = mapStu1.find(2);
102     mapStu1.erase(my_Iter);
103     cout << "刪除關鍵字2後: " << endl;
104     print(mapStu1);
105 
106     // 第二種刪除(直接刪除關鍵字)
107     int nResult = mapStu1.erase(3); // 若是刪除了會返回1,不然返回0
108     cout << nResult << endl;
109     cout << "刪除關鍵字3後: " << endl;
110     print(mapStu1);
111 
112     // 第三種刪除(用迭代器,成片的刪除)
113     mapStu1.erase(++mapStu1.begin(), mapStu1.end());
114     cout << "剩第一位,其它所有刪除後: " << endl;
115     print(mapStu1);
116 
117     system("pause");
118 }
119 
120 // run out:
121 /*
122 size: 3
123 key: 1 value: Qin
124 key: 2 value: Sun
125 key: 3 value: Wang
126 
127 Sun
128 Wang
129 
130 size: 3
131 key: 1 value: Qin
132 key: 2 value: Ma
133 key: 3 value: Yuan
134 
135 size() :: 3
136 empty() :: 0
137 size() :: 0
138 empty() :: 1
139 mapStu1 == mapStu2 :: 1
140 mapStu1 >= mapStu2 :: 1
141 mapStu1 <= mapStu2 :: 1
142 mapStu1 != mapStu2 :: 0
143 
144 刪除前打印數據信息:
145 size: 9
146 key: 1 value: Qin
147 key: 2 value: Sun
148 key: 3 value: Wang
149 key: 4 value: Qiang
150 key: 5 value: Huang
151 key: 6 value: Li
152 key: 7 value: Hou
153 key: 8 value: Lin
154 key: 9 value: Li
155 
156 刪除關鍵字5 以及 值「Li」後:
157 size: 6
158 key: 1 value: Qin
159 key: 2 value: Sun
160 key: 3 value: Wang
161 key: 4 value: Qiang
162 key: 7 value: Hou
163 key: 8 value: Lin
164 
165 刪除關鍵字2後:
166 size: 5
167 key: 1 value: Qin
168 key: 3 value: Wang
169 key: 4 value: Qiang
170 key: 7 value: Hou
171 key: 8 value: Lin
172 
173 1
174 刪除關鍵字3後:
175 size: 4
176 key: 1 value: Qin
177 key: 4 value: Qiang
178 key: 7 value: Hou
179 key: 8 value: Lin
180 
181 剩第一位,其它所有刪除後:
182 size: 1
183 key: 1 value: Qin
184 
185 請按任意鍵繼續. . .
186 */

(5)map 容器排序問題

請看下面一段代碼:

 1 #include <map>
 2 #include <cstring>
 3 using namespace std;
 4 
 5 typedef struct tagStudentInfo
 6 {
 7     int nID;
 8     string strName;
 9 } StudentInfo, *PStudentInfo;  // 學生信息
10 
11 void main()
12 {
13     // 用學生信息映射分數
14     map<StudentInfo, int> mapStudent;
15     StudentInfo studentInfo;
16     studentInfo.nID = 1;
17     studentInfo.strName = "student_one";
18     mapStudent.insert(pair<StudentInfo, int>(studentInfo, 90));
19     studentInfo.nID = 2;
20     studentInfo.strName = "student_two";
21     mapStudent.insert(pair<StudentInfo, int>(studentInfo, 80));
22 }

注意:以上程序編譯沒法經過!

由編譯器錯誤提示分析:排序問題!STL中默認是採用小於號來排序的,當關鍵字是一個結構體時,涉及到排序就會出現問題。

由於它沒有小於號操做,insert等函數在編譯的時候過不去,下面給出兩個方法解決這個問題:

一、解決方法1,重載運算符。

 1 // 解決方法1
 2 
 3 #include <map>
 4 #include <cstring>
 5 using namespace std;
 6 
 7 typedef struct tagStudentInfo
 8 {
 9     int nID;
10     string strName;
11 
12     bool operator < (tagStudentInfo const & _A)const
13     {
14         // 這個函數指定排序策略,按nID排序,若是nID相等的話,按strName排序。
15         if (nID < _A.nID)
16             return true;
17         if (nID == _A.nID)
18             return strName.compare(_A.strName) < 0;
19 
20         return false;
21     }
22 } StudentInfo, *PStudentInfo;  // 學生信息
23 
24 void main()
25 {
26     // 用學生信息映射分數
27     map<StudentInfo, int> mapStudent;
28     StudentInfo studentInfo;
29     studentInfo.nID = 1;
30     studentInfo.strName = "student_one";
31     mapStudent.insert(pair<StudentInfo, int>(studentInfo, 90));
32     studentInfo.nID = 2;
33     studentInfo.strName = "student_two";
34     mapStudent.insert(pair<StudentInfo, int>(studentInfo, 80));
35 }

二、解決方法2,仿函數。

 1 // 解決方法2
 2 
 3 #include <map>
 4 #include <cstring>
 5 using namespace std;
 6 
 7 typedef struct tagStudentInfo
 8 {
 9     int nID;
10     string strName;
11 } StudentInfo, *PStudentInfo;  // 學生信息
12 
13 class sort
14 {
15 public:
16     bool operator()(StudentInfo const & _A, StudentInfo const & _B) const
17     {
18         if (_A.nID < _B.nID)
19             return true;
20         if (_A.nID == _B.nID)
21             return _A.strName.compare(_B.strName) < 0;
22 
23         return false;
24     }
25 };
26 
27 void main()
28 {
29     // 用學生信息映射分數
30     map<StudentInfo, int, sort> mapStudent;
31     StudentInfo studentInfo;
32     studentInfo.nID = 1;
33     studentInfo.strName = "student_one";
34     mapStudent.insert(pair<StudentInfo, int>(studentInfo, 90));
35     studentInfo.nID = 2;
36     studentInfo.strName = "student_two";
37     mapStudent.insert(pair<StudentInfo, int>(studentInfo, 80));
38 }

(6)待續...

【3】總結說明

(1)因爲STL是一個統一的總體,map的不少用法都和STL中其它的東西結合在一塊兒。

好比,在排序方面,這裏默認用的是小於號,即less<>,若是要從大到小排序呢,這裏涉及到的東西不少,在此沒法一一加以說明。

(2)map容器內部有序,由紅黑樹保證,所以不少函數執行的時間複雜度都是log2N的,用map函數能夠實現的功能,而STL Algorithm也能夠完成該功能。

可是,建議用map自帶函數,效率更高一些。

(3)map在空間上的特性。

因爲map的每一個數據對應紅黑樹上的一個節點,這個節點在不保存你的數據時,是佔用16個字節:

一個父節點指針,左右兩個孩子指針,還有一個枚舉值(標示紅黑的,至關於平衡二叉樹中的平衡因子)。

 

Good  Good  Study,  Day  Day  Up.

順序  選擇  循環  總結

相關文章
相關標籤/搜索