STL是C++为了提高代码的重复利用率而建立的一种数据结构和算法的统一标准。
一、什么是STL?
1.一般来说,STL可分为容器、迭代器、算法。
2.STL的代码基本上使用的都是C++独有的模板类型或者模板函数。
二、STL的组成:
STL的六大组件其中包括容器、算法、迭代器、仿函数、配置器、空间配置器(空间的分配和管理)。
1.容器:顾名思义是一个存放数据的容器。
通常的容器分为两种:序列式容器和关联式容器
序列式容器 着重的是值的排序,每个值都有一定的空间位置。
关联式容器 没有实际意义的顺序联系 例如二叉树等数据结构。
2.算法:计算问题的方法
算法也有两种:质变算法、非质变算法。
质变算法:在运算时会更改元素的内容,例如:拷贝、删除、替换等。
非质变算法:与质变相对,运算时没有改变元素的内容。
3.迭代器:连接容器和算法的超级接口
提供一个接口,可以通过这个接口访问容器里面的所有元素,同时不会暴露容器内部。每个容器都会有属于自己的迭代器。
单从功能来看迭代器和指针的差别并不大。通过迭代器来访问和修改容器。
三、容器
1.vector容器
vector容器类似于数组。
区别在于当存储数据过大时,vector会自动把原有数据拷贝到一个新空间,并释放原有空间,而数组则是固定空间。
vector//容器
vector<int> ve;//初始化
ve.begin();//容器首个数据
ve.end();//容器最后一个数据
ve.push_back(10);//尾部插入数据
ve.pop_back();//尾部删除
ve.insert(ve.begin(),20);//在头部插入20,参数1需要迭代器
ve.insert(ve.begin(),2,30);//在头部插入两个30
ve.erase(vi.begin());头部删除
ve.clear;//清空
ve.at(i);//访问第i个元素
ve[i];//使用[]访问
2.string容器
从本质上来说string是一个类,其中封装了char*类型。
string的相关操作:
string s1;//默认构造
string s2(str);//字符串初始化
string s3(s2);//使用一个string类型来初始化另一个string对象
//赋值
s1 = "hello world";//直接赋值字符串操作
s2 = s1;//将一个string对象的内容直接赋值给另一个string对象
s3 = 'b';//赋值字符操作
//拼接
s1 += "你好世界";//字符串拼接 以追加方式
s2.append("lock");//调用拼接
s2.append("lock arr",4);//拼接前四个
s2.append(s3);//将string对象内容拼接
//查找
s1.find();//返回需要查找字符或者字符串的首位次 从0开始,不存在则返回-1;
//替换
s1.replace(x,y,"ssss");//将第x个位置开始的y个字符替换为ssss;
//插入删除
s1.insert(1,"111");//第一个位置插入111
s1.erase(1,3);//从第一个位置开始删除三个字符
3.deque容器
deque容器:双端数组,可以在头端进行插入删除;
对比与vector容器:在头部的插入和删除效率更高、速度更快。
vector容器访问速度更快。
d1.empty();//空为1非空为0
d1.size();//容器中的元素个数
d1.resize(15,1);//指定大小
d1.push_back(10);//尾插
d1.push_front(10);//头插
d1.pop_back();//尾部删除
d1.pop_front(); //尾部删除
d1.insert(d1.begin(),10);//在头部插入10
d1.insert(d1.begin(),2,10);//在头部插入俩个10
d1.insert(d1.begin(),d2.begin(),d2.end());//在d1的头部插入d2,是按照区间来进行插入的
d1.erase(); //删除
d1.erase(d1.begin(),d1.end()); //按照区间删除
d1.clear; //清空
d1[i];//[]访问
d1.at(i);//at访问
4.stack容器
stack是一种先进后出的数据结构,栈不能进行遍历,一般是判断是否为空,也可以获取容器内部元素个数。
satck<int>s1;//构造
s1.push(10);//入栈
s1.pop();//出栈
//判空
while(!s1.empty())
{
cout<<"栈不为空"<<endl;
}
s.size;//栈的大小
5.queue容器
queue容器(队列):是一种先进先出的数据结构,具有两个出口,队尾进(入队 push),队头出(出队 pop)。
队列可以一端新进元素,一端删除元素。
队列也不能被遍历,只能访问头部和尾部。
queue<int>q1;//构造队列 int类型
q1.push(10);//入队 10
q1.pop();//出队
//判空
while(!q1.empty())
{
cout<< "队列不为空" <<endl;
q1.pop();//出队
}
6.list容器
list也叫做链表:是一种物理上非连续性的储存结构,数据顺序是通过指针的指向来实现。
链表是由一个个节点组成,每个节点包含了数据域和指针域。指针指向下一个节点。
链表的优点:可以快速的进行插入删除
缺点:遍历较慢,占用空间大
在STL中的链表是一个双重循环链表,其中相对于普通链表不同的是最后一个节点指向第一个节点。list的迭代器只能支持前移后移操作,是一个双向迭代器。
list<int> l1;//构造
list<int> l2;
l1.push(10);//插入 10
l2.push(20);
l2 = l1;//赋值操作
l1.swap(l2);//交换
l1.insert(x,y);//在x位置插入y
l1.insert(x,n,y);//在x位置插入n个y
l1.clear();//清空
l1.erase(1,4);//删除区间[1-4];
l1.erase(pos);//删除pos位置的数据 返回下一个数据
l1.remove(elem);//删除链表中与elem相同的元素
l1.front();//返回第一个元素
l1.back();//返回最后一个元素
l1.reverse();//list的反转
l1.sort();list的排序
7.set/multiset容器:
所有元素在插入时自动排序
set/multiset是基于二叉树实现的
set中不能有数据重复,multiset可以有数据重复
//初始化
set<int>s1;
set<int>s2;
s1.insert(10);//插入
s1.size();//大小
s1.empty();//判空
s1.swap(s2);//交换
s1.insert(elem);//插入
s1.clear();//删除
s1.erase(pop);//删除pop所指的元素,返回下一个元素
s1.erase(begin,end);//删除begin,end的元素,返回下一个元素
s1.erase(elem);//删除容器中为elem的元素
s1.find(pos);//查找pos是否存在,存在就返回该键元素,不存在就返回set.end()
s1.count(pos);//返回pos元素的个数
8.map/multimap容器
map是一个两列多行表,第一列为key值,如同钥匙,第二列是实值value。
通过key来访问value,元素都是基于key值来自动排序。
map表实质是一个二叉树。
map容器的优点:通过key快速找到value。
缺点:map不能有重复的key。但是multimap允许有重复key。
map<int>m1;//初始化
m1.size();//大小
m1.empty();//容器是否空
m1.swap();//交换
m1.insert();//插入
m1.clear();//清空
m1.erase(num);//删除num元素
m1.erase(x,y);//删除x到y区间的元素
m1.find(x);//查找x元素
m1.count(x);//计数
四、常用泛型算法
1.查询算法find ()
int main()
{
vector<int> v = { 2,0,2,2,0,4,0,1 };
int x = 5;
auto result1 = find(v.begin(), v.end(),x);
if (result1 == v.end())
{
cout << "x does not contain" << endl;
}
else
{
cout << *result1 << endl;
}
}
2.复制 copy()
void PrintFunc(int x) {
std::cout << x << " ";
}
int main() {
vector<int> v = { 2,0,2,2,0,4,0,1 };
vector<int> u(8);
cout << "1." << endl;
for_each(v.begin(), v.end(), PrintFunc);
copy(v.begin(), v.end(), u.begin());
cout << "2." << endl;
for_each(u.begin(), u.end(), PrintFunc);
}