首页 > 学院 > 开发设计 > 正文

数据结构::STL库里map和set的用法简介

2019-11-08 19:34:40
字体:
来源:转载
供稿:网友

前言:

【pair的简介】:

1、它是一种模板类型的结构体,定义在头文件#include<utility>

template<class T1,class T2>

2、有两个成员是first,second

3、模板参数可以是任何类型的

【STL简单提要】:

1、分为序列式容器和关联式容器

1)序列式容器就是里面操作的数据无关联,比如:vector,它的操作push,pop

2)关联式容器就是里面操作的数据有关联,比如:set,map,它的操作insert,erase

一、set(集合)

1、概念:

*set是一种Key结构,它的元素就是它的键值,它的键值唯一,不允许重复,它里面的数都会被自动排序。

*它也是模板类型的:

template < class T,class Compare = less<T>,           class Alloc = allocator<T> > class set;

1)第一个参数是键值类型

2)第二个模板参数可以利用仿函数实现,这样我们就可以控制在set中插入值的时候是按什么顺序进行排列的

3)第三个参数是空间配置器

2、特点:

1)插入到set中的值是排好序的

2)如果重复进行插入的话,set是会把重复的值过滤掉的(防冗余)

3、底层实现原理:

它在底层是利用红黑树进行实现的,但注意它的底层插入机制是insert_unique

4、一些接口的简单使用:

1)insert

三种类型:

A:直接插入一个值:pair<iterator,bool> insert ( const value_type& x );B:在特定的位置插入一个值:iterator insert ( iterator position, const value_type& x );C:插入一段区间:template <class InputIterator>void insert ( InputIterator first,InputIterator last);

用代码简单使用:

void TestSet(){	//插入的测试	//1、直接插入一个值	set<int> s1;	s1.insert(1);	s1.insert(2);	s1.insert(3);	s1.insert(4);	s1.insert(5);	//2、在特定的位置进行插入	/*s1.insert(s1.begin(),10);	s1.insert(s1.begin(),5);	s1.insert(s1.begin(),7);	s1.insert(s1.begin(),9);*/	//3、插入一段区间	//s1.insert (s1.begin(),s1.end());		set<int>::iterator it1 = s1.begin();	while(it1 != s1.end())	{		cout<<*it1<<" ";		it1++;	}	cout<<endl;}

2)erase

三种类型:

A:删除特定位置的值:void erase ( iterator position );B:删除一个值:size_type erase ( const key_type& x );C:删除一段迭代器区间:void erase ( iterator first, iterator last );

用代码简单使用:

void TestSet(){	//插入的测试	//1、直接插入一个值	set<int> s1;	s1.insert(1);	s1.insert(2);	s1.insert(3);	s1.insert(4);	s1.insert(5);	//2、在特定的位置进行插入	/*s1.insert(s1.begin(),10);	s1.insert(s1.begin(),5);	s1.insert(s1.begin(),7);	s1.insert(s1.begin(),9);*/	//3、插入一段区间	//s1.insert (s1.begin(),s1.end());			//删除的测试	//1、直接删除值	//说明:删除这个值得时候,如果不在你原本的插入数据中时,不会发生崩溃	/*s1.erase(4);	s1.erase(1);	s1.erase(6);*/	//2、删除一个特定位置的值	//说明:如果是删除一个位置上的数的话,如果没有这个数的话,删除的话	//      就会崩溃	//set<int>::iterator pos = s1.find(6);	//s1.erase(pos);	//3、删除一段迭代器区间	//s1.erase(++s1.begin(),--s1.end());		set<int>::iterator it1 = s1.begin();	while(it1 != s1.end())	{		cout<<*it1<<" ";		it1++;	}	cout<<endl;}说明:要注意的点我在上面的测试代码中已经说明。

3)count:

判断一个值是否存在,存在的话返回1,不存在返回0

	//如果要查找值是否存在,那么可以用find先进行查找,然后再进行	//判断是否存在	map<string,int>::iterator it1 = countstr.find(1);	if(it1 != countstr.end())	{}	else	{}	//而如果用count的话,因为它的意义。我们可以直接来进行判断	if(countstr.count(key) > 0)	{}	else	{}

4)emplace:

c++11新特性:

说明:用于插入一个元素,比insert的效率高一些, insert插入的时候返回是先进行构造一个临时对象,然后通过这个临时对象再进行拷贝构造,而emplace是直接就进行的构造,效率更高一些

简单使用:

       set<string> s2;	s2.emplace("hello");	auto ret = s2.emplate("hello");	if(!ret.second)	cout<<"hello 已经存在"<<endl;

5)find:

  iterator find(const value_type& val) const;

 如果找到的话就返回这个位置的迭代器,否则就返回end。

6、应用:

1)因为set里有检查值是否存在的接口count,因此我们可以使用set来进行单词拼写的检查

2)插入的时候有防冗余的作用,可以用于过滤,我们可以用其实现爬虫

二、map(映射)

1、概念:

*map是一种key(键值)-value(实值)结构;

 它的每一种键值对应它的实值。

 它有键值和实值,它的键值是不允许更改的,但是它的实值是可以不同的。

 map中的所有元素都是pair,pair的first被视为键值,它的second被视为实值。

(map的每个元素都是pair类型。typedef pair<K,V> value_type;)

*它也有和set类似的模板结构

template<class Key,class T,classCompare=less<Key>,class Alloc=allocator<pair<const Key,T> > >它有四个模板参数类型,第一个是键值的类型。第二个是实值的类型。第三个是一个仿函数,它传入的是键值的比较方式,默认是升序排列。第四个是空间配置器。

2、底层实现:

也是通过红黑树进行实现的

3、一些常用接口的简介

1)insert:

三种类型:

  *pair<iterator,bool> insert(const value_type& val);  说明: 插入一个value_type类型,返回值是一个pair类型。    pair<iterator,bool>=pair<map<K,V>::iterator,bool>。如果插入成功的话则bool就为true,且iterator指向插入的位置,否则的话iterator就指向已经存在的这个元素的位置。iterator是一个pair<K,V>类型的迭代器。  *iterator insert(iterator,const value_type& val)    在一个迭代器的位置插入一个value_type类型的数据,如果插入成功的话返回这个成功位置的迭代器,如果失败的话则返回这个传入的迭代器。

   *template<class InputIterator>    void insert(InputIterator first,InputIterator last);    插入一段迭代器区间

2)erase:

  *void erase(iterator position)    删除一个这个迭代器位置的元素。  *size_type erase(const key_type& k)    删除这个键值所在的位置,成功返回1,失败返回0  *void erase(iterator first,iterator last);    删除一段迭代器区间。

3)find:

    iterator find(const key_type& k)    如果查找成功的话则返回这个元素的迭代器,否则返回end,所以在使用find返回的迭代器之前要先判断一下。

4)count:

    size_type count(const key_type& k)const   与set的count功能一样。

5)Operator[]

    mapped_type& operator[](const key_type& k)    map中的operator[]是最常用的,如果map中有这个k,则它就把这个k所对应的value的引用返回。如果map中没有这个k的话,则它会调用insert(pair<K,V>(k,V())),将k和V的缺省值对应起来插入进去,并返回这个value的引用。  

   模拟实现下重载下标操作符:

	V& operator[](const K& key)	{		pair<iterator,bool> ret = insert(const K& key,const V& value);		return ret->first.second;	}

3、应用:

1)通常用来实现字典结构

2)统计字符串出现的个数等等

三、multiset和multimap简单说明

1、multiset:

1)接口和set类似

2)要说明的:

     **multiset的插入是不防冗余的,插入的原则就是中序遍历之后是有序即可

     **multiset要是要查找一个重复插入的值的话,它找到的是这些重复数的第一个。

#include<iostream>//#include<multimap>#include<set>using namespace std;void TestMultimap(){	multiset<int> m2;	m2.insert(1);	m2.insert(2);	m2.insert(3);	m2.insert(2);	m2.insert(5);	multiset<int>::iterator it2 = m2.find(2);	cout<<*it2<<endl;	it2++;	cout<<*it2<<endl;	it2++;};int main(){	TestMultimap();	return 0;}

2、multimap:

1)key可以相同,但是value可以不同,这是要和map进行区别的一点

2)它没有重载下标运算符[]

3)它里面的count是真正意义上的进行统计个数,因为它也是不防冗余的,而在set和map中,count其实就只是充当找这个值是否存在。

四、一些要说的琐碎之话:

1、关于空间适配器和容器的区别

   适配器说白了就是用于转换。我用下面的栈和map举个例子来说明下:

1)stack和queue是适配器

2)map和set是容器


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表