c++标准模板库STL之基础

一、STL分类

容器类(container)

(1)顺序容器:

vector:内存成倍增长的动态数组

deque:动态开辟的二维数组

list:双向链表

(2)关联容器:

set:单重集合                 红黑树

mutiset:多重集合         红黑树

map:单重映射              红黑树

mutimap:多重映射       红黑树

(3)容器适配器:

stack

queue

prioriy_queue

迭代子(iterator):

正向迭代器:iterator / const_iterator

反向迭代器:reverse_iterator / const_reverse_iterator

插入行迭代器:back_insert_iterator / front_insert_iterator/insert_iterator

流式迭代器:istream_iterator / ostream_iterator

算法(algorithm)

泛型算法(generic algorithm)和函数对象(function object)的使用。

二、容器的实现

(1)vector

插入

a.用push_back(value)//在尾部快速插入元素

b.用insert(it,value);//在迭代器指向的位置进行插入元素

删除

a.用clear();//清除元素中的所有元素;

b.用erase(it_fist,it_second);//删除迭代器区间的元素;

c.用erase(it);//删除迭代器指向的元素;

修改

a.使用迭代器进行修改;

b.用下标进行修改,因为vector提供了[]运算符的重载;

查找

a.使用迭代器遍历整个容器查找;

b.使用find(it_fist,it_second,num);查找;找到返回当前元素的迭代器,未找到返回末尾位置迭代器;

c.使用find_if()进行查找;

代码练习:

int main()
{
	srand(time(0));
	vector<int> vec;
	/*
	  第一部分:增加元素:
	 */
	cout<<"--------------------------------------------"<<endl;

	vec.push_back(13);
	vec.push_back(44);
	vec.push_back(4);
	vec.push_back(8);

	sort(vec.begin(),vec.end());//默认升序排序

	vector<int>::iterator it1=vec.begin();
	for(;it1!=vec.end();++it1)
	{
		cout<<*it1<<" ";//打印出4 8 13 44
	}
	cout<<endl;

	vector<int>::iterator it2=vec.begin();
	vec.insert(it2,85);//插入完之后迭代器将失效;不能使用迭代器遍历打印
	copy(vec.begin(),vec.end(),ostream_iterator<int>(cout," "));//输出85 4 8 13 44
	cout<<endl;

	/*
	  第二部分:删除元素:
	*/
	cout<<"--------------------------------------------"<<endl;

	vector<int>::iterator it3=vec.begin();
	vec.erase(it3);//删除完之后将会使迭代器失效,不能使用迭代器遍历打印
	copy(vec.begin(),vec.end(),ostream_iterator<int>(cout," "));
	cout<<endl;
	
	//vec.clear();
	cout<<vec.size()<<endl;//容器内元素的个数
	cout<<vec.capacity()<<endl;//返回当前vector最大能够存储的元素个数

	/*
	  第三部分:修改:
	*/
	cout<<"--------------------------------------------"<<endl;

	vector<int>::iterator it4=vec.begin();
	*it4=55;//迭代器解引用修改
	vec[1]=100;//[]运算符重载函数修改
	copy(vec.begin(),vec.end(),ostream_iterator<int>(cout," "));
	cout<<endl;

	/*
	第四部分:查找元素:
	*/
	cout<<"--------------------------------------------"<<endl;

	vector<int>::iterator it5=find(vec.begin(),vec.end(),55);
	if(it5==vec.end())
	{
		cout<<"55 not find"<<endl;
		return -1;
	}
	cout<<"55  finded"<<endl;
	/*
	第五部分:练习:
	1、从大到小进行排序(前提)
	2、把74插到合适的位置。如果序列中有74,则不需要插入。
	3、找到74,如果有则删除
	*/
	cout<<"--------------------------------------------"<<endl;
	vec.clear();//清空
	for(int i=0;i<20;++i)
	{
		vec.push_back(rand()%100+1);
	}

	vector<int>::iterator it6=vec.begin();
	for(;it6!=vec.end();++it6)
	{
		cout<<*it6<<" ";
	}
	cout<<endl;

	sort(vec.begin(),vec.end(),greater<int>());//从大到小排序
	vector<int>::iterator it7=find_if(vec.begin(),vec.end(),bind1st(greater_equal<int>(),74));
	if(*it7!=74)//先找74
	{
		vec.insert(it7,74);
	}
	copy(vec.begin(),vec.end(),ostream_iterator<int>(cout," "));
	cout<<endl;

	vector<int>::iterator it8=find(vec.begin(),vec.end(),74);//找74
	/*if(*it8==74)//不可这样判断,因为当未找到时,在打印时出现迭代器失效
		vec.erase(it8);*/
	if(it8==vec.end())//find()找到返回当前元素的迭代器;未找到返回end()
	{
		cout<<"74 not find"<<endl;
		return -1;
	}
	cout<<"74 finded"<<endl;
	vec.erase(it8);
	copy(vec.begin(),vec.end(),ostream_iterator<int>(cout," "));
	cout<<endl;
	cout<<"--------------------------------------------"<<endl;

	return 0;
}


(2)deque

int main()
{
	deque<int> deq;
	cout<<deq.size()<<endl;
	//cout<<deq.capacity()<<endl;

	/*增加*/
	deq.insert(deq.begin(),10);//在迭代器位置插入
	deq.push_back(12);//后插
	deq.push_front(15);//前插

	copy(deq.begin(),deq.end(),ostream_iterator<int>(cout," "));
	cout<<endl;

	/*删除*/
	deq.erase(deq.begin());//把迭代器位置的元素删除
	copy(deq.begin(),deq.end(),ostream_iterator<int>(cout," "));
	cout<<endl;

	/*deq.clear();
	copy(deq.begin(),deq.end(),ostream_iterator<int>(cout," "));
	cout<<endl;*/

	/*修改*/
	deq[0]=88;
	copy(deq.begin(),deq.end(),ostream_iterator<int>(cout," "));
	cout<<endl;

	cout<<deq[1]<<endl;
	
	/*查找*/
	deque<int>::iterator it1=find(deq.begin(),deq.end(),88);
	if(it1==deq.end())
		cout<<"not find"<<endl;

	deque<int>::iterator it=find_if(deq.begin(),deq.end(),bind1st(greater_equal<int>(),74));
	if(*it!=74)
	{
		deq.insert(it,74);
	}
	copy(deq.begin(),deq.end(),ostream_iterator<int>(cout," "));
	cout<<endl;

	return 0;
}

(3)list

int main()
{
	list<int> t;

	/*增加*/
	t.insert(t.begin(),96);
	t.push_back(89);
	t.push_front(3);

	copy(t.begin(),t.end(),ostream_iterator<int>(cout," "));
	cout<<endl;

	/*删除*/
	/*t.erase(t.begin());
	t.clear();*/

	/*修改*/
	//t[0]=100;//不提供,因为list底层用链表实现,内存空间不连续;采取迭代器修改

	/*查找*/
	list<int>::iterator it1=find(t.begin(),t.end(),188);
	if(it1==t.end())
		cout<<"not find"<<endl;


	list<int>::iterator it=find_if(t.begin(),t.end(),bind1st(greater_equal<int>(),74));
	if(*it!=74)
	{
		t.insert(it,74);
	}
	copy(t.begin(),t.end(),ostream_iterator<int>(cout," "));
	cout<<endl;
	return 0;
}

(4)set   &   multiset

int main()
{
	set<int> myset1;//用一个类型实例化set时,一定要保证该类型提供小于运算符的重载函数,因为set底层用红黑树实现,红黑树本身就是一个排序树
	/*增加*/
	myset1.insert(15);
	myset1.insert(3);
	myset1.insert(1);
	myset1.insert(44);
	myset1.insert(78);

	copy(myset1.begin(),myset1.end(),ostream_iterator<int>(cout," "));
	cout<<endl;

	set<int,greater<int>> myset2;//按升序插入
	myset2.insert(89);
	myset2.insert(189);
	myset2.insert(82);
	myset2.insert(14);
	myset2.insert(14);
	copy(myset2.begin(),myset2.end(),ostream_iterator<int>(cout," "));
	cout<<endl;

	/*删除*/
	myset2.erase(myset2.begin());
	copy(myset2.begin(),myset2.end(),ostream_iterator<int>(cout," "));
	cout<<endl;

	multiset<int> myset3;//多重集合,允许键值重复
	myset3.insert(14);
	myset3.insert(15);
	myset3.insert(14);
	
	cout<<myset3.count(14)<<endl;//打印myset3中14出现的次数
	copy(myset3.begin(),myset3.end(),ostream_iterator<int>(cout," "));
	cout<<endl;

	/*查找*/
	multiset<int>::iterator it=myset3.find(14);//提供了自己的find()算法,效率高;不建议使用全局的find算法(O(n))
	if(it==myset3.end())
	{
		cout<<"14 not find"<<endl;
		return -1;
	}
	myset3.erase(it);
	copy(myset3.begin(),myset3.end(),ostream_iterator<int>(cout," "));
	return 0;
}

(5)map

int main()
{
	map<string,vector<int>> mymap;
	vector<int> vec1,vec2,vec3;
	/*增加*/
	//方法一:利用map中提供的[]运算符重载函数来进行插入
	mymap["LiuBei"]=vec1;
	mymap["ZhaoYun"]=vec2;
	mymap["ZhuGeLiang"]=vec3;
	
	//方法二:map中元素的类型是pair对象,把键值对打包起来用insert进行插入
	typedef map<string,vector<int>>::value_type _VT;
	mymap.insert(_VT("ZhangFei",vec1));
	
	//方法二:typedef重命名
	typedef pair<string,vector<int>> _PAIR;
	mymap.insert(_PAIR("CaoCao",vec1));

	map<string,vector<int>>::iterator it=mymap.find("LiuBei");
	if(it==mymap.end())
	{
		cout<<"not find"<<endl;
		return -1;
	}

	for(int i=0;i<20;i++)
	{
		it->second.push_back(rand()%100);
	}
	copy(it->second.begin(),it->second.end(),ostream_iterator<int>(cout," "));//打印
	cout<<endl;

	map<string,vector<int>>::iterator it1=mymap.begin();
	
	for(;it1!=mymap.end();++it1)
	{
		cout<<it1->first<<" ";
		copy(it->second.begin(),it->second.end(),ostream_iterator<int>(cout," "));
		cout<<endl;
	}

	return 0;
}


(6)容器适配器

容器适配器就是对已有容器的一个再封装。底层并没有自己独立的数据结构。

stack:栈;底层是deque.

queue:队列;底层是deque.

priority_queue:优先级队列;底层一vector为基础;插入的元素按优先级插,取元素的时候优先级最高的先取出。

三、算法

函数对象:每个对象都是一个类模板,以操作数类型为模板参数。包含头文件:#include<functional>

(1)函数对象的来源

1. 标准库预定义的一组算术,关系和逻辑函数对象;

1.1算术:

加法:plus<Type>
减法:minus<Type>//同加法
乘法:multiplies<Type>//不能用串,可用于复数和浮点数等
除法:divides<Type>//同乘法
求余:modulus<Type>//不能用于复数,浮点数,只能用于整数
取反:negate<Type>//同取余,但为单参数

1.2关系:返回值为布尔量,两个参数,第一参数和第二参数相比:

等于:equal_to<Type>
不等于:not_equal_to<Type>
大于:greater<Type>
大于等于:greater_equal<Type>
小于:less<Type>
小于等于:less_equal<Type>

1.3逻辑操作(逻辑函数对象,Type必须支持逻辑运算,有两个参数。)

逻辑与:logical_and<Type> //对应&&
逻辑或:logical_or<Type> //对应||
逻辑非:logical_not<Type> //对应!

2. 预定义的一组函数适配器,允许对预定义的函数对象进行特殊化或扩展;

2.1绑定器(binder);

把二元函数对象中的一个参数固定(绑定),使之转为一元函数;

C++标准库提供两种预定义的binder适配器:bind1st和bind2nd,分别绑定了第一或第二个参数。

2.2取反器(negator):

把函数对象的值翻转的适配器;如原来为小于,用了它后就变成了大于。
C++标准库也提供了两种negator适配器:not1和not2。not1用于一元预定义函数对象;not2用于二元预定义函数对象。 

3. 自定义函数对象。

泛型算法:

泛型算法函数名都加有后缀

_if 表示函数采用的操作是在元素上,而不是对元素的值本身进行操作。如find_if算法表示查找一些值满足函数指定条件的元素,而find查找特定的值。
_copy 表示算法不仅操作元素的值,而且还把修改的值复制到一个目标范围中。reverser算法颠倒范围中元素的排列顺序,而reverse_copy算法同时把结果复制到目标范围中。


联系:
函数对象主要是作为泛型算法的实参使用,通常用来改变缺省的操作

比如:sort(vec.begin(),vec.end(),greater<int>());这就是把整数的大于关系函数对象作为实参,得降序排列。
 


  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值