STL中map和set详解

来源:互联网 发布:韩顺平满汉楼数据库 编辑:程序博客网 时间:2024/05/18 00:28

在STL中有这两个容器set和map,它们的特性都是:所有元素都会根据元素的键值自动被排序

下面来介绍一下这两个容器和与之相关的几个容器。

一、set和map

1.set和map的区别和联系

联系:它们的底层实现都是红黑树

区别:set是key形式的,set元素的键值(key)就是实值(value),实值就是键值。而map是key/value形式的,map的所有元素都是pair,同时拥有实值和键值;它们两个的key值都是唯一的,不能有重复。

2.set的常见用法:

<1>元素的插入insert:insert当set中已经有所要插入的元素,则插入失败,若没有,则插入成功。(因为key值唯一)

void TestInsert(){set<int> s1;set<int>::iterator setIt;pair<set<int>::iterator, bool> ret;//插入1:直接插入keys1.insert(1);s1.insert(10);s1.insert(5);s1.insert(7);ret = s1.insert(10);  //已经存在,插入失败//插入二:利用迭代器插入if (ret.second == false)setIt = ret.first;s1.insert(setIt, 6);//插入三:插入一个迭代器区间list<int> l1;l1.push_back(34);l1.push_back(33);l1.push_back(32);l1.push_back(31);list<int>::iterator listIt = l1.begin();s1.insert(listIt, l1.end()); //将list的迭代器区间插入//正向遍历setIt = s1.begin();while (setIt != s1.end()){cout << *setIt << " ";++setIt;}}

<2>元素的删除erase:

void TestErase(){set<int> s1;set<int>::iterator setIt;for (int i = 10; i > 0; --i)s1.insert(i);//删除一:利用迭代器删除(无返回值)setIt = s1.begin();//setIt指向1s1.erase(setIt); //删除二:根据key值删除(删除成功返回1,失败返回0)size_t ret1 = s1.erase(10);size_t ret3 = s1.erase(5);size_t ret2 = s1.erase(20);cout << "删除二返回值:";cout << ret1 << " " << ret2 <<" " << ret3<< endl;//删除三:删除一段迭代器区间setIt = s1.find(7);s1.erase(setIt, s1.end());//遍历cout << "遍历set:";setIt = s1.begin();while (setIt != s1.end()){cout << *setIt << " ";++setIt;}}


<3>查找元素find:参数为key值,找到则返回要查找结点的迭代器,找不到则返回end()

void TestFind(){set<int> s1;set<int>::iterator setIt;for (int i = 10; i > 0; --i)s1.insert(i);setIt = s1.find(8); //存在cout << *setIt << endl;setIt = s1.find(20); //不存在cout << (setIt == s1.end()) << endl; //打印1,说明返回值为end()}

3.map的常见用法:

<1>map的插入insert,删除erase,查找find都和set类似,这里说说操作的不同。

set是key形式的,map是key/value形式的。所以原来传入key的位置现在要传入一个pair结构体类型。

pair类型其实就是:

template<class K, class V>struct pair{K first;V second;};

示例程序如下:

void TestInsert(){map<string, int> wordCount;//示例插入方式之一,插入pair元素,其余与set类似wordCount.insert(pair<string, int>("hello", 1));wordCount.insert(pair<string, int>("world", 3));wordCount.insert(pair<string, int>("aaa", 7));wordCount.insert(pair<string, int>("bbb", 1));PrintMap(wordCount); //遍历map的函数}

<2>map的operator[ ] 方法:

operator[ ] 传入参数为key值,返回值为value的引用。它的内部实现嵌套了insert函数,当传入key值不存在时,就会插入该key。

通过返回value值的引用,可以修改元素的value值。

示例程序:统计出现次数最多的前K种水果。(利用operator[ ]统计水果出现的个数。)

//统计出现次数最多的前K种水果void TopK(vector<string>& fruits){//统计水果出现的次数map<string, int> fruitCount;size_t size = fruits.size();for (size_t i = 0; i < size; ++i){fruitCount[fruits[i]]++;}//排序vector<map<string, int>::iterator> v; //将数据保存在可以随机访问的容器里。map<string, int>::iterator it = fruitCount.begin();while (it != fruitCount.end()){v.push_back(it);++it;}struct CMP{bool operator()(const map<string, int>::iterator l,const map<string, int>::iterator r) const{return (l->second > r->second);}};sort(v.begin(), v.end(), CMP());//输出排序结果for (size_t i = 0; i < v.size(); ++i){cout << v[i]->first << "-" << v[i]->second << endl;}}void TestFruitCount(){vector<string> fruits;fruits.push_back("苹果");fruits.push_back("梨");fruits.push_back("苹果");fruits.push_back("香蕉");fruits.push_back("葡萄");fruits.push_back("苹果");fruits.push_back("苹果");fruits.push_back("梨");fruits.push_back("葡萄");fruits.push_back("西瓜");fruits.push_back("猕猴桃");fruits.push_back("葡萄");fruits.push_back("猕猴桃");fruits.push_back("猕猴桃");fruits.push_back("柠檬");fruits.push_back("香蕉");fruits.push_back("柚子");fruits.push_back("香蕉");TopK(fruits);}


注意:

不能通过迭代器来改变set和map内部的值,因为要保证key值的唯一和元素的顺序

*setIt = 20; //这样是错误的



0 0
原创粉丝点击