STL学习心得

STL概述

STL组件

1.容器(Container) - 管理某类对象的集合
2.迭代器(Iterator) - 在对象集合上进行遍历
(注意:这些集合可能是容器,也可能是容器的子集。)
3.算法(Algorithm) - 处理集合内的元素,算法作用于容器。(算法提供了执行各种操作的方式,包括对容器内容执行初始化、排序、搜索和转换等操作。)
4.容器适配器(container adaptor)
5.函数对象(functor)
在这里插入图片描述
(注意:STL容器的共同能力:
1.所有容器中存放的都是值而非引用。如果希望存放的不是副本,容器元素只能是指针。
2.所有元素都形成一个次序(order),可以按相同的次序一次或多次遍历每个元素)

STL类别

1.序列式容器-排列次序取决于插入时机和位置
在这里插入图片描述
2.关联式容器-排列顺序取决于特定准则
在这里插入图片描述

STL容器元素的条件

1.必须能够通过拷贝构造函数进行复制
2.必须可以通过赋值运算符完成赋值操作
3.必须可以通过析构函数完称销毁动作
4.序列式容器元素的默认构造函数必须可用
5.某些动作必须定义 operator==,例如搜寻操作
6.关联式容器必须定义出排序准则,默认情况是重载operator <
(对于基本数据类型(int,long,char,double,…)而言,以上条件总是满足)

STL容器的共同操作

初始化

1.产生一个空容器
std::list l;
2.以另一个容器元素为初值完成初始化
std::list l;

std::vector c(l.begin(),l.end())
3.以数组元素为初值完成初始化
int array[]={2,4,6,1345};

std::set c(array,array+sizeof(array)/sizeof(array[0]));

与大小相关的操作

1.size()-返回当前容器的元素数量
2.empty()-判断容器是否为空
3.max_size()-返回容器能容纳的最大元素数量

比较

1.==,!=,<,<=,>,>=
2.比较操作两端的容器必须属于同一类型
3.如果两个容器内的所有元素按序相等,那么这两个容器相等
4.采用字典式顺序判断某个容器是否小于另一个容器

赋值和交换

swap用于提高赋值操作效率

与迭代器相关的操作

1.begin()-返回一个迭代器,指向第一个元素
2.end()-返回一个迭代器,指向最后一个元素之后
3.rbegin()-返回一个逆向迭代器,指向逆向遍历的第一个元素
4.rend()-返回一个逆向迭代器,指向逆向遍历的最后一个元素之后

元素操作

1.insert(pos,e)-将元素e的拷贝安插于迭代器pos所指的位置
2.erase(beg,end)-移除[beg,end]区间内的所有元素
3.clear()-移除所有元素

迭代器

1.可遍历STL容器内全部或部分元素的对象
2.指出容器中的一个特定位置
3.迭代器的基本操作
在这里插入图片描述
在这里插入图片描述

迭代器分类

1.双向迭代器
可以双向行进,以递增运算前进或以递减运算后退、可以用==和!=比较。
list、set和map提供双向迭代器

list<int> l; 
for(pos=l.begin();pos!=l.end();++pos{}

2.随机存取迭代器
除了具备双向迭代器的所有属性,还具备随机访问能力。
可以对迭代器增加或减少一个偏移量、处理迭代器之间的距离或者使用<和>之类的关系运算符比较两个迭代器。
vector、deque和string提供随机存取迭代器

vector<int> v; 
for(pos=v.begin();pos<v.end();++pos{}

vector

1.vector模拟动态数组
2.vector的元素可以是任意类型T,但必须具备赋值和拷贝能力(具有public拷贝构造函数和重载的赋值操作符)
3.必须包含的头文件#include
4.vector支持随机存取
5.vector的大小(size)和容量(capacity)
(1)size返回实际元素个数,
(2)capacity返回vector能容纳的元素最大数量。如果插入元素时,元素个数超过capacity,需要重新配置内部存储器。
在这里插入图片描述

非变动操作

在这里插入图片描述

赋值操作

在这里插入图片描述
(注意:所有的赋值操作都有可能调用元素类型的默认构造函数,拷贝构造函数,赋值操作符和析构函数)

元素存取

在这里插入图片描述

迭代器相关函数

在这里插入图片描述
(注意: 迭代器持续有效,除非发生以下两种情况:
(1)删除或插入元素
(2)容量变化而引起内存重新分配)

安插元素

在这里插入图片描述

移除元素

在这里插入图片描述

map/multimap

概述

1.使用平衡二叉树管理元素
2.元素包含两部分(key,value),key和value可以是任意类型
3.必须包含的头文件#include
4.根据元素的key自动对元素排序,因此根据元素的key进行定位很快,但根据元素的value定位很慢
5.不能直接改变元素的key,可以通过operator []直接存取元素值
6.map中不允许key相同的元素,multimap允许key相同的元素

构造、拷贝和析构

在这里插入图片描述
(注意:其中map可以是下列形式:
map<key,value> 一个以less(<)为排序准则的map,
map<key,value,op> 一个以op为排序准则的map)

非变动性操作

在这里插入图片描述

赋值

在这里插入图片描述

特殊搜寻操作

在这里插入图片描述

迭代器相关函数

在这里插入图片描述

安插元素

在这里插入图片描述

移除元素

在这里插入图片描述

set/multiset

概述

1.使用平衡二叉树管理元素
2.集合(Set)是一种包含已排序对象的关联容器。
3.必须包含的头文件#include
4.map容器是键-值对的集合,好比以人名为键的地址和电话号码。相反地,set容器5.只是单纯的键的集合。当我们想知道某位用户是否存在时,使用set容器是最合适的。
6.set中不允许key相同的元素,multiset允许key相同的元素

基本操作

在这里插入图片描述
在这里插入图片描述

算法

泛型算法通则

1.所有算法的前两个参数都是一对iterators:[first,last),用来指出容器内一个范围内的元素。
2.每个算法的声明中,都表现出它所需要的最低层次的iterator类型。

count

size_t count(InIt first, InIt last, const T& val);
计算[first,last) 中等于val的元素个数

count_if

size_t count_if(InIt first, InIt last, Pred pr);

计算[first,last) 中符合pr(e) == true 的元素 e的个数

min_element

template
FwdIt min_element(FwdIt first, FwdIt last);

返回[first,last) 中最小元素的迭代器,以 “< ”作比较器

max_element

template
FwdIt max_element(FwdIt first, FwdIt last);

返回[first,last) 中最大(不小)元素的迭代器,以 “< ”作比较器

for_each

Fun for_each(InIt first, InIt last, Fun f);

对[first,last)中的每个元素 e ,执行 f(e) , 要求 f(e)不能改变e

find

template<class InIt, class T>
InIt find(InIt first, InIt last, const T& val);

返回区间 [first,last) 中的迭代器 i ,使得 * i == val

find_if

template<class InIt, class Pred>
InIt find_if(InIt first, InIt last, Pred pr);
返回区间 [first,last) 中的迭代器 i, 使得 pr(*i) == true

binary_search

(折半查找,要求容器已经有序且支持随机访问迭代器,返回是否找到)
1.template<class FwdIt, class T>
bool binary_search(FwdIt first, FwdIt last, const T& val);
上面这个版本,比较两个元素x,y 大小时, 看 x < y

2.template<class FwdIt, class T, class Pred>
bool binary_search(FwdIt first, FwdIt last, const T& val, Pred pr);
上面这个版本,比较两个元素x,y 大小时, 看 pr(x,y)

lower_bound,uper_bound, equal_range

lower_bound:
template<class FwdIt, class T>
FwdIt lower_bound(FwdIt first, FwdIt last, const T& val);

要求[first,last)是有序的,
查找大于等于val的最小的位置
uper_bound
template<class FwdIt, class T>
FwdIt upper_bound(FwdIt first, FwdIt last, const T& val);
要求[first,last)是有序的,
查找大于val的最小位置
equal_range
template<class FwdIt, class T>
pair<FwdIt, FwdIt> equal_range(FwdIt first, FwdIt last, const T& val);

要求[first,last)是有序的,
返回值是一个pair, 假设为 p, 则
[first,p.first) 中的元素都比 val 小
[p.second,last)中的所有元素都比 val 大

sort 快速排序

template
void sort(RanIt first, RanIt last);
按升序排序。判断x是否应比y靠前,就看 x < y 是否为true

template<class RanIt, class Pred>
void sort(RanIt first, RanIt last, Pred pr);
按升序排序。判断x是否应比y靠前,就看 pr(x,y) 是否为true

unique(改变序列)

1.template
FwdIt unique(FwdIt first, FwdIt last);
用 == 比较是否相等
2.template<class FwdIt, class Pred>
FwdIt unique(FwdIt first, FwdIt last, Pred pr);
用 pr 比较是否等

去除[first,last) 这个升序序列中的重复元素
返回值是迭代器,指向元素删除后的区间的最后一个元素的后面

reverse

template
void reverse(BidIt first, BidIt last);

颠倒区间[first,last)顺序

注意的点

1.push_back( ) 成员函数在向量的末尾插入值,如果有必要会扩展向量的大小。
2.size( ) 函数显示向量的大小。
3.begin( ) 函数返回一个指向向量开头的迭代器。
4.end( ) 函数返回一个指向向量末尾的迭代器。
5. string 中的 find函数

 if(s1.find(s2)!=string::npos)  注意 其查找 是以s1的任何起点去找是否存在s2  如果是查找前缀字符串(一个字符串是另一个字符串的前缀)  如果这样找就可能超时

6.有时候出现弹窗 cannot read vs2005 是有提示的 而vc6是不提示的 原因之一可能是由于使用了没有赋值的变量导致指针乱飘了

一些实际应用

单个元素的查找

find() 比较条件为相等的查找

find()从给定区间中查找单个元素,定义:


int myints[] = { 10, 20, 30, 40 };
std::vector<int> myvector (myints,myints+4);
it = find (myvector.begin(), myvector.end(), 30);
if (it != myvector.end())
    std::cout << "Element found in myvector: " << *it << '\n';
else
    std::cout << "Element not found in myvector\n"
find_if() 自定义比较函数

std::find_if():从给定区间中找出满足比较函数的第一个元素;
示例,从myvector中查找能够被30整除的第一个元素:

bool cmpFunction (int i) {
  return ((i%30)==0);
}
it = std::find_if (myvector.begin(), myvector.end(), cmpFunction);
std::cout << "first:" <<  *it <<std::endl;
利用find_if()函数结合map实现模糊查找

(注意:重载运算符是重点!!!)
首先对find_if函数的谓词函数进行改造:

template<class InIt, class Pred> 
InIt find_if(InIt first, InIt last, Pred pr); 

然后构造一个类,并重载函数运算符,在其内部实现取子串查找:

class map_value_finder
{
public:
	map_value_finder(const string& cmp_string) :m_s_cmp_string(cmp_string) {}
	bool operator ()(const multimap<string,int>::value_type& pair)
	{
		int loc;
		loc=pair.first.find(m_s_cmp_string);
		if (loc != pair.first.npos)
			return true;
		return false;
	}
private:
	const std::string& m_s_cmp_string;
};
void Operation::fuzzyFindBname(string str)
{
	multimap<string, int>::iterator it,p1,p2,p;
	p1 = bookname.begin();
	p2 = bookname.end();

	it = find_if(p1, bookname.end(), map_value_finder(str));
	if (it == bookname.end())
		return;
	else
		cout << book[it->second];
	it++;
	for (p = it; p != p2; p++)
	{
		it = find_if(p, bookname.end(), map_value_finder(str));
		if (it == bookname.end())
			return;
		else
			cout << book[it->second];
	}
	
}

vector巧用swap收缩内存空间
#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<vector>
using namespace std;

int main(){

	vector<int> v;
	for (int i = 0; i < 100000;i ++){
		v.push_back(i);
	}

	cout << "capacity:" << v.capacity() << endl;
	cout << "size:" << v.size() << endl;

	//此时 通过resize改变容器大小
	v.resize(10);

	cout << "capacity:" << v.capacity() << endl;
	cout << "size:" << v.size() << endl;

	//容量没有改变
	vector<int>(v).swap(v);

	cout << "capacity:" << v.capacity() << endl;
	cout << "size:" << v.size() << endl;


	system("pause");
	return EXIT_SUCCESS;
}

set的返回值
//插入操作返回值
void test01(){

	set<int> s;
	pair<set<int>::iterator,bool> ret = s.insert(10);
	if (ret.second){
		cout << "插入成功:" << *ret.first << endl;
	}
	else{
		cout << "插入失败:" << *ret.first << endl;
	}
	
	ret = s.insert(10);
	if(ret.second){
		cout << "插入成功:" << *ret.first << endl;
	}
	else{
		cout << "插入失败:" << *ret.first << endl;
	}

}

struct MyCompare02{
	bool operator()(int v1,int v2){
		return v1 > v2;
	}
};
//从大到小排序
void test02(){

	srand((unsigned int)time(NULL));
	//我们发现set容器的第二个模板参数可以设置排序规则,默认规则是less<_Kty>
	set<int, MyCompare02> s;
	for (int i = 0; i < 10;i++){
		s.insert(rand() % 100);
	}
	
	for (set<int, MyCompare02>::iterator it = s.begin(); it != s.end(); it ++){
		cout << *it << " ";
	}
	cout << endl;
}

学习心得

这一段时间我们学习了STL,感受就是既简单又复杂,说简单是因为STL的一个重要特点是数据结构和算法的分离。尽管这是个简单的概念,但这种分离确实使得STL变得非常通用,方便了我们的使用,使一些复杂问题可以通关简单的手段就能实现。说复杂是因为较难理解,有些地方比较绕,较难理解。有的时候理解了,运用到实例中时,却常常感到无从下手。近几天的学习状态不是很好,每天都感觉自己很忙,但是晚上入睡前回想总是感觉自己这一天啥也没干,啥也不是,状态很是浮躁。最近一段时间的生物钟也挺乱的,每天都不能按时吃饭睡觉,导致每天精神欠佳,迷迷糊糊的,这个星期开始调整自己的作息,找回自己的状态。

  • 2
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值