现在的位置: 首页 > 综合 > 正文

STL学习笔记—-5.容器 set 和 multiset

2013年08月18日 ⁄ 综合 ⁄ 共 2603字 ⁄ 字号 评论关闭

一. Set 的特点

Set 和 multiset 会根据特定的排序准则,自动将元素排序。两者不同处在于multiset允许元素重复set不允许重复

优点:

搜索元素时具有良好的性能。

限制:

不能直接改变元素值,因为这样会打乱原本正确的顺序,因此要改变元素值,必须先删除旧元素,再插入新元素。

Set 和 multiset 通常以平衡二叉树来实现,如下图:


二. 排序准则

Set<Elem, op>,其中op为排序准则,缺省准则是less,即从小到大排序。

std::set<int, std::greater<int> > coll;  //从大到小
std::set<int, std::less<int> > coll;	//从小到大

std::set<int> coll; //默认less<>,也是从小到大 

三. 搜索函数

由于 set 和 multiset 在元素快速搜索方面有优化设计,所以提供了特殊的搜索函数:

//返回元素值为elem的元素个数
s.count(elem)

//返回第一个元素值为 elem 的位置,找不到的话返回end()
s.find(elem)

//返回 elem 的第一个可以安插的位置,也就是 (元素值 >=elem)的位置
s.lower_bound(elem)

//返回 elem 的最后一个可以安插的位置,也就是(元素值 > elem)的位置
s.upper_bound(elem)

//返回 elem 可以安插的第一个位置和最后一个位置,也就是(元素值 == elem) 的元素区间
s.equal_range(elem)

四. 插入和删除函数

//插入elem元素,返回新元素的位置,pos 指出插入操作的搜寻起点,如果 pos 恰当可以加快速度
c.insert(pos,elem)
c.insert(elem)
	

//删除与elem相等的元素,返回删除元素的个数
c.erase(elem)

c.erase(pos)
c.erase(beg, end)

注意插入操作的返回值:

因为 set 不允许重复,面 multiset 允许重复,所以他们的 insert 操作有不有同的返回值。

//set 提供的接口
pair<iterator, bool> insert(const value_type& elem); //返回 pair<>

因为 set 不允许元素重复,所以如果插入相同的元素,将会返回失败

Pari 的 secode 成员表示插入是否成功。

Pair 的 first 成员返回新元素的位置。

//multiset 提供的接口
iterator            insert(const value_type& elem); //返回新元素的位置

注意删除操作:

//删除与 elem 相等的元素,返回删除元素的个数
c.erase(elem)

我们可以看到,其它容器的 erase() 操作参数都是位置。而set 除了其它几个erase(),还有这个传入值的 erase() 函数操作。这个操作在 list 里应该对应的是,c.remove()。但是这里确没有一至,可能是历史原因吧,我也不知道,但是这个要注意。反正我们记住,在 set 里有一个 erase(elem),在 list 里有一个 remove() 
操作就行了。

如果 multisets 内含有重复元素,你不能使用 erase(),来删除这些重复元素中的第一个,你可以这么做:

std::multiset<Elem> coll;
...

//remove first element with passed value
std::multiset<Elem>::iterator pos;
pos = coll.find (elem);
if (pos != coll.end()) 
{
    coll.erase(pos);
}

五. 示例代码

#include <iostream>
#include <set>
using namespace std;

int main()
{
	
/*type of the collection:
*-no duplicates
*-elements are integral values
*-descending order
*/
	typedef set<int,greater<int> > IntSet;
	
	IntSet coll1;         // empty set container
	
	//insert elements in random order
	coll1.insert(4);
	coll1.insert(3);
	coll1.insert(5);
	coll1.insert(1);
	coll1.insert(6);
	coll1.insert(2);
	coll1.insert(5);
	
	//iterate over all elements and print them
	IntSet::iterator pos;
	for (pos = coll1.begin(); pos != coll1.end(); ++pos) {
		cout << *pos << ' ';
	}
	cout << endl;
	
	//再次插入 4
	pair<IntSet::iterator, bool> status = coll1.insert(4);
	if (status.second) {
		cout << "4 inserted as element "
			<< distance (coll1.begin(),status. first) + 1
			<< endl;
	}
	else {
		cout << "4 already exists" << endl;
	}
	
	//assign elements to another set with ascending order
	set<int> coll2(coll1.begin(),
		coll1.end());
	
	//print all elements of the copy
	copy (coll2.begin(), coll2.end(),
		ostream_iterator<int>(cout," "));
	cout << endl;
	
	//remove all elements up to element with value 3
	coll2.erase (coll2.begin(), coll2.find(3));
	
	//remove all elements with value 5
	int num;
	num = coll2.erase (5);
	cout << num << " element(s) removed" << endl;
	
	//print all elements
	copy (coll2.begin(), coll2.end(),
		ostream_iterator<int>(cout," "));
	cout << endl;

	return 0;
}

抱歉!评论已关闭.