09 std::set std::mutilset

set和mutilset会根据特定的排序准则,自动将元素排序。两者不同之处在于mutilset允许元素重复而set不允许。属于关联式容器。
#include <set>
只要是可以根据某种排序准则作比较的任意类型T都可以成为set或mutilset的元素。
所谓的排序准则,意义如下:
(1) 必须是非对称的
对operator< 而言, 如果 x<y 为true, 则 y<x 为false
对判断式 op()而言, 如果 op(x, y) 为true, 则 op(y, x) 为false
(2) 必须是可传递的
对 operator 而言, 如果 x<y 为true, 且 y<z 为true, 则 x<z 为true
对 op() 而言, 如果 op(x, y) 为true且op(y, z)为true, 则 op(x, z)为true
(3) 必须是非自反的
对 operator< 而言, x<x 永远为false
对 op() 而言, op(x, x) 永远为false
(4) 必须有等效传递性:如果 a=b, b=c 成立, 则 a=c 必然成立
这意味着必须区分less和equal, 像 operator <= 这样的准则不符合条件。
根据这些性质,排序准则也被用来检查等效性。也就是说,两个元素,如果没有任何一个小于另一个,则视为重复。
mutilset等效元素的次序是随机但稳定的。

特性

set和mutilset通常以平衡二叉树实现。
自动排序的优点在于令二叉树查找元素时拥有良好的效能,查找函数具有对数复杂度。
自动排序的限制是,不能直接改变元素值,因为这样会打乱原本的顺序。
要改变元素,必须先删除旧元素,再插入新元素
-> set和mutilset不提供任何操作函数可以直接访问元素
-> 通过迭代器进行元素见访问,从迭代器的角度看,元素值是常量

部分操作

c.key_comp()

返回比较准则

c.value_comp()

返回针对value的比较准则

c.empty()

是否为空

c.size()

当前元素个数

c.max_size()

 

c1 == c2

 

c1 != c2

 

c1 < c2

 

c1 > c2

 

c1 <= c2

 

c1 >= c2

 
  

c.count(val)

返回元素值为value的元素个数

c.find(val)

返回元素值为value的第一个元素,如果找不到就返回end

c.lower_bound(val)

返回val的第一个可安插位置,也就是 元素值>=val 的第一个位置

c.upper_bound(val)

返回val的最后一个可安插位置,也就是 元素值>=val 的第一个位置

c.equal_range(val)

返回val可被安插的第一个位置和最后一个位置,也就是 元素值==val 的元素区间

  

c = c2

 

c = rv

 

c = initlist

 

c1.swap(c2)

 

swap(c1,c2)

 
  

c.begin()

 

c.end()

 

c.cbegin()

 

c.cend()

 

c.rbegin()

 

c.rend()

 

c.crbegin()

 

c.crend()

 
  

c.insert(val)

安插一个val拷贝,返回新元素位置, 不论是否成功

c.insert(pos,val)

安插一个val拷贝,返回新元素位置(pos是个提示,可加快速度)

c.insert(beg,end)

将区间[beg,end)内所有元素的拷贝安插到c,五返回值

c.insert(initlist)

 

c.emplace(args...)

 

c.emplace_hint(pos,args...)

 

c.erase(val)

移除与val之相等的所有元素,返回被移除元素的个数

c.erase(pos)

移除pos位置上的元素,无返回值

c.erase(beg,end)

移除区间内的所有元素,无返回值

c.clear()

清空

lower_bound(), upper_bound()和equal_range()的使用例子

#include <iostream>
#include <set>
using namespace std;
int main ()
{
	set<int> c;
	c.insert(1);
	c.insert(2);
	c.insert(4);
	c.insert(5);
	c.insert(6);
	cout << "lower_bound(3): " << *c.lower_bound(3) << endl;
	cout << "upper_bound(3): " << *c.upper_bound(3) << endl;
	cout << "equal_range(3): " << *c.equal_range(3).first << " " << *c.equal_range(3).second << endl;
	cout << endl;
	cout << "lower_bound(5): " << *c.lower_bound(5) << endl;
	cout << "upper_bound(5): " << *c.upper_bound(5) << endl;
	cout << "equal_range(5): " << *c.equal_range(5).first << " " << *c.equal_range(5).second << endl;
}
--------------------------------------
lower_bound(3): 4
upper_bound(3): 4
equal_range(3): 4 4
lower_bound(5): 5
upper_bound(5): 6
equal_range(5): 5 6

使用示例
 

#include <iostream>
#include <set>
#include <algorithm>
#include <iterator>
using namespace std;
int main()
{
	// type of the collection:
	// - no duplicates
	// - elements are integral values
	// - descending order
	set<int,greater<int>> coll1;
	// insert elements in random order using different member functions
	coll1.insert({4,3,5,1,6,2});
	coll1.insert(5);
	// print all elements
	for (int elem : coll1) {
		cout << elem << ’ ’;
	}
	cout << endl;
	// insert 4 again and process return value
	auto 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.cbegin(),coll1.cend());
	// print all elements of the copy using stream iterators
	copy (coll2.cbegin(), coll2.cend(),
	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.cbegin(), coll2.cend(),
	ostream_iterator<int>(cout," "));
	cout << endl;
}

运行期指定准则

无论是将排序准则作为第二个template实参传入,或是采用默认的排序准则 less<>, 通常都会将排序准则定义为类型的一部分。但有时候必须在运行期处理排序准则,或者有时候需要对同一种数据类型采用不同的排序准则,此时就需要一个用来表示准则的特殊类型,能够在运行期才给定某个准则,以下程序说明了这种做法:

#include <iostream>
#include <set>
#include "print.hpp"
using namespace std;
// type for runtime sorting criterion
class RuntimeCmp {
public:
	enum cmp_mode {normal, reverse};
	private:
	cmp_mode mode;
public:
	// constructor for sorting criterion
	// - default criterion uses value normal
	RuntimeCmp (cmp_mode m=normal) : mode(m) {
	}
	// comparison of elements
	// - member function for any element type
	template <typename T>
	bool operator() (const T& t1, const T& t2) const {
		return mode==normal ? t1<t2 : t2<t1;
	}
	// comparison of sorting criteria
	bool operator== (const RuntimeCmp& rc) const {
		return mode == rc.mode;
	}
};

// type of a set that uses this sorting criterion
typedef set<int,RuntimeCmp> IntSet;
int main()
{
	// create, fill, and print set with normal element order
	// - uses default sorting criterion
	IntSet coll1 = { 4, 7, 5, 1, 6, 2, 5 };
	PRINT_ELEMENTS (coll1, "coll1: ");
	// create sorting criterion with reverse element order
	RuntimeCmp reverse_order(RuntimeCmp::reverse);
	// create, fill, and print set with reverse element order
	IntSet coll2(reverse_order);
	coll2 = { 4, 7, 5, 1, 6, 2, 5 };
	PRINT_ELEMENTS (coll2, "coll2: ");
	// assign elements AND sorting criterion
	coll1 = coll2;
	coll1.insert(3);
	PRINT_ELEMENTS (coll1, "coll1: ");
	
	// just to make sure...
	if (coll1.value_comp() == coll2.value_comp()) {
		cout << "coll1 and coll2 have the same sorting criterion" << endl;
	}
	else {
		cout << "coll1 and coll2 have a different sorting criterion" << endl;
	}
}

在这个程序中,class RuntimeCmp提供了一种泛化能力:允许在运行期间对任何数据类型指定排序准则。其构造函数设定以升序进行排序,用的是默认值normal。他也允许传递RuntimeCmp::reverse作为构造函数实参,实现降序排序。

 

 

 

 

 

 

 

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值