C++容器——集合(set)

1. 简介

set是一种关联式容器,包含的key值唯一,且会进行排序;增加、修改和查询具有对数的时间复杂度,其存储结构为红黑树;

头文件和定义

//头文件
#include <set>

//定义
template<
    class Key,
    class Compare = std::less<Key>,
    class Allocator = std::allocator<Key>
> class set;

2. 初始化

初始化的方法主要包括直接初始化、复制初始化和拷贝初始化

示例

#include <iostream>
#include <set>
#include <string>
#include <algorithm>

template<typename T>
void showInfo(T &t)
{
	for(auto &au : t)
	{
		std::cout<<au<<" ";
	}
}

int main(int argc, char *argv[])
{
	std::set<std::string> s;
	s.emplace("c++");
	s.emplace("c");
	s.emplace("java");
	s.emplace("shell");
	
	//std::for_each(s.begin(), s.end(), [](auto &a){std::cout<<a<<" ";});           //自动类型推导c++14之后才支持
	//std::for_each(s.begin(), s.end(), [](std::string str){std::cout<<str<<" ";});   //指定类型,c++11就可以

	showInfo(s);
	std::cout<<std::endl;

	std::set<int32_t> s1;
	s1 = {23,4,5,1,2,10};
	showInfo(s1);
	std::cout<<std::endl;

	std::set<int32_t> s2{34,5,6,7,98,1,2};
	showInfo(s2);
	std::cout<<std::endl;

	std::set<int32_t> s3 = s2;
	showInfo(s3);
	std::cout<<std::endl;

	std::set<int32_t> s4 = {100,200,50,160,50,160};    //重复的数据会被过滤掉
	showInfo(s4);
	std::cout<<std::endl;


	return 0;
}

结果

c c++ java shell
1 2 4 5 10 23
1 2 5 6 7 34 98
1 2 5 6 7 34 98
50 100 160 200

3. 使用

3.1 元素访问

方法说明
iterator集合元素的遍历

示例

int main(int argc, char *argv[])
{
	std::set<std::string> s1{"c++", "c", "java", "shell"};
	auto it = s1.begin();
	std::cout<<"it is: "<<*it<<std::endl;
	std::advance(it, 2);   //移动位置
	std::cout<<"it is: "<<*it<<std::endl;

	return 0;
}

输出

it is: c
it is: java

3.2 元素的大小

方法说明
empty集合判空
size集合大小
max_size最大容量
clear清空set的大小
swap交换两个set的内容

示例

int main(int argc, char *argv[])
{
	std::set<std::string> s1{"c++", "c", "java", "shell"};
	std::cout<<"size is: "<<s1.size()<<std::endl;
	std::cout<<"max_size is: "<<s1.max_size()<<std::endl;	

	std::cout<<"\n"<<"[s1 s2]"<<std::endl;
	std::set<std::string> s2{"student", "teacher"};
	showInfo(s1);
	std::cout<<std::endl;
	showInfo(s2);
	std::cout<<std::endl;

	std::cout<<"\n"<<"[swap][s1 s2]"<<std::endl;
	s1.swap(s2);
	showInfo(s1);
	std::cout<<std::endl;
	showInfo(s2);
	std::cout<<std::endl;

	s1.clear();
	if(s1.empty())
	{
		std::cout<<"empty"<<std::endl;
	}
	else{
		std::cout<<"not empty"<<std::endl;
	}
	
	return 0;
}

结果

size is: 4
max_size is: 288230376151711743

[s1 s2]
c c++ java shell
student teacher

[swap][s1 s2]
student teacher
c c++ java shell
empty

3.3 元素的修改

主要包括元素的赋值、插入和删除等,相关的操作和list还是存在差异

方法说明
=直接赋值
get_allocator返回内存分配器
insert插入元素
emplace插入元素
emplace_hint插入元素
erase删除元素
erase_if(C++20)条件删除,通常和lambda一起使用
extract(C++17)元素的删除,可以返回该值
merge(C++17)set的合并

示例

int main(int argc, char *argv[])
{
	//1.元素增加
	std::set<std::string> s1{"c++", "c", "java", "shell"};
	std::cout<<"s1 is: ";
	showInfo(s1);	

	std::cout<<"(insert)s1 is: ";
	s1.insert("python");
	showInfo(s1);	

	std::cout<<"(emplace)s1 is: ";
	s1.emplace("linux");
	showInfo(s1);	

	std::cout<<"(emplace_hint)s1 is: ";
	s1.emplace_hint(s1.begin(), "matlab");    //需要带位置
	showInfo(s1);
	std::cout<<std::endl;

	//2.元素删除
	auto iter = s1.find("c");	
	std::cout<<"find value is: "<<*iter<<std::endl;
	s1.erase(iter);    //erase通常和find()一起使用	
	showInfo(s1);
	std::cout<<std::endl;

	//3.extract(17) merge(17)
	std::cout<<std::endl;
	std::set<int32_t> s2{12,34,5,6,7,89};
	auto s2_iter = s2.find(7);	
	auto va = s2.extract(s2_iter);   //元素删除,并可以保存其结果
	showInfo(s2);

	std::set<int32_t> s3{1,3,5,6,7,9};
	s2.merge(s3);    //元素的合并
	showInfo(s2);

	return 0;
}

结果

s1 is: c c++ java shell
(insert)s1 is: c c++ java python shell
(emplace)s1 is: c c++ java linux python shell
(emplace_hint)s1 is: c c++ java linux matlab python shell

find value is: c
c++ java linux matlab python shell


5 6 12 34 89
1 3 5 6 7 9 12 34 89

3.4 元素的操作

方法说明
count计算set中元素出现的次数
find查找元素
equal_range返回的是一个范围 [lower_bound, upper_bound]
lower_bound返回当前元素的位置,查找不到返回end
upper_bound返回当前元素的下一个位置,查找不到返回end
key_comp比较函数
value_comp比较函数

示例

int main(int argc, char *argv[])
{
	//1.元素计算
	std::set<std::string> s1{"c++", "c", "java", "shell","c"};
	showInfo(s1);
	std::cout<<s1.count("c")<<std::endl;
	std::cout<<s1.count("c++")<<std::endl;

	//2.find
	auto re = s1.find("java1");
	if(re != s1.end())
	{
		std::cout<<"the result of find is: "<<*re<<std::endl;
	}
	else
	{
		std::cout<<"can not find the value."<<std::endl;
	}
	std::cout<<std::endl;

	//3.equal_range,返回的是一个范围
	auto eq_iter = s1.equal_range("java");
	std::cout<<"equal_range first elemenet is: "<<*eq_iter.first<<std::endl;
	std::cout<<"equal_range second elemenet is: "<<*eq_iter.second<<std::endl<<std::endl;

	//4.lower_bound,返回c++
	auto lower_iter = s1.lower_bound("c++");
	std::cout<<"lower_iter value is: "<<*lower_iter<<std::endl<<std::endl;

	//3.upper_bound,返回java
	auto upper_iter = s1.upper_bound("c++");
	std::cout<<"upper_iter value is: "<<*upper_iter<<std::endl<<std::endl;

	//4.key_comp 比较函数
	std::set<int32_t> s2{2,3,4,11,23,44};
	auto comp_func = s2.key_comp();
	for(auto au : s2)
	{
		//au > 10?  au和10的位置互换,则是10>au
		if(comp_func(au, 10))
		{
			std::cout<<"true ";
		}
		else{
			std::cout<<"false ";
		}
	}
	std::cout<<std::endl;	

	//5.value_comp 比较函数
	auto value_func = s2.value_comp();
	for(auto au : s2)
	{
		//au > 10?  au和10的位置互换,则是10>au
		if(value_func(au, 10))
		{
			std::cout<<"true ";
		}
		else{
			std::cout<<"false ";
		}
	}
	std::cout<<std::endl;	

	return 0;
}

结果

c c++ java shell
1
1
can not find the value.

equal_range first elemenet is: java
equal_range second elemenet is: shell

lower_iter value is: c++

upper_iter value is: java

true true true false false false
true true true false false false

3.5 迭代器

迭代器最好结合STL中的算法一起使用;迭代器的返回值最好用auto接收;

set不能通过下标进行访问,只能通过迭代器访问其中的元素,所以迭代器和其辅助函数用的比较多,同时会加上一些算法;

迭代器的类型包括:iterator、const_iterator、reverse_iterator和const_reverse_iterator

方法说明
begin返回set的头元素(迭代器),其值可修改
end返回set的尾元素(迭代器),其值可修改
cbegin返回set的头元素(迭代器),其值不可修改,const属性
cend返回set的尾元素(迭代器),其值不可修改,const属性
rbegin反序返回set的头元素(迭代器),其值可修改,同end()
rend反序返回set的尾元素(迭代器),其值可修改,同begin()
crbegin反序返回set的头元素(迭代器),其值不可修改,同cend,const属性
crend反序返回set的头元素(迭代器),其值不可修改,同cbegin,const属性

迭代器的辅助函数
辅助函数的使用需要包含头文件

#include <iterator>
方法说明
advance移动迭代器的位置
distance计算两个迭代器的距离
begin返回容器第一个元素的迭代器
end返回容器最后一个元素的迭代器
prev迭代器向前移动一个元素
next迭代器向后移动一个元素
  • 1
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值