STL结合容器之set/multiset详解

1. STL结合容器中的set/multiset容器

 

STL(Standard Template Library,标准模板库)是惠普实验室开发的一系列软件的统称。它是由Alexander Stepanov、Meng Lee和David R Musser在惠普实验室工作时所开发出来的。现在虽说它主要出现在C++中,但在被引入C++之前该技术就已经存在了很长的一段时间。

STL的代码从广义上讲分为三类:algorithm(算法)、container(容器)和iterator(迭代器),几乎所有的代码都采用了模板类和模版函数的方式,这相比于传统的由函数和类组成的库来说提供了更好的代码重用机会。

在C++标准中,STL被组织为下面的13个头文件

STL提供了很多种容器,每种容器都提供一组操作行为即算法接口。结合容器是STL提供的容器中的一种,其中的元素 都是经过排序的,它主要通过关键码的方式来提高查询的效率。结合容器包括set、multiset、map、multimap、hash table。

 


1.1 set/multiset的基本概念

set类又称为集合类模版,一个集合对象像链表一样顺序的存储一组值。在一个集合中,集合元素既充当存储的数据,又充当数据的关键码。可以使用下面的几种方法来创建set对象。

set拥有和list某些相同的性质,当对容器中的元素进行插入操作或者删除操作的时候,操作之前所有的迭代器,在操作完成之后依然有效,被删除的那个元素的迭代器必然是一个例外。

set/multiset默认的构造函数和拷贝构造函数:

set st;//set默认构造函数:

mulitset mst; //multiset

默认构造函数: set(const set &st);//拷贝构造函数

 

创建一个list对象,可以通过一些方式:

1) std::set name; //创建一个单元诉set对象

2) std::set name(myset); //创建一个名为name,并且包含type类型数据的set空对象,该对象使用predicate所指向的函数里对集合中的元素进行排序。

3) std::set name(first,last); //这种方法范围的元素中根据多重指示器所指示的起始和终止位置创建一个集合。

注:multiset特性及用法和set完全相同,唯一的差别在于它允许键值重复。set和multiset的底层实现是红黑树.

1.2 set/multiset的特点

a. set和multiset的底层实现是红黑树。

b. set和multiset的元素不可随机存取,但元素搜寻速度很快。

c. 对插入元素自动排序,可以指定元素排序方式。

 

1.3 set/multiset的迭代器

set/multiset有定义自己的迭代器。

迭代器的用法如下:

创建一个iSet集合,然后通过迭代器遍历他的元素。

	set iSet; //创建一个整数集合
    set::iterator it; 
	for (it = iSet.begin(); it != iSet.end(); it++)
	{
		cout << *it << endl;
	}

1.4 set/multiset的数据结构

set/multiset的底层实现是红黑树,一个集合对象像链表一样顺序的存储一组值。

下面讲set对象插入时会涉及到pair,这里介绍一下对组(pair):

对组(pair)将一对值组合成一个值,这一对值可以具有不同的数据类型,两个值可以分别用pair的两个公有属性first和second访问。
类模板:template struct pair.

	//第一种方法创建一个对组
	pair pair1(string("name"),20);
	cout << pair1.first << pair1.second << endl;
	//第二种
	pair pair2 = make_pair("name",30);
	cout << pair2.first << pair2.second << endl;
	//pair=赋值
	pair pair3 = pair2;
	count << pair3.first << endl;
	cout << pair3.second << endl;

set的使用场景:比如对手机游戏的个人得分记录的存储,存储要求从高分到低分的顺序排列。

 

1.5 set/multiset的常用API

函数 说明
begin() 返回指向集合中第一个元素的迭代器
clear() 删除集合中所有元素
empty() 如果集合为空,则返回为true值

end

返回指向集合中最后一个元素的迭代器
erase(i) 删除迭代器i所指向的集合元素
erase(start,end) 删除迭代器start和end所管辖范围内的集合元素
erase(x) 删除集合中值为x的元素
equal_range(x) 返回表示x下界和上界的两个迭代器,下界表示集合中有一个值等于x的元素,上界表示第一个值大于x的元素
insert(i,start,end) 把迭代器start和end所管辖范围内的元素插入到集合中由迭代器i所指明的位置
insert(i,x) 把值x插入集合中,x的插入位置从迭代器i所指明的元素处开始查找
insert(x) 把x插入集合
find(x) 返回一个指向x的迭代器。如果x不存在,返回的迭代器等于end
lower_bound(x) 返回一个迭代器,指向位于x之前且紧邻x的元素。
max_size() 返回集合的最大容量
upper_bound(x) 返回一个指向x的迭代器
push_front(x) 把x放到链表的开始
rbegin 返回一个反向迭代器,指向链表末尾元素之后
rend 返回一个反向迭代器,指向链表起始元素
size() 返回链表的大小(元素的个数)
swap(list) 交换两个集合的内容
value_comp 返回value_compare类型的对象,该对象用于判断集合中元素的先后顺序

 

1)insert接口的应用代码如下:

set集合的insert的函数返回的是一个pair类型,如果插入数据成功则pair对象的second的值为true,如果插入失败pair对象的second的值为非0.

	set s;
	pair::iterator, bool> ret = s.insert(10);
	if (ret.second)
	{
		cout << "插入成功:" << *ret.first << endl;
	}
	else
	{
		cout << "插入失败:" << *ret.first << endl;
	}

 

2)set集合的双元素类型对象,第二个参数可以确定排序方式。

std::set name(myset); //创建一个名为name,并且包含type类型数据的set空对象,该对象使用predicate所指向的函数里对集合中的元素进行排序。

//set set两元素情况下,第二个元素可以用于决定set的排序方式
struct MyCompare02{

	bool operator()(int v1, int v2)
	{
		return v1 > v2;
	}
		
};
void test_set_02(void)
{
	srand((unsigned int)time(NULL));
	//我们发现set容器的第二个模版可以设置拍讯规格,默认是从小到大
	set s;
	for (int i = 0; i < 10; i++)
	{
		s.insert(rand()%100);
	}

	for (set::iterator it = s.begin(); it != s.end(); it++)
	{
		cout << *it << " ";
	}

	cout << endl;

}

3)set的find(x)函数用法,如果找到了返回对应元素的迭代器,如没有找到返回set集合对象的end()。

    set cSet; //创建一个整数集合
	cSet.insert('D');
	cSet.insert('B');
	cSet.insert('C');
	cSet.insert('A');
	cSet.insert('F');
	cout << "old set:" << endl;
	set::iterator it;
	for (it = cSet.begin(); it != cSet.end(); it++)
	{
		cout << *it << endl;
	}
	char cTmp;
	cTmp = 'F';
	it = cSet.find(cTmp);
	cout << "start find cTmp" << endl;
	if (it == cSet.end())
	{
		cout << "not find" << endl;
	}
	else
	{
		cout << "find " << endl;
	}

 

你可能感兴趣的:(C++,c++)