本文主要是介绍【STL源码剖析】第五章 关联式容器 之 set、map、multiset和multimap,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
所有的元素都会根据元素的键值自动被排序。set的元素不像map那样可以同时拥有实值(value)和键值(key),set元素的键值就是实值。set不允许两个元素有相同的键值。
不可以通过set的迭代器改变set的元素值。因为set元素值就是其键值,关系到set元素的排列规则。如果任意改变set元素值,会严重破坏set组织。set源码中,
set<T>::iterator
被定义为底层RB-tree的const_iterator,杜绝写入操作。换句话,set iterators是一种constant iterators。set拥有与list相同的某些性质:当客户端对它进行元素新增操作(insert)或删除操作(erase)时,操作之前的所有迭代器,在操作完成之后依然有效。当然,被删除的那个元素的迭代器必然是个例外。
STL set以RB-tree为底层机制,set的操作几乎都是转调用RB-tree的函数而已。
set测试代码:
using namespace std;int main(){ int ia[] = { 5, 3, 4, 1, 6, 2 }; set<int> iset(begin(ia), end(ia)); cout << "size=" << iset.size() << endl; //size=6 cout << "3 count=" << iset.count(3) << endl;//3 count=1 iset.insert(3); cout << "size=" << iset.size() << endl;//size=6 cout << "3 count=" << iset.count(3) << endl;//3 count=1 iset.insert(7); cout << "size=" << iset.size() << endl;//size=7 cout << "3 count=" << iset.count(3) << endl;//3 count=1 iset.erase(1); cout << "size=" << iset.size() << endl;//size=6 cout << "1 count=" << iset.count(1) << endl;//1 count=0 set<int>::iterator it; for (it = iset.begin(); it != iset.end(); ++it) cout << *it << " "; //2 3 4 5 6 7 cout << endl; it = find(iset.begin(), iset.end(), 3); if (it != iset.end()) cout << "3 found" << endl;//3 found it = find(iset.begin(), iset.end(), 1); if (it == iset.end()) cout << "1 not found" << endl;//1 not found system("pause"); return 0;}
map
map的特性是,所有元素都会根据元素的键值自动被排序。map的所有元素都是pair,同时拥有实值(value)和键值(key)。pair的第一元素被视为键值,第二元素被视为实值。map不允许两个元素拥有相同的键值。下面是
<stl_pair.h>
中pair定义:template<class T1,class T2>struct pair{ typedef T1 first_type; typedef T2 second_type; T1 first; T2 second; pair():first(T1()),second(T2()) {} pair(const T1& a,const T2& b):first(a),second(b) {}}
不能通过map的迭代器改变map的键值,但通过map的迭代器能改变map的实值。因此map的iterators既不是一种const iterators,也不是一种mutable iterators。
map拥有和list相同的某些性质:当客户端对它进行元素新增操作(insert)或删除操作(erase)时,操作之前的所有迭代器,在操作完成之后都依然有效。当然,被删除的那个元素的迭代器必然是个例外。
由于RB-tree是一种平衡二叉搜索树,自动排序的效果很不错,所以标准的STL map即以RB-tree为底层机制。又由于map所开放的各种操作接口,RB-tree也都提供了,所以几乎所有的map操作行为,都只是转调用RB-tree的操作行为而已。
using namespace std;int main(){ map<string, int> simap; //以string为键值,以int为实值 simap[string("jjhou")] = 1; //第一对内容是("jjhou",1) simap[string("jerry")] = 2; //第一对内容是("jerry",2) simap[string("jason")] = 3; //第一对内容是("jason",3) simap[string("jimmy")] = 4; //第一对内容是("jimmy",4) pair<string, int> value(string("david"), 5); simap.insert(value); map<string, int>::iterator simap_iter = simap.begin(); for (; simap_iter != simap.end(); ++simap_iter) cout << simap_iter->first << ' ' << simap_iter->second << endl; //david 5 //按键值排序 //jason 3 //jerry 2 //jimmy 4 //jjhou 1 int number = simap[string("jjhou")]; cout << number << endl; //1 map<string, int>::iterator ite1; //面对关联式容器,应使用其所提供的find函数来搜寻元素,会比STL算法find()更有效率。因为STL find()只是循序搜索 ite1 = simap.find(string("mchen")); if (ite1 == simap.end()) cout << "mchen not found" << endl; //mchen not found ite1 = simap.find(string("jerry")); if (ite1 != simap.end()) cout << "jerry found" << endl; //jerry found ite1->second = 9; int number2 = simap[string("jerry")]; cout << number2 << endl; //9}
multiset
multiset的特性以及用法和set完全相同,唯一的差别在于它允许键值重复,因此它的插入操作采用的是底层机制RB-tree的insert_equal()而非insert_unique()。
using namespace std;int main() { vector<int> a = { 5, 3, 4, 1, 6, 2 }; multiset<int> iset(a.begin(),a.end()); cout << "size=" << iset.size() << endl; //size=6 cout << "3 count=" << iset.count(3) << endl;//3 count=1 iset.insert(3); //和set区别的地方 cout << "size=" << iset.size() << endl;//size=7 cout << "3 count=" << iset.count(3) << endl;//3 count=2 iset.insert(7); cout << "size=" << iset.size() << endl;//size=8 cout << "3 count=" << iset.count(3) << endl;//3 count=2 iset.erase(1); cout << "size=" << iset.size() << endl;//size=7 cout << "1 count=" << iset.count(1) << endl;//1 count=0 set<int>::iterator it; for (it = iset.begin(); it != iset.end(); ++it) cout << *it << " "; //2 3 3 4 5 6 7 cout << endl; it = find(iset.begin(), iset.end(), 3); if (it != iset.end()) cout << "3 found" << endl;//3 found it = find(iset.begin(), iset.end(), 1); if (it == iset.end()) cout << "1 not found" << endl;//1 not found system("pause"); return 0;}
multimap
multimap的特性以及用法与map完全相同,唯一的差别在于它允许键值重复,因此它的插入操作采用的是底层机制RB-tree的insert_equal()而非insert_unique()。
using namespace std;int main(){ multimap<string, int> mp;//multimap没有下标操作 mp.insert(pair<string, int>("Jack", 1)); mp.insert(pair<string, int>("John", 2)); mp.insert(pair<string, int>("Lily", 3)); mp.insert(pair<string, int>("Kate", 4));//按键值字典序排序 mp.insert(pair<string, int>("Tom", 5)); //Jack 1 mp.insert(pair<string, int>("John", 8)); //John 2 //John 8 map<string, int>::iterator it; //Kate 4 for (it = mp.begin(); it != mp.end(); ++it) //Lily 3 cout << it->first << " " << it->second << endl; //Tom 5 it = mp.find("John"); if (it != mp.end()) cout << "John found" << endl; //John found it->second = 8; it = mp.find("John"); cout << it->second << endl;//8 system("pause"); return 0;}
这篇关于【STL源码剖析】第五章 关联式容器 之 set、map、multiset和multimap的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!