C++ STL

1.STL概论

1.1STL六大组件

容器、算法、迭代器、仿函数、适配器、空间配置器

1.2STL优点

内建在C++编译器中,不需要安装额外内容
不需要了解具体实现内容,只要熟练运用即可
高复用,可移植,高性能

1.3容器划分

序列式容器
关联式容器 有个key起到索引作用

1.4算法

质变算法,改变元素的内容或者位置。
非质变算法,对原数组无变化。

2.容器

2.1vector

以数组为核心机制的动态集合对象,

创建一个vector容器

vector<int>v; //创建一个vector容器,容器中存放元素类型是int类型
vector(v.begin(), v.end());//将v[begin(), end())区间中的元素拷贝给本身。
vector(n, elem);//构造函数将n个elem拷贝给本身。
vector(const vector &vec);//拷贝构造函数。

插入和删除元素

insert(const_iterator pos, int count,ele);//迭代器指向位置pos插入count个元素ele.
push_back(ele); //尾部插入元素ele
pop_back();//删除最后一个元素
erase(const_iterator start, const_iterator end);//删除迭代器从start到end之间的元素
erase(const_iterator pos);//删除迭代器指向的元素
clear();//删除容器中所有元素

//插入元素
v.push_back(10);
v.push_back(30);
v.push_back(20);
v.push_back(40);

插入对象元素

//自定义数据类型
class Person
{
public:
	Person(string name, int age)
	{
		this->m_Name = name;
		this->m_Age = age;
	}
	string m_Name;
	int m_Age;
};

vector<Person> v;

Person p1("aaa", 10);
Person p2("bbb", 20);

//插入对象
v.push_back(p1);
v.push_back(p2);

遍历元素

//遍历元素
vector<int>::iterator  itBegin = v.begin(); //v.begin() 起始迭代器,指向容器中第一个数据

vector<int>::iterator  itEnd = v.end(); //v.end();结束迭代器,指向的是容器中最后一个元素的下一个位置
//遍历方式1
for (; begin != end; begin++)
{
     cout<<"item=" <<*begin <<endl;
}

void myprint(int va){
    cout<<va<<endl; 
}
//遍历方式2
for_each(v.begin(),v.end(),myprint);
    

vector常用赋值操作

assign(beg, end);//将[beg, end)区间中的数据拷贝赋值给本身。
assign(n, elem);//将n个elem拷贝赋值给本身。
vector& operator=(const vector  &vec);//重载等号操作符
swap(vec);// 将vec与本身的元素互换。


vector<int>v3;
v3.assign(v1.begin(), v1.end());

vector大小操作

size();//返回容器中元素的个数
empty();//判断容器是否为空
resize(int num);//重新指定容器的长度为num,若容器变长,则以默认值填充新位置。如果容器变短,则末尾超出容器长度的元素被删除。
resize(int num, elem);//重新指定容器的长度为num,若容器变长,则以elem值填充新位置。如果容器变短,则末尾超出容器长>度的元素被删除。
capacity();//容器的容量
reserve(int len);//容器预留len个元素长度,预留位置不初始化,元素不可访问。
reverse  翻转

v1.front()
v1.back()

2.2 deque

以数组为核心机制的双组集合,数组前后都可以添加数据,当需要扩容时,在对象的末端添加固定长度的数组对象。

2.2.1 deque构造函数

deque<T> deqT;//默认构造形式
deque(beg, end);//构造函数将[beg, end)区间中的元素拷贝给本身。
deque(n, elem);//构造函数将n个elem拷贝给本身。
deque(const deque &deq);//拷贝构造函数。

2.2.2deque赋值操作

assign(beg, end);//将[beg, end)区间中的数据拷贝赋值给本身。
assign(n, elem);//将n个elem拷贝赋值给本身。
deque& operator=(const deque &deq); //重载等号操作符
swap(deq);// 将deq与本身的元素互换

2.2.3deque大小操作

deque.size();//返回容器中元素的个数
deque.empty();//判断容器是否为空
deque.resize(num);//重新指定容器的长度为num,若容器变长,则以默认值填充新位置。如果容器变短,则末尾超出容器长度的元素被删除。
deque.resize(num, elem); //重新指定容器的长度为num,若容器变长,
则以elem值填充新位置,如果容器变短,则末尾超出容器长度的元素被删除。

2.2.4 deque双端插入和删除操作

push_back(elem);//在容器尾部添加一个数据
push_front(elem);//在容器头部插入一个数据
pop_back();//删除容器最后一个数据
pop_front();//删除容器第一个数据

2.2.5 deque数据存取

at(idx);//返回索引idx所指的数据,如果idx越界,抛出out_of_range。
operator[];//返回索引idx所指的数据,如果idx越界,不抛出异常,直接出错。
front();//返回第一个数据。
back();//返回最后一个数据

2.2.6 deque插入操作

insert(pos,elem);//在pos位置插入一个elem元素的拷贝,返回新数据的位置。
insert(pos,n,elem);//在pos位置插入n个elem数据,无返回值。
insert(pos,beg,end);//在pos位置插入[beg,end)区间的数据,无返回值。

2.2.7 deque删除操作

clear();//移除容器的所有数据
erase(beg,end);//删除[beg,end)区间的数据,返回下一个数据的位置。
erase(pos);//删除pos位置的数据,返回下一个数据的位置。

sort(v.begin,v.end) 默认升序排序

3.stack

stack构造函数

stack<T> stkT;//stack采用模板类实现, stack对象的默认构造形式:
stack(const stack &stk);//拷贝构造函数

stack赋值操作

stack& operator=(const stack &stk);//重载等号操作符

stack数据存取操作

push(elem);//向栈顶添加元素
pop();//从栈顶移除第一个元素
top();//返回栈顶元素

3.4.3.4 stack大小操作

empty();//判断堆栈是否为空
size();//返回堆栈的大小

4.queue

构造函数

queue& operator=(const queue &que);//重载等号操作符

入队

Q.push(p1);
Q.empty()
Q.front()//队首
Q.back()//队尾
Q.size()

出队

Q.pop();

5.list

list构造函数

list<T> lstT;//list采用采用模板类实现,对象的默认构造形式:
list(beg,end);//构造函数将[beg, end)区间中的元素拷贝给本身。
list(n,elem);//构造函数将n个elem拷贝给本身。
list(const list &lst);//拷贝构造函数。

list数据元素插入

 
push_back(elem);//在容器尾部加入一个元素

push_front(elem);//在容器开头插入一个元素

insert(pos,elem);//在pos位置插elem元素的拷贝,返回新数据的位置。
insert(pos,n,elem);//在pos位置插入n个elem数据,无返回值。
insert(pos,beg,end);//在pos位置插入[beg,end)区间的数据,无返回值。

删除元素

clear();//移除容器的所有数据
erase(beg,end);//删除[beg,end)区间的数据,返回下一个数据的位置。
erase(pos);//删除pos位置的数据,返回下一个数据的位置。
remove(elem);//删除容器中所有与elem值匹配的元素。
pop_back();//删除容器中最后一个元素
pop_front();//从容器开头移除第一个元素

6.set

set构造函数

 
set<T> st;//set默认构造函数:
mulitset<T> mst; //multiset默认构造函数:
set(const set &st);//拷贝构造函数

set赋值操作


set& operator=(const set &st);//重载等号操作符
swap(st);//交换两个集合容器

set大小操作

size();//返回容器中元素的数目
empty();//判断容器是否为空

set插入和删除操作

insert(elem);//在容器中插入元素。
clear();//清除所有元素
erase(pos);//删除pos迭代器所指的元素,返回下一个元素的迭代器。
erase(beg, end);//删除区间[beg,end)的所有元素 ,返回下一个元素的迭代器。
erase(elem);//删除容器中值为elem的元素。

7.map

map构造函数

map<T1, T2> mapTT;//map默认构造函数:
map(const map &mp);//拷贝构造函数

map赋值操作

map& operator=(const map &mp);//重载等号操作符
swap(mp);//交换两个集合容器

map大小操作

size();//返回容器中元素的数目
empty();//判断容器是否为空

map插入数据元素操作

map.insert(...); //往容器插入元素,返回pair<iterator,bool>
map<int, string> mapStu;

// 第一种 通过pair的方式插入对象
mapStu.insert(pair<int, string>(3, "小张"));
// 第二种 通过pair的方式插入对象
mapStu.inset(make_pair(-1, "校长"));
// 第三种 通过value_type的方式插入对象
mapStu.insert(map<int, string>::value_type(1, "小李"));
// 第四种 通过数组的方式插入值
mapStu[3] = "小刘";
mapStu[5] = "小王";

map查找操作

find(key);//查找键key是否存在,若存在,返回该键的元素的迭代器;/若不存在,返回map.end();
count(keyElem);//返回容器中key为keyElem的对组个数。对map来说,要么是0,要么是1。对multimap来说,值可能大于1。
lower_bound(keyElem);//返回第一个key>=keyElem元素的迭代器。
upper_bound(keyElem);//返回第一个key>keyElem元素的迭代器。
equal_range(keyElem);//返回容器中key与keyElem相等的上下限的两个迭代器。

multimap

3.string 对象

构造函数

string();//创建一个空的字符串 例如: string str;
string(const string& str);//使用一个string对象初始化另一个string对象
string(const char* s);//使用字符串s初始化
string(int n, char c);//使用n个字符c初始化

string str;
string str2(str);

string str3("abc");

string str4(10, 'a');

string基本赋值操作

string& operator=(const char* s);//char*类型字符串 赋值给当前的字符串
string& operator=(const string &s);//把字符串s赋给当前的字符串
string& operator=(char c);//字符赋值给当前的字符串
string& assign(const char *s);//把字符串s赋给当前的字符串
string& assign(const char *s, int n);//把字符串s的前n个字符赋给当前的字符串
string& assign(const string &s);//把字符串s赋给当前字符串
string& assign(int n, char c);//用n个字符c赋给当前字符串
string& assign(const string &s, int start, int n);//将s从start开始n个字符赋值给字符串

string存取字符操作

char& operator[](int n);//通过[]方式取字符
char& at(int n);//通过at方法获取字符

string str = "hello world";
//[]和at区别,[]访问越界 直接挂掉 , at访问越界  抛出out_of_range异常
for (int i = 0; i < str.size();i++)
{
	//cout << str[i] << endl;
	cout << str.at(i) << endl;
}

string拼接操作

string& operator+=(const string& str);//重载+=操作符
string& operator+=(const char* str);//重载+=操作符
string& operator+=(const char c);//重载+=操作符
string& append(const char *s);//把字符串s连接到当前字符串结尾
string& append(const char *s, int n);//把字符串s的前n个字符连接到当前字符串结尾
string& append(const string &s);//同operator+=()
string& append(const string &s, int pos, int n);//把字符串s中从pos开始的n个字符连接到当前字符串结尾
string& append(int n, char c);//在当前字符串结尾添加n个字符c

string查找和替换

int find(const string& str, int pos = 0) const; //查找str第一次出现位置,从pos开始查找
int find(const char* s, int pos = 0) const;  //查找s第一次出现位置,从pos开始查找
int find(const char* s, int pos, int n) const;  //从pos位置查找s的前n个字符第一次位置
int find(const char c, int pos = 0) const;  //查找字符c第一次出现位置
int rfind(const string& str, int pos = npos) const;//查找str最后一次位置,从pos开始查找
int rfind(const char* s, int pos = npos) const;//查找s最后一次出现位置,从pos开始查找
int rfind(const char* s, int pos, int n) const;//从pos查找s的前n个字符最后一次位置
int rfind(const char c, int pos = 0) const; //查找字符c最后一次出现位置
string& replace(int pos, int n, const string& str); //替换从pos开始n个字符为字符串str
string& replace(int pos, int n, const char* s); //替换从pos开始的n个字符为字符串s

string比较操作

//compare函数在>时返回 1,<时返回 -1,==时返回 0。比较区分大小写,比较时参考字典顺序,排越前面的越小。大写的A比小写的a小。
int compare(const string &s) const;//与字符串s比较
int compare(const char *s) const;//与字符串s比较

string子串

string substr(int pos = 0, int n = npos) const;//返回由pos开始的n个字符组成的字符串

string插入和删除操作

string& insert(int pos, const char* s); //插入字符串
string& insert(int pos, const string& str); //插入字符串
string& insert(int pos, int n, char c);//在指定位置插入n个字符c
string& erase(int pos, int n = npos);//删除从Pos开始的n个字符

string和c-style字符串转换

const char * str = "abcd";

//const char * 转为 string
string s(str);

//string 转为 const char *
const char * str2 = s.c_str();

//const char * 可以隐式类型转换为  string
doWork(str2);
//string 不可以隐式类型转换为  const char* 
//doWork2(s);

小写、大写字母转换

string str = "abcdEFg";

for (int i = 0; i < str.size();i++)
{
	//str[i] = toupper(str[i]);
	str[i] = tolower(str[i]);
}
cout << str << endl;

函数对象-仿函数

重载函数调用操作符的类,其对象常称为函数对象(function object)。重载了‘()’操作符的对象,叫函数对象,也叫函数符,
操作符重载的时候,要求一个参数,又叫一元仿函数
要两个参数,就要二元仿函数。

1、函数对象通常不定义构造函数和析构函数,所以在构造和析构时不会发生任何问题,避免了函数调用的运行时问题。

2、函数对象超出普通函数的概念,函数对象可以有自己的状态

3、函数对象可内联编译,性能好。

4、模版函数对象使函数对象具有通用性

class myprint{

   public:
        void operator()(string name){
            cout<< name<<endl;
        }
};

 myprint my;
 myprint my("world");

谓词
生成器是不用参数就可以调用的函数符。
一元函数是用一个参数可以调用的函数符。
二元函数是用两个参数可以调用的函数符。
返回bool值得一元函数是谓词
返回bool值得二元函数是二元谓词

内建函数对象

STL提供的一些函数对象,分为算数类、关系类、逻辑运算类。使用内建函数对象,引入头文件#include <functional>

  • 算数类
    negate是一元运算,其他都是二元运算。所谓二元运算,就是需要2个参数。
template<class T> T plus<T>//加法仿函数

template<class T> T minus//减法仿函数

template<class T> T multiplies//乘法仿函数

template<class T> T divides//除法仿函数

template<class T> T modulus//取模仿函数

template<class T> T negate//取反仿函数

eg:加法仿函数

void test02()
{
	plus<int> p;

	cout << p(10, 10) << endl;

}
  • 关系类
    都是二元运算。
template<class T> bool equal_to//等于

template<class T> bool not_equal_to//不等于

template<class T> bool greater//大于

template<class T> bool greater_equal//大于等于

template<class T> bool less//小于

template<class T> bool less_equal//小于等于
  • 逻辑运算类
    not为一元运算,其余为二元运算。
template<class T> bool logical_and//逻辑与

template<class T> bool logical_or//逻辑或

template<class T> bool logical_not//逻辑非

lambda表达式

距离,简洁,效率,功能

bool f3(int x){ return x%3==0;}

等同于

[](int x){return x%3==0;}
  • [] 代替了函数名
  • 返回值,由decltyp自行推断,如没有返回值,为void
count3 = std::count_if(v.begin(),v.end(),[](int x){return x%3==0;})

使用整个lambda表达式替换函数指针或者函数符构造函数
注意:仅当lambda表达式由一条返回语句组成时,自动类型推断才有效。

适配器(包装器)

常用算法

算法

遍历算法

1.foreach遍历

class MyPrint
{
public:
	void operator()(int val)
	{
		cout << val << endl;
		m_Count++;
	}
	int m_Count = 0;
};

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

MyPrint print = for_each(v.begin(), v.end(), MyPrint());

cout << "print.count = " << print.m_Count << endl;

2.foreach 绑定参数输入

//for_each可以绑定参数输出
//int,int,void: 第一个参数,第二个参数,返回值
class MyPrint2 :public binary_function<int,int,void>
{
public:
	void operator()(int val , int start) const
	{
		cout << val << endl;
		
	}

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

MyPrint print = for_each(v.begin(), v.end(), MyPrint());

cout << "print.count = " << print.m_Count << endl;

3.transform算法 将指定容器区间元素搬运到另一容器中

//transform算法 将指定容器区间元素搬运到另一容器中
class MyTransform
{
public:
	int operator()(int val)
	{	
		return val + 10000;
	}
};
void test03()
{
	vector<int>v;
	for (int i = 0; i < 10; i++)
	{
		v.push_back(i);
	}



	vector<int>v2;
	v2.resize(v.size());

	transform(v.begin(), v.end(), v2.begin(), MyTransform());
	//lambda表达式
	for_each(v2.begin(), v2.end(), [](int val){cout << val << " "; });

}

查找算法

find算法 查找元素

/*find算法 查找元素
@param beg 容器开始迭代器
@param end 容器结束迭代器
@param value 查找的元素
@return 返回查找元素的位置
*/
vector<int>v;
	for (int i = 0; i < 10;i++)
	{
		v.push_back(i);
	}
	
	vector<int>::iterator pos = find(v.begin(), v.end(), 5);

	if (pos != v.end())
	{
		cout << "找到了元素:" << *pos << endl;
	}

find_if算法 条件查找


@param beg 容器开始迭代器
@param end 容器结束迭代器
@param  callback 回调函数或者谓词(返回bool类型的函数对象)
@return bool 查找返回true 否则false

Person * p = new Person("bbb", 20);

	vector<Person *>::iterator pos = find_if(v.begin(), v.end(), bind2nd( MyComparePerson() ,p)  );

	if (pos != v.end())
	{
		cout << "找到了元素--- 姓名: " << (*pos)->m_Name << " 年龄: " << (*pos)->m_Age << endl;
	}
	else
	{
		cout << "未找到" << endl;
	}

adjacent_find算法 查找相邻重复元素

vector<int>v;

	v.push_back(3);
	v.push_back(2);
	v.push_back(300);
	v.push_back(300);
	v.push_back(6);
	v.push_back(3);

	vector<int>::iterator ret = adjacent_find(v.begin(), v.end());

binary_search算法 二分查找法
注意:容器一定要有序

vector<int>v;
	for (int i = 0; i < 10; i++)
	{
		v.push_back(i);
	}
	//v.push_back(4);  必须是有序序列,如果无效 结果未知

   bool ret=binary_search(v.begin(), v.end(), 2);

count算法 统计元素出现次数

@param beg 容器开始迭代器
@param end 容器结束迭代器
@param  value回调函数或者谓词(返回bool类型的函数对象)
@return int返回元素个数

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

v.push_back(3);
v.push_back(3);
v.push_back(3);

int num = count(v.begin(), v.end(), 3);

排序算法

merge算法 容器元素合并,并存储到另一容器中
注意 : 两个容器必须是有序的,顺序要一致

	vector<int>vTarget; //目标容器
	vTarget.resize(v1.size() + v2.size());

	merge(v1.begin(), v1.end(), v2.begin(), v2.end(), vTarget.begin());

	for_each(vTarget.begin(), vTarget.end(), [](int val){cout << val << " "; });

sort 排序

sort(v.begin(), v.end(), greater<int>());

random_shuffle算法 对指定范围内的元素随机调整次序

random_shuffle(v.begin(), v.end());
	for_each(v.begin(), v.end(), [](int val){cout << val << " "; });

reverse算法 反转指定范围的元素

reverse(v.begin(), v.end());

	cout << "反转后打印: " << endl;
	for_each(v.begin(), v.end(), [](int val){cout << val << " "; });

拷贝和替换算法

copy算法 将容器内指定范围的元素拷贝到另一容器中

vector<int>v2;
	v2.resize(v.size());
	copy(v.begin(), v.end(), v2.begin());

//replace算法 将容器内指定范围的旧元素修改为新元素
//replace_if(iterator beg, iterator end, _callback, newvalue) 按条件替换

//将容器中的3替换为 3000
	replace(v.begin(), v.end(), 3, 3000);



class MyReplace
{
public:
	bool operator()(int val)
	{
		return val > 3;
	}
};
//将容器中所有大于3的都替换为 30000;
	replace_if(v.begin(), v.end(), MyReplace() , 30000);

swap交换

cout << "交换数据后:" << endl;
swap(v, v2);

//遍历打印
copy(v.begin(), v.end(), ostream_iterator<int>(cout, " "));
cout << endl;

常用算数算法

引入#include //accumulate算法头文件

accumulate算法


//accumulate算法 计算容器元素累计总和
void test01()
{
	vector<int>v;
	for (int i = 0; i <= 100;i++)
	{
		v.push_back(i);
	}

	int num = accumulate(v.begin(), v.end(),1000); // 参数3代表 累加起始值

	cout << "num = " << num << endl;
}

fill算法 向容器中添加元素

//fill算法 向容器中添加元素
 
fill(v.begin(), v.end(), 100);

for_each(v.begin(), v.end(), [](int val){cout << val << " "; });
cout << endl;


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值