C++map和set
目录
一、序列式容器和关联式容器
二、set
1、插入与构造
2、删除与查找与迭代器
3、lower_bound和upper_bound
4、multiset
三、map
1、插入和构造以及迭代器
2、operator【】重载
3、operator【】重载的功能:查找、修改、插入
4、multimap和map依旧完全类似,支持相同数据
一、序列式容器和关联式容器
序列式容器逻辑结构为线性序列的数据结构,两个存储的值之间一般没有紧密关联,
顺序容器中的元素是按照他们在容器中的存储位置来顺序保存和访问的,比如list、string、vector、deque、array
关联式容器也是用来存储数据的,逻辑结构通常是非线性结构,两个位置交换一下存储结构就被破坏了
关联式容器中的元素是按关键字来保存和访问的
二、set
set底层使用红黑树来实现,增删查效率是O(logN),迭代器遍历采用的是中序遍历(双向迭代器)
1、插入与构造
int main()
{//去重+升序排序set<int,less<int>> s;s.insert(5);s.insert(2);s.insert(7);s.insert(5);s.insert({ 2, 8, 3, 9 });//set<int>::iterator it = s.begin();迭代器不可以进行赋值auto it = s.begin();while (it != s.end()){cout << *it << " ";++it;}cout << endl;set<string> strset = { "sort", "insert", "add" };//先构造出临时对象,在进行拷贝构造set<string> strset({ "sort", "insert", "add" });//直接构造return 0;
}
2、删除与查找与迭代器
int main()
{set<int> s = { 4,2,7,2,8,5,9 };for (auto e : s){cout << e << " ";}cout << endl;//erase迭代器失效,分两种情况,一种是节点被删了,出现野指针//第二种是删除头结点,虽然我们采用替代法去删除,但是意义已经发生了改变//只要使用了erases.erase(4);for (auto e : s){cout << e << " ";}cout << endl;s.erase(s.begin());for (auto e : s){cout << e << " ";}cout << endl;/*int x;cin >> x;int num = x;if (x == 0){cout << x << "不存在" << endl;}else{cout << "删除成功" << endl;}*///int x;//cin >> x;////利用二叉搜索树的性质的find效率更高O(logN)//auto pos = s.find(x);////用STL的findO(N)//auto pos1 = find(s.begin(), s.end(), x);//if (pos != s.end())//{// s.erase(pos);//}//else//{// cout << x << "do not exists" << endl;//}int x;cin >> x;if (s.count(x)){cout << "exist" << endl;}else{cout << "do not exist" << endl;}return 0;
}
3、lower_bound和upper_bound
int main()
{std::set<int> myset;for (int i = 0; i < 10; i++){myset.insert(i * 10);}for (auto e : myset){cout << e << " ";}cout << endl;//删除30,40,50//>=auto itlow = myset.lower_bound(30);//>auto itupper = myset.upper_bound(60);//所有容器结构左闭右开myset.erase(itlow, itupper);for (auto e : myset){cout << e << " ";}cout << endl;return 0;
}
4、multiset
基本上和set完全类似,但是支持数据冗余
int main()
{multiset<int> s({ 1,5,3,8,6,9,3,2,6 });auto it = s.begin();for (auto e : s){cout << e << " ";}cout << endl;//查找中序遍历的第一个三//找到3,再在3的左子树找,如果左子树找不到3,那么当前节点就是中序的第一个3s.erase(3);for (auto e : s){cout << e << " ";}cout << endl;cout << s.count(3) << endl;return 0;
}
三、map
map一个节点里存两个值,插入的是pair,里面有first和second两个数据
1、插入和构造以及迭代器
int main()
{//只有insert和key和value都有关,其他的只看keymap<string, string> dict;pair<string, string> kv1("first", "第一个");dict.insert(kv1);//插入匿名对象dict.insert(pair<string, string>("first", "第一个"));//调用make_pairdict.insert(make_pair("sort", "排序"));//插入时只看前面的key,后面的value并不会更新dict.insert(make_pair("auto", "自动的"));dict.insert(make_pair("auto", "非人工的"));//使用隐式类型转换dict.insert({ "computer", "电脑" });map<string, string>::iterator it = dict.begin();while (it != dict.end()){cout << (*it).first << ":" << (*it).second << endl;cout << it->first << ":" << it->second << endl;cout << it.operator->()->first << ":" << it.operator->()->second << endl;++it;}cout << endl;cout << dict.count("computer") << endl;return 0;
}
2、operator【】重载
int main()
{map<string, int> countmap;string arr[] = { "哈密瓜", "香蕉", "苹果" ,"苹果"};for (const auto& str : arr){//插入、查找+修改//str存在时,修改;str不存在是,插入+修改countmap[str]++;//map内部使用的insert//operator【】重载的方式如下//int operator[](const string& str)// {//pair<iterator, bool> ret = insert({str, int()});//这里给的是整型的缺省值,即1// iterator it = ret.first// return it->second;// }//}for (const auto& e : countmap){cout << e.first << ":" << e.second << endl;}cout << endl;return 0;
}
3、operator【】重载的功能:查找、修改、插入
int main()
{map<string, string> dict;dict.insert(make_pair("sort", "排序"));//这里就是普通的插入功能dict["insert"];//插入+修改dict["left"] = "左边";//修改dict["left"] = "左边, 修改";auto it = dict.begin();while (it != dict.end()){cout << it->first << ":" << it->second << endl;it++;}return 0;
}