set和Multiset会根据特定的排序规则自动将元素排序,multiset允许元素重复,set不允许元素重复,二者在std中定义如下:
namespace std
{
template <class T,
class Compare = less<T>,
class Allocator = allocator<T>>
class set ;
template <class T,
class Compare = less<T>,
class Allocator = allocator<T>>
class multiset ;
}
可有可无的排序准则,当我们没有传入排序准则时,就会采用less---这是一个访函数,以operator<对元素进行比较,一边完成排序
第三个参数定义了内存模型,默认是allocator
和所有标准关联式容器类似,set,multiset通常使用平衡二叉树实现
ps:1.事实上set和multiset通常使用红黑树(red-black tree)实作而成,红黑树在改变元素数量和元素搜索方面都很出色,他保证节点安插时最多只会作两个重新连接动作,而且到达某一元素的最长路径深度,最多只是最短路径深度的两倍。
2.标准的STL序列容器包括:vector、list、deque、heap(算法呈现)、stack(适配器)、queue(适配器)、priority_queue(适配器)。
标准的STL关联式容器包括:set、multiset、map、multimap。
SGI STL还提供了一些非标准的关联式容器,eg:hash_table、hash_set。
3.二叉搜索树是一种特殊的二叉树,其具有如下性质:
1) 若左子树不空,则左子树所有结点的值均小于它的根结点的值
2)若右子树不空,则右子树所有节点的值均大于它的根节点的值
3)左右子树也分别为二叉搜索树
二叉搜索树支持各种动态集合操作,包括:插入、查找、删除,其操作的时间复杂度与树的高度成正比,在遇到二叉树极端不平衡的情况下,其形状就与链表是一样的,二叉树插入、查找、删除的时间复杂度都退化为O(n)。
平衡二叉搜索树是一种特殊的二叉搜索树,其没有一个节点深度过大,不同的平衡条件,造就不同的效率表现。常见的平衡二叉搜索树有:AVL-tree和RB-tree。
关联容器一般以平衡二叉搜索树作为内部数据结构,RB-tree的应用尤其广泛。
RB-tree是许多平衡二叉查找树的一种,一颗有n个内结点的红黑树的高度至多为2lg(n+1),它能保证在最坏情况下,基本的动态集合操作时间为O(lgn)。
自动排序主要优点是使搜索元素时具有良好的性能,具有对数复杂度。但是自动排序造成的一个限制是:不能直接改变元素值,因为这样会改变原来的顺序,要想改变的话必须先删除原来的元素,再插入一个新的元素。
c.rbegin()----逆向迭代器,指向逆向遍历时的第一个元素
c.rend()----逆向迭代器,指向遍历时的最后元素的下一个位置
c.insert(elem)----插入elem的副本,返回位置
c.insert(pos,elem)---插入elem,返回位置信息,pos是个提示信息,如果恰当会加快速度
c.insert(beg,end)---将区间[beg,end)的元素插入进去
c.erase(elem)---删除值为elem的元素,返回被删除的个数
c.erase(pos)---移除迭代器pos上的元素
c.erase(beg,end)---移除区间[beg,end)内的所有元素,无返回值
c.clear()---移除所有元素,将容器清空
- set提供如下接口
pair<iterator,bool> insert(const value_type& elem) ;
iterator insert(iterator pos_hint, const value_type& elem) ;
- multiset提供如下接口
iterator insert(const value_type& elem) ;
iterator insert(iterator pos_hint, const value_type& elem) ;
#include <iostream>
#include <set>
#include <iterator>
using namespace std;
int main()
{
typedef set<int, greater<int>> IntSet ;//设置排序规则从大到小
IntSet coll1 ;
coll1.insert(4) ;
coll1.insert(3) ;
coll1.insert(5) ;
coll1.insert(1) ;
coll1.insert(6) ;
coll1.insert(2) ;
coll1.insert(5) ;
IntSet::iterator pos ;
for (pos = coll1.begin(); pos != coll1.end(); ++pos)
{
cout << *pos ;
}
cout << endl ;
pair<IntSet::iterator, bool> status = coll1.insert(4) ;
if (status.second)
{
cout << "4 inserted as element"
<< distance(coll1.begin(), status.first) + 1
<<endl ;
}
else//set不允许重复
{
cout << "4 already exits" << endl ;
}
set<int> coll2(coll1.begin(), coll1.end()) ;//coll2使用默认排序规则,从小到大
copy(coll2.begin(), coll2.end(), ostream_iterator<int>(cout, " ")) ;
cout << endl ;
coll2.erase(coll2.begin(), coll2.find(3)) ;//find会返回迭代器的位置
int num = coll2.erase(5) ;
cout << num << "element removed" << endl ;
copy(coll2.begin(), coll2.end(), ostream_iterator<int>(cout, " ")) ;
cout << endl ;
system("pause") ;
}