C++STL

STL是什么

C++标准:ANSI是ISO组织的美国分支机构。
所以,他们是一样的。
通常是 ANSI制定标准,然后ISO修改批准,ANSI再修改,所以最后他们就一样了,一般写作ANSI/ISO C++。
翻译过来就是标准C++。

STL是C++的ANSI/ISO标准的一部分,STL提供了大量的可服用软件组织,
STL(Standard Template Library),即标准模板库,是一个具有工业强度的,高效的C++程序库。它被容纳于C++标准程序库中,包括容器、算法、迭代器组件。

STL的组成:
三大核心:容器、算法、迭代器,还有容器适配器,函数对象。

容器:
容器是数据在内存中组织的方法,例如,数组、堆栈、队列、链表或二叉树(不过这些都不是STL标准容器)。STL中的容器是一种存储T(Template)类型值的有限集合的数据结构,容器的内部实现一般是类。这些值可以是对象本身,如果数据类型T代表的是Class的话。

算法:
算法是应用在容器上以各种方法处理其内容的行为或功能。例如,有对容器内容排序、复制、检索和合并的算法。在STL中,算法是由模板函数表现的。这些函数不是容器类的成员函数。相反,它们是独立的函数。令人吃惊的特点之一就是其算法如此通用。不仅可以将其用于 STL容器,而且可以用于普通的C++数组或任何其他应用程序指定的容器。

迭代器:
一旦选定一种容器类型和数据行为(算法),那么剩下唯一要他做的就是用迭代器使其相互作用。可以把达代器看作一个指向容器中元素的普通指针。可以如递增一个指针那样递增迭代器,使其依次指向容器中每一个后继的元素。迭代器是STL的一个关键部分,因为它将算法和容器连在一起。

这里介绍list,vector,deque等队列容器,和set和multisets,map和multimaps等关联容器,一共7种基本容器类。
队列容器(顺序容器):队列容器按照线性排列来存储T类型值的集合,队列的每个成员都有自己的特有的位置。顺序容器有向量类型、双端队列类型、列表类型三种。

三种基本容器的底层实现

1.vector
向量容器vector,是一个动态开辟的数组,每次以原来的2倍进行扩容,
vector vec;
增加元素:
vec.push_back(20); 末尾添加元素 时间复杂度O(1) 可以导致容器扩容
vec.insert(it, 20); it迭代器指向的位置添加一个元素20 时间复杂度O(n) 可以导致容器扩容

删除元素:
vec.pop_back(); 末尾删除元素 O(1)
vec.erase(it); 删除it迭代器指向的元素 O(n)
对容器进行连续插入或者删除操作(insert/erase),一定要更新迭代器,否则第一次insert或者erase完成,
迭代器就失效了,
更新迭代器:it=vec.erase(it)。

查询:
operator[] 下标的随机访问vec[5] O(1)
iterator迭代器进行遍历
还可以用算法查询:find,for_each
foreach => 通过iterator来实现的

常用方法介绍:
size():求元素个数
empty():判断容器是否为空
reserve(20):vector预留空间的 只给容器底层开辟指定大小的内存空间,并不会添加新的元素
resize(20):容器扩容用的 不仅给容器底层开辟指定大小的内存空间,还会添加新的元素(初始化为0)
swap : 两个容器进行元素交换

2.list
链表容器list,底层是一个双向循环链表(有前驱指针pre,有后继指针next,还有数据data)
list mylist;
增加元素:
mylist.push_back(20); 从末尾添加元素 O(1)
mylist.push_front(20); 从首部添加元素 O(1)
mylist.insert(it, 20); it指向的位置添加元素 O(1)
链表中进行insert的时候,先要进行一个query查询操作
对于链表来说,查询操作效率就比较慢了

删除:
mylist.pop_back(); 从末尾删除元素 O(1)
mylist.pop_front(); 从首部删除元素 O(1)
mylist.erase(it); 从it指向的位置删除元素 O(1)

查询搜索:
用迭代器iterator(连续的insert和erase一定要考虑迭代器失效的问题)

3.deque
双端队列容器deque,底层是动态开辟的二维数组,
一维数组从2开始,以2倍的方式进行扩容,每次扩容后,原来第二维的数组,从
新的第一维数组的下标oldsize/2开始存放,上下都预留相同的空行,方便支持deque的首尾元素添加

deque deq;
增加:
deq.push_back(20); 从末尾添加元素 O(1)
deq.push_front(20); 从首部添加元素 O(1)
deq.insert(it, 20); it指向的位置添加元素 O(n)

删除:
deq.pop_back(); 从末尾删除元素 O(1)
deq.pop_front(); 从首部删除元素 O(1)
deq.erase(it); 从it指向的位置删除元素 O(n)

查询搜索:
iterator(连续的insert和erase一定要考虑迭代器失效的问题)

常用的STL算法

1.for_each()

void print(int elem)
{
	cout << elem << " ";
}

//函数对象,使用起来像函数的都叫函数
class PrintInt
{
public:
	void operator()(int elem) const//这个成员函数必须叫operator
	{
		cout << elem << " ";
	}
};
//算法                             函数或函数对象
for_each(ivec.begin(), ivec.end(), print);//然后对ivec里面的值进行函数操作
cout << endl;//                    函数对象
for_each(ivec.begin(), ivec.end(), PrintInt());//然后对ivec里面的值进行函数操作

2.count和count_if

//返回值是bool的函数或函数对象称为谓词
bool isEven(int elem)//只有一个参数,叫一元谓词函数
{
	return elem % 2 == 0;
}
num = count(ivec.begin(), ivec.end(), 4);//用count计算4的个数
	cout << "有" << num << "个4" << endl;
num = count_if(ivec.begin(), ivec.end(), isEven);//用count计算偶数的个数
	cout << "有" << num << "个偶数" << endl;

//                         用bind2nd绑定两个数    modulus相当于取模运算
//                                               param1%param2 这里相当于要返回大于0的数                            
num = count_if(ivec.begin(), ivec.end(), bind2nd(modulus<int>(), 2));//用2绑定取模运算的第二个参数
cout << "有" << num << "个奇数" << endl;

//                                      函数适配器  函数对象
//                                               paraml>param2  这里将param2变成4,param1变成ivec里的数
//                                                                返回大于4的所有数的数量             
num = count_if(ivec.begin(), ivec.end(),bind2nd(greater<int>(),4));//函数对象得和适配器一起用
cout << "有" << num << "个数大于4" << endl;

multiset<int> mset;
	for (int i = 1; i <= 9; ++i)
		for (multiset<int>::iterator iter = mset.begin(); iter != mset.end(); ++iter)
			cout << *iter << " ";
	cout << endl;

	num = count(mset.begin(), mset.end(), 7);
	//速度慢,对所有容器通用,只能用线性的方式查找
	cout << "有" << num << "个7" << endl;

	num = mset.count(7);
	cout << "有" << num << "个7" << endl;
	//速度快 底层红黑树,用的二分查找

3.min_element()取最小值,max_element取最大值

bool absLess(int elem1, int elem2)//二元谓词,最小值
{
	return abs(elem1) <abs(elem2);//abs是绝对值
}

deque<int>::iterator result = min_element(ideq.begin(), ideq.end());
cout << "最小值:" <<*result<<endl;
cout << "最小值:" << *min_element(ideq.begin(), ideq.end())<<endl;
cout << "最大值:" << *max_element(ideq.begin(), ideq.end())<<endl;

cout << "绝对值最小值:" << *min_element(ideq.begin(), ideq.end(), absLess) << endl;
cout << "绝对值最大值:" << abs(*max_element(ideq.begin(), ideq.end(), absLess))<<endl;

4.查找算法search_n(),通用的,search()和find_end()是一对的

pos = search_n(ideq.begin(), ideq.end(), 4, 3);
//找4个3,返回的是第一个3的迭代器

pos = search_n(ideq.begin(), ideq.end(), 3, 6,greater<int>());//加谓词
// 找连续3个大于6的数
//search_n加谓词不需要加if,这和其他算法不一样

5.find_first_of()

//find_first_of,找到的一个就停下来
//这个函数查找在前一个区间出现的第一个后一个区间的数
//标准的算法没有find_last_of,要使用只能用逆向迭代器
//但在string函数里有find_last_of
//stl算法对所有容器都可用
pos=find_first_of(ivec.begin(), ivec.end(), searchList.begin(), searchList.end());

vector<int>::reverse_iterator rpos;//逆向迭代器
rpos = find_first_of(ivec.rbegin(), ivec.rend(), searchList.begin(), searchList.end());
//             逆向迭代器 end           begin

cout << "找到的位置:" << distance(ivec.begin(), rpos.base()) << endl;
	//                                              逆向迭代器转正向,不用加1,逆向迭代器特点
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值