STL 提供三种类型的组件 : 容器 , 迭代 和算法 ,他们都支持泛型程序设计标准 .
容器有两类 : 顺序容器 和 关联容器 . 顺序容器 (vector ,list ,deque ,string etc..)它是一系列元素的有序集合.关联容器(set , multist , map , multimap )包括查找元素的键值,
迭代器的作用是遍历容器 .
STL 算法库 包括四类算法 : 排序算法 , 不可变序算法 ,变序性算法 和数值算法 .
#include <iostream>
#include <fstream>
#include <cstdio>
#include <vector>
#include <numeric>
using namespace std ;
// 用 vector 向量容器装入10个整数 , 然后 , 使用迭代器 iterator 和 accumulate 算法统计出
// 10 个元素的和
int main ()
{
vector<int> v;
vector<int>::iterator it ;
int i ;
for (i = 0 ; i<10 ;i++)
{
// 尾部元素扩张方式赋值
v.push_back(i);
}
// 使用iterator 迭代器 顺序遍历容器 ;
for (it = v.begin() ; it!= v.end(); it++)
{
// 输出迭代器当前位置的元素
cout<<*it <<" ";
}
cout<<endl;
cout<<accumulate(v.begin() ,v.end(),0);
return 0 ;
}
一 vector
1 丶 vector 容向量容器不但能像数组那样对数组进行随机访问 , 还能在尾部插入元素,完全可以代替数组 ,值得注意的是, vector 具有自动管理的功能 ,对于元素的插入和删除 ,可以动态的调整所占内存的空间.
2 丶 使用vector 向量容器 ,需要包含头文件 #include <vector> .
3 丶 vector 容器的下表示从0 开始的, 也就是说 ,如果vector 的 容器大小是 n,那么,元素的下标是 0 ~n-1 , 可以事先定义容器的大小, 还有一个就是 vector 的begin () 和end()方法 , 前者返回的是首元素的迭代器 ,end()返回的是最后一个元素的下一个元素的迭代器.
二 创建vector对象
创建vector 有三种常用的方法
(1) 不指定容器的元素个数 ,
vector <int> v ;
(2) 创建时指定容器的大小 , 比如 , 定义一个用来存储10 个double 类型的向量容器;
vector <double > v(10) ;
ps : 注意下标
(3) 创建一个具有 n个元素的向量容器对象 ,每个对象具有指定的初始值;
vecor <double > v(10 ,8.6) ;
三 尾部容器扩张
3.1
我们通常会用push_back()对vector 容器在尾部插入新元素, vector 容器会自动分配内存空间. 可以对空的 vector 对象扩张
也可对已有的元素的vector 对象扩张.
int main ()
{
vector <int> v ;
v.push_back(8) ;
v.push_back(4) ;
v.push_back(1) ;
v.push_back(5) ;
return 0 ;
}
3.2 下标方式访问 vector 元素
int main ()
{
vector <int> v(3) ;
v[0] = 1 ;
v[1] = 2 ;
v[2] = 3 ;
return 0 ;
}
3.3 用迭代器访问vector元素
int main ()
{
vector <int> v(3) ;
v[0] = 1 ;
v[1] = 2 ;
v[2] = 3 ;
vector<int>::iterator it ;
for( it = v.begin() ; it!= v.end() ;it++)
{
cout<< *it<<" ";
}
return 0 ;
}
3.4 元素的插入
使用 insert() 方法可以在vector 对象的任意位置前插入一个新的对象 , 同时 ,vector
自动扩张一个元素空间, 插入位置后的所有元素依次向后挪动一个位置.
当然要注意的是, insert()方法要求插入的位置 , 是元素的迭代器的位置 ,而不是元素的下标 ;
int main ()
{
vector <int> v(3) ;
v[0] = 10 ;
v[1] = 11 ;
v[2] = 12 ;
v.insert(v.begin(),8 );
v.insert(v.begin()+2 ,1);
v.insert(v.begin()+1, 2);
v.insert(v.end(),3) ;
vector<int>::iterator it ;
for( it = v.begin() ; it!= v.end() ;it++)
{
cout<< *it<<" ";
}
// 运行结果
// 8 2 10 1 11 12 3
return 0 ;
}
3.5 元素的删除
erase()方法可以删除 vector 中迭代器所指的一个元素或一段区间中的所有元素.
clear()方法则可以一次性的 删除 vector 中的所有元素 :
int main ()
{
vector <int> v(10) ;
int i ;
for( i = 1 ; i<=10 ;i++)
{
v[i-1] = i ;
}
// 删除第二个元素,从0 开始计数;
v.erase(v.begin()+2);
vector<int>::iterator it ;
for( it = v.begin() ; it!= v.end() ;it++)
{
cout<< *it<<" ";
}
cout<<endl;
v.erase(v.begin()+1 , v.begin()+5);
for( it = v.begin() ; it!= v.end() ;it++)
{
cout<< *it<<" ";
}
cout<<endl;
//运行结果
// 1 2 4 5 6 7 8 9 10
// 1 7 8 9 10
v.clear(); // 删除所有的
cout<<v.size()<<endl;
return 0 ;
}
3.6 使用reverse 反向排序算法
reverse 反向排序算法 ,需要定义头文件"#include <algorithm>"
reverse 算法可以将向量中的某段迭代器区间元素反向排列,
int main ()
{
int i ;
vector<int> v(10) ;
for (i = 0 ; i< 10 ;i++)
{
v[i] = i ;
}
// 反向排列向量的从首到尾的元素;
reverse(v.begin() ,v.end()) ;
vector<int>::iterator it ;
for(it = v.begin() ; it!=v.end() ;it++)
{
cout<<*it<<" " ;
}
// 运行结果
// 9 8 7 6 5 4 3 2 1 0
return 0 ;
}
3.7 使用sort算法对向量进行元素排序
struct Rule{
bool operator () (const int &a ,const int &b)
{
return a>b ;
}
};
int main ()
{
int i ;
vector<int> v(10) ;
for (i = 0 ; i< 10 ;i++)
{
v[i] = i ;
}
sort(v.begin(),v.end()); // 默认是从小到大排列;
sort(v.begin(),v.end(),Rule()); // 改写成 从大到小;
vector<int>::iterator it ;
for (it = v.begin() ; it!=v.end() ;it++)
{
cout<<*it<<" ";
}
return 0 ;
}
3.8 向量的大小
使用size 方法 返回的是向量大小,即元素的个数
使用empty 方法可以判空
此处 不用代码演示了 .
四 丶 String 基本字符系列的容器
C语言提供一个 char 类型来处理字符串 ,但是对于字符串 ; 只能通过字符串数组来进行处理, 就不太方便 ,c++STL 就提供了
string 字符串容器 ,比如 可以 vector <string> 可以替换 c语言中的 char str[100] ;
当然使用的时候要包含 #include <string>
4.1 创建一个string 对象
int main ()
{
string s ;
s = "hello";
cout<<s<<endl;
cout<<s.size()<<endl;
s = "HELLO11";
cout<<s<<endl;
cout<<s.size()<<endl;
// 注意可以随时修改字符串
// 运行结果
/* hello
5
HELLO11
7
*/
return 0 ;
}
4.2 更常用的方法 , 把字符串指针赋给一个字符串对象
int main ()
{
string s ;
char ss[100] ;
scanf("%s",ss);
s = ss ;
cout<<s ;
// hello word
//hello word
return 0 ;
}
4.3 从string 对象尾部填加字符
int main ()
{
string s="123" ;
s+='a';
s+='b';
s+='c';
cout<<s;
return 0 ;
}
4.3.1 从string 对象尾部追加字符串
int main ()
{
string s="123" ;
s+="abc" ;
s+="hello";
cout<<s<<" "<<s.size() ;
return 0 ;
}
4.3.2 采用append() 方法
int main ()
{
string s="hello" ;
s.append(" abc") ;
s.append(" 123") ;
cout<<s;
// hello abc 123
return 0 ;
}
4.4 给string 对象插入字符
int main ()
{
string s="123456" ;
string::iterator it ; // 定义迭代器;
it = s.begin() ;
s.insert(it+1,'*');
cout<<s;
//1*23456
return 0 ;
}
4.5 访问string 对象的元素
一般我们会使用下标方式随机访问 string 对象的元素 , 下标从0 开始的 .
4.6 删除string对象的元素
(1) 清空一个字符串 , 则直接给它赋空字符串即可 ;
(2) 使用 erase() 方法删除迭代器所指的那个元素或一个区间中所有的元素
int main ()
{
string s="123456" ;
string::iterator it = s.begin() ; // 定义迭代器;
s.erase(it+1 ,it+5);
cout<<s;
return 0 ;
}
4.7 替换string 对象的字符
int main ()
{
string s="123456" ;
string::iterator it = s.begin() ; // 定义迭代器;
// 从第三个开始 ,将持续的三个字符替换成"good"
s.replace(3,3,"Good");
cout<<s;
// 运行结果
// 123Good
return 0 ;
}
4.8 搜素string 对象的 元素或者子串
采用find() 方法可以查找字符串中的第一个字符元素(char , 用单引号界定 )或者子串(用 双引号界定 ) ,如果查到
则返回下标值 (从0 开始的) , 如果查不到 ,则返回4294967295 .
find() 方法 有许多重载函数 ;
int main ()
{
string s ;
s = "cat dog cat";
// 查找第一个字符'c' 返回下标;
cout<<s.find('o')<<endl;
// 查找第一个子串 "c" 返回下标 ;
cout<<s.find("c")<<endl;
// 查找第一个cat 子串
cout<<s.find("cat")<<endl;
// 查找第一个 dog 子串
cout<<s.find("dog")<<endl;
cout<<s.find("dok")<<endl; // 找不到 返回 垃圾值
return 0 ;
}
4.9 string 对象的比较
string 对象的可以使用 compare()方法与其他字符串相比较 . 如果它比对方大,则返回1 ;
如果它比对方小, 则返回-1 ,相同返回0
int main ()
{
string s ;
s = "cat dog cat" ;
cout<<s.compare("cat")<<endl;
cout<<s.compare("cat dog cat")<<endl;
cout<<s.compare("dog")<<endl;
return 0 ;
}
4.9.1 用reverse 反向排序 string 对象
采用reverse()方法 可以将 string 对象的迭代器所指的一段区间中的元素 (字符)反向排序. reverse()方法需要头文件哦
int main ()
{
string s ;
s = "123456789" ;
reverse(s.begin() ,s.end()) ;
cout<<s;
return 0 ;
}
4.9.2 string 对象作为vector 元素
string对象可以作为vector 向量的元素 类似于字符串数组
int main ()
{
vector<string> s ;
s.push_back("Jack") ;
s.push_back("Mike") ;
s.push_back("Tom") ;
cout<<s[0]<<endl;
cout<<s[0][2]<<endl;
return 0 ;
}
4.9.3 string 类型的数字化处理
在许多竞赛中 ,常常需要将读入的数字的每一位分离出来 ,如果采用取余的方法,花费时间就会太长,这时候,我们可以将读入的
数据当做字符串来处理 ,这样就比较省事 ; 下面是计算一个整数各位的和
int main ()
{
string s ;
int i ;
int sum = 0 ;
s = "1234059 " ;
for (i = 0 ; i<s.length() ; i++)
{
if(s[i]=='0') sum+=0 ;
else if(s[i]=='1') sum+=1 ;
else if(s[i]=='2') sum+=2 ;
else if(s[i]=='3') sum+=3 ;
else if(s[i]=='4') sum+=4 ;
else if(s[i]=='5') sum+=5 ;
else if(s[i]=='6') sum+=6 ;
else if(s[i]=='7') sum+=7 ;
else if(s[i]=='8') sum+=8 ;
else if(s[i]=='9') sum+=9 ;
}
cout<<sum ;
return 0 ;
}
4.9.4 string 对象与字符串数组互操作
int main ()
{
string s ;
char ss[100] ;
scanf("%s",ss);
s = ss ;
printf(s.c_str());
cout<<endl;
printf("%s\n",ss);
cout<<s<<endl;
/*abc123
abc123
abc123
abc123*/
return 0 ;
}
4.9.5 string对象 与sscanf 函数
在C语言里 ,sscanf 函数很管用 ,它可以把一个字符串按照你需要的方式分离出子串 ,甚至数字 ;