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

前言:

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是容器



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值