set源码分析及实例

本文深入分析了C++标准模板库(STL)中set的数据结构和实现原理,重点介绍了set基于红黑树的自动排序特性和不允许重复键值的特点。此外,还提供了一个实际的set使用示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

/**
set的特性是:所有的元素都会根据元素的键值自动被排序。set的元素不像map那样可以
同时拥有实值(value)和键值(key)set元素的实值就是键值,键值就是实值
set不允许有两个相同的键值
不能通过set叠加器改变set的值
由于rb_tree是一种平衡二叉搜索树,自动排序的效果很不错,所以标准的STL set
即以rb_tree为底层机制
*/
//下面将展示set的源码

template<class Key,class Compare=less<key>,//缺省情况下采用递增排序
	class Alloc=alloc>
class set{
	public:
	//typedefs:
	typedef Key key_type;
	typedef Key Value_key;
	//注意:以下key_compare和value_compare使用同一个比较函数
	typedef Compare key_compare;
	typedef Compare value_compare;
	private:
		template <class T>
		struct identity:public unary_function<T,T>{
			const T& operator()(const T& x)const{return x;}
};
	typedef rb_tree<key_type,value_type,identity<value_type>,key_compare,Alloc>rep_type;
	rep_type t;//采用红黑树(RB_tree)来表现set
	public:
		typedef typename rep_type::const_pointer pointer;
		typedef typename rep_type::const_pointer const_pointer;
		typedef typename rep_type::const_reference reference;
		typedef typename rep_type::const_reference const_reference;
		typedef typename rep_type::const_iterator iterator;
		//注意上一行 iterator定义为RB_tree的const_iterator,这表示set的
		//迭代器无法执行写操作,这是因为set的元素有一定的次序安排
		//不允许用户在任意处进行写入操作
		typedef typename rep_type::const_iterator iterator;
		typedef typename rep_type::const_reverse_iterator reverse_iterator;
		typedef typename rep_type::const_reverse_iterator const_reverse_iterator;
		typedef typename rep_type::size_type size_type;
		typedef typename rep_type::difference_type difference_type;
		//allocation/deallocation
		//注意set一定使用RB_tree的insert_unique 而非insert_equal()
		//因为multiset才使用RB_tree的insert_equal
		//因为set不允许相同键值存在,multiset才允许相同键值的存在
		set():t(Compare()){}
		explicit set(const Compare&comp):t(comp){}
		template<class InputIterator>
		set(InputIterator first,InputIterator last)
		:t(compare()){t.insert_unique(first,last);}
		template <class InputIterator>
		set(InputIterator first,InputIterator last,const Compare&comp)
		:t(comp){t.insert_unqiue(first,last);}
		set(const set<Key,Compare,Alloc>&x):t(x.t){}
		set<Key,Compare,Alloc>&operator=(const set<Key,Compare,Alloc>&x){
			t=x.t;
			return *this;
	}

}
//以下所有的操作行为,RB_tree都已经提供,所以set只要传递调用即可
//accessors
key_compare key_comp()const{return t.key_comp();}
//以下注意,set的value_comp()事实上为RB_tree的key_comp
value_compare value_comp()const{return t.key_comp();}
iterator begin() const{return t.begin();}
iterator end()	const{return t.end();}
reverse_iterator rbegin()const{return t.rbegin();}
reverse_iterator rend()const{return t.end();}
bool empty()const{return t.empty();}
size_type size()const{return t.size();}
size_type max_size()const{return t.max_size();}
void swap(set<key,Compare,Alloc>&x){t.swap(x.t);}
//insert/erase
typedef pair<iterator ,bool>pair_iterator_bool;
pair<iterator,bool>insert(const value_type &x){
	pair<typename rep_type::iterator rep_iterator,bool>p=t.insert_unique(x);
	return pair<iterator,bool>(p.first,p.second);
}
iterator insert(iterator position,const value_type&x){
	typedef typename rep_type::iterator rep_iterator;
	return t.insert_unique((rep_iterator&)position,x);
}
template<class InputIterator>
void insert(InputIterator first,InputIterator last){
t.insert_unique(first,last);
}
void erase(iterator position){
	typedef typename rep_type::iterator rep_iterator;
	t.erase((rep_iterator&)position);
}
size_type erase(const key_type& x){
	return t.erase(x);
}
void erase(iterator first,iterator last){
	typedef typename rep_type::iterator rep_iterator;
	t.erase((rep_iterator&)first,(rep_iterator&)last);
}
void clear(){t.clear();}
//set operations
iterator find(const key_type&x)const{return t.find(x);}
size_type count(const key_type& x)const {return t.count(x);}
iterator lower_bound(cosnt key_type&x)const{
	return t.lower_bound(x);
}
iterator upper_bound(const key_type&x)const{
	return t.upper_bound(x);
}
pair<iterator,iterator>equal_range(const key_type&x)const{
	return t.equal_range(x);
}
//以下的__STL_NULL_TMPL_ARGS被定义为< >
friend bool operator==__STL_NULL_TMPL_ARGS(const set&,const set&);
	friend bool operator<__STL_NULL_TMPL_ARGS(const set&,const set&);
};
template <class Key,class Compare,class Alloc>
inline bool operator==(const set<Key,Compare,Alloc>&x,const set<Key,Compare,Alloc>&y){
	return x.t==y.t;
}
template <class Key,class Compare,class Alloc>
inline bool operator<const set<Key,Compare,Alloc>&x,const set<Key,Compare,Alloc>&y>{
	return x.t<y.t;
}


下面给出一个测试实例

#include<set>
#include<iostream>
using namespace std;
int main(){
int i;
int ia[5]={0,1,2,3,4};
set<int>iset(ia,ia+5);
cout<<"size="<<iset.size()<<endl;
cout<<"3count"<<iset.count(3)<<endl;
iset.insert(5);
cout<<"size="<<iset.size()<<endl;
cout<<"3 count="<<iset.count(3)<<endl;
iset.erase(1);
cout<<"size="<<iset.size()<<endl;
cout<<"3 count="<<iset.count(3)<<endl;
cout<<"1 count="<<iset.count(1)<<endl;
set<int>::iterator ite1=iset.begin();
set<int>::iterator ite2=iset.end();
for(;ite1!=ite2;++ite1)
	cout<<*ite1;
cout<<endl;
//STL算法find()来搜寻元素 可以有效的运作,散步时好办法
//if(ite1!=iset.end())
//	cout<<"3 found"<<endl;
//if(ite1==iset.end())
//	cout<<"1 not found"<<endl;
//面对关联是容器 应该使用其所提供的find()函数来搜寻元素,会比
//使用STL算法find()更有效率 ,因为STL算法find()只是循序搜寻
ite1=iset.find(3);
if(ite1!=iset.end())
	cout<<"3found"<<endl;
ite1=iset.find(1);
if(ite1==iset.end())
cout<<"1 not found"<<endl;
//企图通过迭代器来改变set元素,是不被允许的
//*ite1=9;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值