C++STL学习(4)容器set和multiset

注:博客内容均来自于对《C++标准库》侯捷,华中科技大学出版社一书的笔记。转载请注明出处。

所有例程在Red Hat Linux 3.2.2-5版本上编译运行,g++的版本是 g++ (GCC) 3.2.2 20030222。


1、set和multiset

  set和multiset里面的元素都是“有序的”。因为set和multiset会根据特定的排序准则,自动将元素排序。不同的是set容器里面不允许有重复的元素,multiset容器允许存在重复的元素。
C++STL学习(4)容器set和multiset_第1张图片
   set和multiset通常都是以平衡二叉树来实现的。(这是根据他们各项操作的复杂度得出的结论,C++标准规格书中并没有说明这一点!)
   实际上,set和multiset通常以红黑树(red-black tree)实现的。红黑树在改变元素数量和元素搜索方面表现都很出色,它保证节点安插时最多只会作两个重新连接(relink)动作,而且到达某一元素的最长路径深度,最多只是最短路径的两倍。


自动排序的主要优点在于使二叉树查找元素时具有良好的性能。其查找算法具有对数复杂度!
但是,自动排序造成set和multiset的一个重要限制:不能直接改变元素值,因为这样会打乱原本的正确顺序,因此,要改变元素值,必须先删除旧元素,在插入新元素,因此:
1:set和multiset一样,不提供用来直接存取元素的任何操作函数;
2:通过迭代器进行元素的间接存取,有一个限制:元素值是常数



2、set和multiset的操作函数

2.1 创建、构造和析构

C++STL学习(4)容器set和multiset_第2张图片

排序准则可以这样定义:
1> 以template参数定义之。 
std::set > col1;

第二个参数排序准则的型别,实际的排序准则是容器所产生的仿函数。下面一个例子来说明这种方式。

example:

#include 
#include 
#include 
#include 
using namespace std;

class Person
{
public:
	Person(string a,string b) : 
	       strFirstname(a),strLastname(b)
	{}
public:
	string firstname() const
	{
		return strFirstname;
	}
	string lastname() const
	{
		return strLastname;
	}
private:
	const string strFirstname;
	const string strLastname;
};


//仿函数实现自定义排序
class PersonSortCriterion
{
public :
	bool operator()(const Person &p1, const Person &p2)
	{
		return (p1.lastname() < p2.lastname() ||
			(!(p2.lastname() < p1.lastname()) && 
			p1.firstname() < p2.firstname()));
	}
};


int main(int argc, char *argv[])
{
	typedef set PersonSet;
	PersonSet col1;
	//创建元素,并添加到容器
	Person p1("Jay","Chou");
	Person p2("Robin","Chou");
	Person p3("Robin","Lee");
	Person p4("Bob","Smith");
	col1.insert(p1);
	col1.insert(p2);
	col1.insert(p3);
	col1.insert(p4);
	PersonSet::iterator pos;
	//输出PersonSet中的所有元素
	for(pos = col1.begin(); pos != col1.end(); ++pos)
	{
		cout<firstname()<< " " << pos->lastname() << endl;
	}
	cout<

2> 以构造函数定义之。
这种情况下,同一个型别可以运行不同的排序准则,而排序的初始值或者状态也可以不同。

如果执行期间才获得排序准则,而且需要用到不同的排序准则,那么使用这种方式再好不过了!

example:

#include 
#include 
#include "print.h"
using namespace std;

template 
class RuntimeCmp
{
public:
	enum cmp_mode {normal, reverse};
private:
	cmp_mode mode;
public:
	RuntimeCmp(cmp_mode m = normal): mode(m)
	{
	}

	bool operator() (const T& t1, const T& t2) const
	{
		return mode == normal ? t1 > IntSet;

void fill(IntSet& set)
{
	set.insert(4);
	set.insert(7);
	set.insert(5);
	set.insert(1);
	set.insert(6);
	set.insert(2);
	set.insert(5);
}


int main(int argc, char *argv[])
{
	IntSet col1;
	fill(col1);
	PRINT_ELEMENTS(col1, "col1: ");

	RuntimeCmp reverse_order(RuntimeCmp::reverse);

	IntSet col2(reverse_order);
	fill(col2);
	PRINT_ELEMENTS(col2, "col2: ");

	col1= col2;
	col1.insert(3);
	PRINT_ELEMENTS(col1, "col1: ");

	if(col1.value_comp() == col2.value_comp())
	{
		cout<<"col1 == col2"<

C++STL学习(4)容器set和multiset_第3张图片

注:比较操作只能比较类型相同的容器。不同类型的容器比较会出错!!


C++STL学习(4)容器set和multiset_第4张图片



C++STL学习(4)容器set和multiset_第5张图片

C++STL学习(4)容器set和multiset_第6张图片

3、例子

#include 
#include 
#include 
#include 
using namespace std;

int main(int argc, char *argv[])
{
	typedef set > IntSet;
	
	IntSet col1;
	col1.insert(4);
	col1.insert(3);
	col1.insert(5);
	col1.insert(1);
	col1.insert(6);
	col1.insert(2);
	col1.insert(5);

	IntSet::iterator pos;
	for(pos = col1.begin(); pos != col1.end(); ++pos)
	{
		cout<< *pos << " ";
	}
	cout<< endl;
	
	pair status = col1.insert(4);
	if(status.second)
	{
		cout<< "4 inset as a element " 
			<< distance(col1.begin(), status.first) + 1
			<< endl;
	}
	else
		cout<< "4 already exists "< col2(col1.begin(),
		          col1.end());

	copy(col2.begin(),col2.end(),
		ostream_iterator(cout," "));
	cout<(cout," "));
	cout<
运行结果

C++STL学习(4)容器set和multiset_第7张图片





你可能感兴趣的:(【C++,STL】,C++,STL循序渐进)