set集合容器使用一种称为红黑树(Red-Black Tree) 的平衡二叉检索树的数据结构,来组织泛化的元素数据。每个节点包含一个取值红色或黑色的颜色域,以利于进行树的平衡处理。作为节点键值的元素的插入,必须确保每个子树根节点的键值大于左子树所有节点的键值,而小于右子树所有节点的键值。不会将重复的键值插入容器,也不需要指定具体的插入位置,而按元素在树中的关联关系,进行位置检索和插入,元素的删除亦然。
    元素数据的检索,使用的是二叉检索树的中序遍历算法,检索的效率高于vector dequelist等容器。由于采用中序遍历算法可将二叉检索树的键值,由小到大排列遍历出来,因此 set 集合容器蕴含了元素间的有序性。
    作为一种关联容器,set 集合容器实现了 Unique Sorted Associative Container 和 Simple Associative Container 概念的函数定义要求。以熟悉的函数形式提供了元素插入、删除和检索的功能,封装了二叉树的复杂操作。

头文件
include <set>

创建 set 对象

为了管理 set 的二叉树的链表数据,先要利用 set 容器的构造函数,创建一个 set 对象。
1.  set(); 用默认的 less<T> 函数对象和内存分配器,创建一个没有任何数据元素的 set 对象。
set<int> s; //创建了一个空的 set 对象 s ,元素类型为 int
2.  set(const key_compare& comp); 指定一个比较函数对象 comp 来创建 set 对象,内存分配器为默认值。

下面的的代码使用自定义的函数对象 strLess ,创建一个 set 容器对象 s 。
    // 定义字符串比较函数对象 strLess
    struct  strLess
    {
        bool  operator()(const char* s1,const char* s2)  const
        {
            return strcmp(s1, s2) < 0;
        }
    };
    // 创建 set 容器对象 s    
    set<const char*, strLess>  s(strLess());  //可以自己写一个结构体,在创建的时候传入这个结构体,让set 容器元素的排序,按照我们定义的方式来进行。
3.  set(const set&);  set 拷贝构造函数,通过红黑树的拷贝构造函数,实现两个 set 容器的元素、头节点和节点个数的拷贝。
下面的代码,利用 set 容器对象 s1 ,拷贝生成 set 容器对象 s2。
    // set<int>  s1;
    set<int>  s2(s1);
4.  set(InputIterator first, InputIteratorlast);  用迭代器区间 [first, last) 所指的元素,创建一个 set 对象。

例如,下面代码将数组 iArray 的元素插入到 set 容器对象 s 的红黑树中。

int iArray[] = {13, 32, 19};
set<int>  s(iArray, iArray + 3);
5.  set(InputIteratorfirst, InputIterator last, const key_compare& comp);// 用迭代器区间 [first, last) 所指的元素和 comp 函数对象,创建一个 set 对象。
例如,下面的代码利用上面定义的 strLess 函数对象和数组 szArray ,创建 set 对象 s。

const  char*  szArray = {"Hello", "dog", "bird"};
set<const char*, strLess >   s(szArray, szArray + 3, strLess());

元素的插入

set 并没有固定的所谓尾部插入 push_back 函数,元素的插入一般使用 insert 进行动态检索插入。
1.    pair<iterator,bool>  insert(const value_type& v)
    
将元素 v 插入 set 容器,要求 v 值不与 set 容器的任何元素重复,否则插入失败。返回一个 pair 配对对象,提供所插入元素的迭代器位置和 true/false 插入成功标志
2.    iterator insert(iteraotr position, const value_type&v)
    
将元素 v 插入 set 容器,参数 position 只是提示可在 position 位置之前插入 v ,所返回的插入位置视实际情况而定,不一定能在 position 位置前插入。
3.    void insert(InputIterator first, InputIterator last)
    
将某迭代器区间 [first, last) 所指的数据作为元素,插入到 set 容器。
    如果希望提供一个是否插入成功的信息,可以使用返回 pair 对象的 insert 函数进行插入,如下面的代码所示。

    set<int>  sInt;
    sInt.insert(10);
    pair<set<int>::iterator, bool>  p = sInt.insert(19);
    if(p.second)
        cout<<"插入新元素"<<*(p.first) << endl;
    else
        cout<<"已存在该元素,不重复插入"<<endl;

元素的删除

与插入一样,set 容器也具有高效的红黑树元素的删除处理,并自动重新调整内部的红黑树平衡。
1. void erase(iterator position); 删除 position 所指的元素
2. size_type erase(const key_type& k);  
删除等于键值 k 的那个元素,对于 set 容器来说,此函数总是返回值 1 ,因为 set 容器不会出现重复的元素值(键值)
3. void erase(iterator first, iterator last);
删除 set 迭代器区间 [first,last) 上的所有元素
4. void clear();
删除所有元素,但不会删除内部红黑树的头节点

元素的搜索

set容器提供了一个应用红黑树进行搜索的函数 find ,返回的迭代器值位搜索到的元素位置,如果元素不存在,则返回一个 end结束元素的位置。

iterator find(constkey_type &k) const

#include <iostream>
#include <set>
int main ()
{
	std::set<int> myset;
	std::set<int>::iterator it;
	//存入一些初始化值:
	for (int i=1; i<=5; i++) myset.insert(i*10);    // 10 20 30 40 50

	it=myset.find(20);//找到
	myset.erase (it);//删除
	myset.erase (myset.find(40));//如果找到,则删除
	std::cout << "myset contains:";
	for (it=myset.begin(); it!=myset.end(); ++it)
		std::cout << ' ' << *it;
	std::cout << '\n';
	return 0;
}


其他函数

set提供的函数还有empty、size、swap、lower_bound、upper_bound和equal_range等

lower_bound(); 下确界函数,返回第一个 > elem 元素的迭代器

upper_bound(); 上确界函数,返回第一个 > elem 元素的迭代器

equal_range();  返回容器中与elem相等的上下限的两个迭代器。上限是闭区间,下限是开区间,如[beg,end)。以上函数返回两个迭代器,而这两个迭代器被封装在pair中。

#include <iostream>
#include <set>
int main ()
{
	std::set<int> myset;
	for (int i=1; i<=5; i++) 
		myset.insert(i*10);   // myset: 10 20 30 40 50
	std::pair<std::set<int>::const_iterator,std::set<int>::const_iterator> ret;
	ret = myset.equal_range(30);
	std::cout << "the lower bound points to: " << *ret.first << '\n';
	std::cout << "the upper bound points to: " << *ret.second << '\n';
	return 0;
}



转载请注明出处: http://blog.csdn.net/lsh_2013/article/details/46745121,谢谢合作!




Logo

权威|前沿|技术|干货|国内首个API全生命周期开发者社区

更多推荐