STL就是Standard Template Library,标准模板库。STL是泛型编程的实例,用到的技术就是类模板和函数模板。STL的一个重要特点是数据结构和算法的分离
模板
所谓模板是一种使用无类型参数来产生一系列函数或类的机制。通过模板可以产生类或函数的集合,使它们操作不同的数据类型,从而避免需要为每一种数据类型产生一个独立的类或函数
泛型程序设计
#include
#include
#include
#include
#include
using namespace std;
int main() {
const int N = 5;
vector<int> s(N); //定义一个大小为N的向量容器
//从标准输入读入向量容器的内容
for (int i = 0; i < N; i++)
cin >> s[i];
//输出向量容器中每个元素的相反数
transform(s.begin(), s.end(), ostream_iterator<int>(cout, " "), negate<int>());
cout << endl;
return 0;
}
Reference
C++序列式容器(STL序列式容器)是什么
所谓序列容器,即以线性排列(类似普通数组的存储方式)来存储某一指定类型(例如 int、double 等)的数据,需要特殊说明的是,该类容器并不会自动对存储的元素按照值的大小进行排序。
需要注意的是,序列容器只是一类容器的统称,并不指具体的某个容器,序列容器大致包含以下几类容器:
奇偶排序示例:
//10_5.cpp
#include
#include
#include
#include
#include
using namespace std;
int main() {
istream_iterator<int> i1(cin), i2; //建立一对儿输入流迭代器
vector<int> s1(i1, i2); //通过输入流迭代器从标准输入流中输入数据
sort(s1.begin(), s1.end()); //将输入的整数排序
deque<int> s2;
//以下循环遍历s1
for (vector<int>::iterator iter = s1.begin(); iter != s1.end(); ++iter) {
if (*iter % 2 == 0) //偶数放到s2尾部
s2.push_back(*iter);
else //奇数放到s2首部
s2.push_front(*iter);
}
//将s2的结果输出
copy(s2.begin(), s2.end(), ostream_iterator<int>(cout, " "));
cout << endl;
return 0;
}
#include
#include
#include
#include
using namespace std;
int main() {
string names1[] = {
"Alice", "Helen", "Lucy", "Susan" };
string names2[] = {
"Bob", "David", "Levin", "Mike" };
list<string> s1(names1, names1 + 4); //用names1数组的内容构造列表s1
list<string> s2(names2, names2 + 4); //用names2数组的内容构造列表s2
//将s1的第一个元素放到s2的最后
s2.splice(s2.end(), s1, s1.begin());
list<string>::iterator iter1 = s1.begin(); //iter1指向s1首
advance(iter1, 2); //iter1前进2个元素,它将指向s1第3个元素
list<string>::iterator iter2 = s2.begin(); //iter2指向s2首
++iter2; //iter2前进1个元素,它将指向s2第2个元素
list<string>::iterator iter3 = iter2; //用iter2初始化iter3
advance(iter3, 2); //iter3前进2个元素,它将指向s2第4个元素
//将[iter2, iter3)范围内的结点接到s1中iter1指向的结点前
s1.splice(iter1, s2, iter2, iter3);
//分别将s1和s2输出
copy(s1.begin(), s1.end(), ostream_iterator<string>(cout, " "));
cout << endl;
copy(s2.begin(), s2.end(), ostream_iterator<string>(cout, " "));
cout << endl;
return 0;
}
关联容器支持高效的关键字查找和访问,两个主要的关联容器是map和set,map中的元素是一些关键字-值(key-value)对:关键字起到索引的作用,值表示与索引相关联的数据。set中每个元素只包含一个关键字:set支持高效的关键字查询操作,检查一个给定关键字是否在set中。
标准库提供了8个关联容器,这8个容器的不同体现在关键字是否能重复,是否按顺序保存元素,这里的顺序不是指元素添加顺序,而是关键字的比较顺序,multi表示关键字可重复,unordered表示元素是无序保存的。
map
set
multi map,
multi set,
unordered_map
unordered_set
unordered_multi map
unordered_multi set
关键字类型的要求
对于有序容器,关键字类型必须定义元素比较的方法,默认情况下标准库使用关键字类型的<运算符来比较,也可以在创建有序容器时自定义比较操作函数。
map的基本操作函数:
C++ maps是一种关联式容器,包含“关键字/值”对
begin() 返回指向map头部的迭代器
clear() 删除所有元素
count() 返回指定元素出现的次数
empty() 如果map为空则返回true
end() 返回指向map末尾的迭代器
equal_range() 返回特殊条目的迭代器对
erase() 删除一个元素
find() 查找一个元素
get_allocator() 返回map的配置器
insert() 插入元素
key_comp() 返回比较元素key的函数
max_size() 返回可以容纳的最大元素个数
rbegin() 返回一个指向map尾部的逆向迭代器
rend() 返回一个指向map头部的逆向迭代器
size() 返回map中元素的个数
swap() 交换两个map
lower_bound() 返回键值>=给定元素的第一个位置
upper_bound() 返回键值>给定元素的第一个位置
value_comp() 返回比较元素value的函数
#include
#include
#include
#include
using namespace std;
int main() {
multimap<string, string> courses;
typedef multimap<string, string>::iterator CourseIter;
//将课程上课时间插入courses映射中
courses.insert(make_pair("C++", "2-6"));
courses.insert(make_pair("COMPILER", "3-1"));
courses.insert(make_pair("COMPILER", "5-2"));
courses.insert(make_pair("OS", "1-2"));
courses.insert(make_pair("OS", "4-1"));
courses.insert(make_pair("OS", "5-5"));
//输入一个课程名,直到找到该课程为止,记下每周上课次数
string name;
int count;
do {
cin >> name;
count = courses.count(name);
if (count == 0)
cout << "Cannot find this course!" << endl;
} while (count == 0);
//输出每周上课次数和上课时间
cout << count << " lesson(s) per week: ";
pair<CourseIter, CourseIter> range = courses.equal_range(name);
for (CourseIter iter = range.first; iter != range.second; ++iter)
cout << iter->second << " ";
cout << endl;
return 0;
}
//10_2.cpp
#include
#include
#include
using namespace std;
//求平方的函数
double square(double x) {
return x * x;
}
int main() {
//从标准输入读入若干个实数,分别将它们的平方输出
transform(istream_iterator<double>(cin), istream_iterator<double>(),
ostream_iterator<double>(cout, "\t"), square);
cout << endl;
return 0;
}
//10_3.cpp
#include
#include
#include
#include
using namespace std;
//将来自输入迭代器p的n个T类型的数值排序,将结果通过输出迭代器result输出
template <class T, class InputIterator, class OutputIterator>
void mySort(InputIterator first, InputIterator last, OutputIterator result) {
//通过输入迭代器p将输入数据存入向量容器s中
vector<T> s;
for (;first != last; ++first)
s.push_back(*first);
//对s进行排序,sort函数的参数必须是随机访问迭代器
sort(s.begin(), s.end());
//将s序列通过输出迭代器输出
copy(s.begin(), s.end(), result);
}
int main() {
//将s数组的内容排序后输出
double a[5] = {
1.2, 2.4, 0.8, 3.3, 3.2 };
mySort<double>(a, a + 5, ostream_iterator<double>(cout, " "));
cout << endl;
//从标准输入读入若干个整数,将排序后的结果输出
mySort<int>(istream_iterator<int>(cin), istream_iterator<int>(), ostream_iterator<int>(cout, " "));
cout << endl;
return 0;
}
//10_13.cpp
#include
#include //包含数值算法头文件
using namespace std;
int mult(int x, int y) {
return x * y; }; //定义一个普通函数
int main() {
int a[] = {
1, 2, 3, 4, 5 };
const int N = sizeof(a) / sizeof(int);
cout << "The result by multipling all elements in a is "
<< accumulate(a, a + N, 1, mult) //将普通函数mult传递给通用算法
<< endl;
return 0;
}
//10_14.cpp
#include
#include //包含数值算法头文件
using namespace std;
class MultClass {
//定义MultClass类
public:
int operator() (int x, int y) const {
return x * y; } //重载操作符operator()
};
int main() {
int a[] = {
1, 2, 3, 4, 5 };
const int N = sizeof(a) / sizeof(int);
cout << "The result by multipling all elements in a is "
<< accumulate(a, a + N, 1, MultClass()) //将类multclass传递给通用算法
<< endl;
return 0;
}
//10_15.cpp
#include
#include //包含数值算法头文件
#include //包含标准函数对象头文件
using namespace std;
int main() {
int a[] = {
1, 2, 3, 4, 5 };
const int N = sizeof(a) / sizeof(int);
cout << "The result by multipling all elements in A is "
<< accumulate(a, a + N, 1, multiplies<int>()) //将标准函数对象传递给通用算法
<< endl;
return 0;
}
//10_16.cpp
#include
#include
#include
#include
#include
using namespace std;
int main() {
int intArr[] = {
30, 90, 10, 40, 70, 50, 20, 80 };
const int N = sizeof(intArr) / sizeof(int);
vector<int> a(intArr, intArr + N);
cout << "before sorting:" << endl;
copy(a.begin(), a.end(), ostream_iterator<int>(cout, "\t"));
cout << endl;
sort(a.begin(), a.end(), greater<int>());
cout << "after sorting:" << endl;
copy(a.begin(), a.end(), ostream_iterator<int>(cout, "\t"));
cout << endl;
return 0;
}
#include
#include
#include
using namespace std;
int main()
{
int src[]={
1,2,3,4,5,6,7};
//vector srcVec;
//srcVec.resize(7);
vector<int> srcVec(src,src+7); //注意!7为长度
ostream_iterator<int> ofile(cout," ");
//将数值复制到vector里,参数依次是开始,结束,vector数组的开始
//(看起来src+7越界了)src+7,表示结束,srcVec.end()相当于src+7
copy(src,src+7,srcVec.begin());
cout<<"srcVec contains:\n";
//将数值复制到输出流中,参数依次是开始,结束,输出流
copy(srcVec.begin(),srcVec.end(),ofile);
cout<<endl;
//将数组向左移动两位
copy(src+2,src+7,src);
cout<<"shifting array sequence left by 2"<<endl;
copy(src,src+7,ofile);
cout<<endl;
//另一种方法,注意观察copy()中第二个参数
//srcVec.end()相当于src+7
//将数组向左移动两位
copy(srcVec.begin()+2,srcVec.end(),srcVec.begin());
cout<<"shifting array sequence left by 2"<<endl;
copy(srcVec.begin(),srcVec.end(),ofile);
cout<<endl;
return 0;
}
数组是c++中类似vector的数据结构,它们都可以对一种类型进行储存,既都是容器。虽说两者有相似之处,但也有显著的区别,c++ primer的作者说到,在实际的编程中,我们作为程序员应该避免用到低级数组和指针,而更应该多用高级的vector和迭代器。在程序强调速度的情况下,我们程序员可以在类类型的内部使用数组和指针。下面我对vector和数组进行了总结。
vector扩容原理概述
当面试官问我们vector扩容机制时,他想问什么?
#include
#include
using namespace std;
int main()
{
vector<int> vec;
cout << vec.capacity() << endl;
for (int i = 0; i<10; ++i)
{
vec.push_back(i);
cout << "size: " << vec.size() << endl;
cout << "capacity: " << vec.capacity() << endl;
}
system("pause");
return 0;
}
两者的相同点如下:
两者的区别如下:
STL标准库常见面试题(一)
C++STL常见面试题