C++ STL:set和map的结构及接口使用

目录

一. set和map的简介

1.1 set的简介

1.2 map的简介 

二. set的主要接口函数及使用方法

2.1 构造及赋值相关接口函数

2.2 通过迭代器遍历set

2.3 结构修改相关接口函数

2.4 其他主要接口函数

三. map的主要接口函数及使用方法 

3.1 构造和赋值相关接口函数

3.2 通过迭代器遍历map

3.3 结构修改相关接口函数

3.3 查找和访问相关接口函数


一. set和map的简介

1.1 set的简介

  • set是按照一定的次序顺序存储数据的容器。
  • set的底层是通过二叉搜索树(红黑树)来实现的。
  • 在默认情况下,set底层的二叉树遵循左子节点小于根节点、右子节点大于根节点且不能有相同节点的结构要求。
  • 每个节点的值key具有const属性,不能被修改。
  • 在set中查找某个特定数据的时间复杂度是O(NlogN)。
  • 默认情况下,使用正向迭代器遍历set,是按照中序遍历进行的,也就是说会得到一组升序的数据。
  • set不可以存储相同的节点,但是multiset可以,multiset与set唯一的不同就是可以存储相同值的节点。
图1.1 set和multiset的声明

1.2 map的简介 

  • map是关联式容器。其结构与set类似,底层都是通过红黑树来实现的。
  • map和set的不同在于,map存储的数据类型是以Key和Value组成的键值对<Key, Value>,通过比较Key的值来使map满足搜索树的结构要求,而Value只是与Key进行配对的数据,不参数比较。
  • map中不允许存储两个Key相同的节点,但是multimap允许。
图1.2 map和multimap的声明

二. set的主要接口函数及使用方法

2.1 构造及赋值相关接口函数

接口函数功能
set(const compare& comp = compare)默认构造,创建空树
set(InputIterator first, InputIterator last, ...)使用迭代器区间初始化
set(const set& x)拷贝构造
set& operator=(const set& x)赋值运算符重载函数

代码2.1:(构造和赋值) 

int main()
{
	int arr[5] = { 5,2,3,4,1 };
	std::set<int> st1;   //默认构造
	std::set<int> st2(arr, arr + 5);   //迭代器区间构造
	std::set<int> st3(st2);  //拷贝构造

	std::set<int, std::greater<int>> st4;   //创建右子节点大于根节点左子节点小于根节点的set
	st1 = st3;  //赋值

	return 0;
}

2.2 通过迭代器遍历set

默认情况下,使用正向迭代器遍历set是进行中序遍历,得到一组升序的数据。

代码2.2:(set遍历的直接实现) 

int main()
{
	int arr[5] = { 5,2,3,4,1 };
	std::set<int> st1(arr, arr + 5);
	std::set<int, std::greater<int>> st2(arr, arr + 5);

	//给定迭代器
	std::set<int>::iterator it1 = st1.begin();
	std::set<int, std::greater<int>>::iterator it2 = st2.begin();

	//正向迭代器遍历st1,得到一组升序数据
	while (it1 != st1.end())
	{
		std::cout << *it1++ << " ";
	}
	std::cout << std::endl;

	//正向迭代器遍历st2,得到一组降序数据
	while (it2 != st2.end())
	{
		std::cout << *it2++ << " ";
	}
	std::cout << std::endl;

	return 0;
}
图2.1 对set前序遍历的运行结果

代码2.3:(set遍历的函数模板实现)

template<class T, class Compare = std::less<T>>
void SetPrint(const std::set<T, Compare>& st)
{
	typename std::set<T, Compare>::const_iterator it = st.begin();
	while (it != st.end())
	{
		std::cout << *it++ << " ";
	}
	std::cout << std::endl;
}

2.3 结构修改相关接口函数

接口函数功能
pair<iterator,bool> insert(const Type& x)在插入值为x的节点
void insert(InputIterator first, InputIterator last)插入位于一段迭代器区间的数据集
size_t erase(const Type& x)删除指定值
void erase(iterator pos)通过给定迭代器位置删除特定节点
void clear()清空所有节点
  • 这里需要注意insert函数的返回值:insert函数返回一键值对,pair中的first数据为iterator类型,如果成功插入节点(set中没有x),则返回新插入节点的位置的迭代器,如果插入节点失败,则返回与x值相同的节点的迭代器。pair中的second数据类型为bool,插入成功返回true,失败返回false。
  • erase返回被删除的节点的个数,因为set不允许有相同的节点,因此erase返回值只能是1或0,而multiset中erase的返回值则可以大于1,因为multiset中允许相同节点的存在。
  • 当调用erase函数给定值不存在或迭代器位置不合法时:如果使用给定值x的方法删除set的节点且x不存在,那么函数不进行任何工作,直接返回。如果给定不合法的迭代器位置调用erase,那么程序会崩溃。

代码2.4:(插入、删除和清空操作) 

int main()
{
	std::set<int> st;
	st.insert(7);
	st.insert(1);
	st.insert(0);
	st.insert(4);
	st.insert(5);   //插入数据
	SetPrint(st);   //set正向遍历打印函数

	st.erase(7);
	st.erase(10);
	st.erase(0);
	SetPrint(st);

	st.clear();   //清空元素
	SetPrint(st);

	return 0;
}
图2.2 代码2.4的运行结果

2.4 其他主要接口函数

接口函数功能
iterator find(const Type& x) const查找特定数据x函数
size_t  count(const Type& x) const统计set中x出现的次数
iterator lower_bound (const Type& x) const返回大于或等于x的最小节点
iterator upper_bound (const Type& x) const返回大于x的最小节点
pair<iterator,iterator> equal_range (const Type& x) const返回包含x的区间
  • find函数如果没有找到值为x的节点,就返回end()的迭代器位置,如果要使用find函数的返回值,保险起见,应当检查 st.find(x) != st.end() 是否成立。
  • 由于set中不允许有相同的节点,count的返回值只能是0或1。
  • equal返回的区间只包含一个数:[first, second) -- 左开右闭区间,*first = x。

代码2.5:

int main()
{
	std::set<int> st = { 10,10,20,30,40,40,50,60,70,80,90 };

	//查找数据20 -- 找得到
	std::set<int>::iterator pos1 = st.find(20);  
	if (pos1 != st.end())
	{
		std::cout << "找到了" << std::endl;
	}
	else
	{
		std::cout << "没找到" << std::endl;
	}

	//查找数据100 -- 找不到
	std::set<int>::iterator pos2 = st.find(100);
	if (pos2 != st.end())
	{
		std::cout << "找到了" << std::endl;
	}
	else
	{
		std::cout << "没找到" << std::endl;
	}

	std::set<int>::iterator it1 = st.lower_bound(30);
	std::set<int>::iterator it2 = st.lower_bound(40);
	std::set<int>::iterator it3 = st.upper_bound(40);
	std::set<int>::iterator it4 = st.upper_bound(45);

	std::cout << "*it1 = " << *it1 << std::endl;
	std::cout << "*it2 = " << *it2 << std::endl;
	std::cout << "*it3 = " << *it3 << std::endl;
	std::cout << "*it4 = " << *it4 << std::endl;

	std::pair<std::set<int>::iterator, std::set<int>::iterator> pa = st.equal_range(50);
	std::cout << "first=" << *pa.first << ", " << "second=" << *pa.second << std::endl;

	return 0;
}
图2.3 代码2.5的运行结果

三. map的主要接口函数及使用方法 

3.1 构造和赋值相关接口函数

接口函数功能
map(const compare& comp = compare)默认构造,创建空树
map(InputIterator first, InputIterator last, ...)使用迭代器区间初始化
map(const map& x)拷贝构造
map& operator=(const map& x)赋值运算符重载函数

代码3.1:(构造和赋值)

int main()
{
	std::map<int, int> mp1;  //默认构造

	std::map<int, int> rmp;
	rmp[1] = 1;
	rmp[3] = 3;
	rmp[2] = 2;

	std::map<int, int> mp2(rmp.begin(), rmp.end());  //通过迭代器区间构造
	std::map<int, int> mp3(mp2);  //拷贝构造
	mp1 = mp2;  //赋值

	return 0;
}

3.2 通过迭代器遍历map

注意:由于map存储的是键值对,对于map的迭代器it,不能直接对it解引用,*it会报错。如果想获取键值对中的数据,应当使用(*it).first/second 或it->first/second。

代码3.1:(迭代器遍历map)

int main()
{
	std::map<int, int> mp;
	mp[1] = 1;
	mp[3] = 3;
	mp[2] = 2;

	std::map<int, int>::iterator it = mp.begin();
	while (it != mp.end())
	{
		//std::cout << (*it).first << "=>" << (*it).second << " ";
		std::cout << it->first << "=>" << it->second << " ";
		++it;
	}
	std::cout << std::endl;

	return 0;
}
图3.2 代码3.1的运行结果

3.3 结构修改相关接口函数

接口函数功能
pair<iterator,bool> insert(const pair<T1,T2>& x)数据插入函数
void insert(InputIterator first, InputIterator second)插入某段迭代器区间的数据
size_t erase(const Type_Key& x)删除键值对中Key为x的数据
void erase(iterator pos)删除特定迭代器位置的节点
void erase(iterator first, iterator second)删除特定迭代器区间的节点
void clear()清空元素
  • make_pair(const Type1& key, const Type2& value) -- 键值对创建函数,给定参数为键值对的key和value,返回键值对pair<Type1,Type2>

代码3.2:(结构修改)

int main()
{
	std::map<int, int> mp;
	mp.insert(std::make_pair(5, 5));
	mp.insert(std::make_pair(7, 7));
	mp.insert(std::make_pair(3, 3));
	mp.insert(std::make_pair(1, 1));
	mp.insert(std::make_pair(9, 9));   //插入数据

	std::map<int, int>::iterator it = mp.begin();
	while (it != mp.end())
	{
		std::cout << it->first << "=>" << it->second << " ";
		++it;
	}
	std::cout << std::endl;

	mp.erase(1);
	mp.erase(9);  //给定值删除
	mp.erase(mp.begin());  //给定迭代器位置删除

	it = mp.begin();
	while (it != mp.end())
	{
		std::cout << it->first << "=>" << it->second << " ";
		++it;
	}
	std::cout << std::endl;

	mp.clear();  //清空元素

	return 0;
}
图3.3 代码3.2的运行结果

3.3 查找和访问相关接口函数

接口函数功能
iterator find(const Key_Type x)查找键值对Key为x的节点
Value_Type& operator[](const Key_Type x)

通过指定的Key的值x访问与之配对的Value值

/ 创建Key值为x的新节点

  • operator[]函数:如果在二叉map中找到了x,那么就直接返回与之配对的Value值的引用。如果没有找到x,那么就会以x为Key插入新的节点,但是Value的值就只能调用的类型的默认构造来给初值,无法保证新插入的节点的Value初值是需要的。

代码3.3:(查找和访问)

int main()
{
	std::map<int, int> mp;
	mp.insert(std::make_pair(5, 5));
	mp.insert(std::make_pair(7, 7));
	mp.insert(std::make_pair(3, 3));
	mp.insert(std::make_pair(1, 1));
	mp.insert(std::make_pair(9, 9));   

	std::map<int, int>::iterator it = mp.find(3);
	std::cout << it->first << "=>" << it->second << std::endl;

	mp[3] = 5;  //3存在
	std::cout << "mp[3] = " << mp[3] << std::endl;

	mp[10] = 10;   //10不存在
	std::cout << "mp[10] = " << mp[10] << std::endl;

	return 0;
}
图3.4 代码3.3的运行结果
  • 9
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值