一、STL简介
1、什么是STL
STL(Standard Template Library)标准模板库,主要由容器、迭代器、算法、函数对象、内存分配器和适配器六大部分组成。STL已是标准C++的一部分,使用STL开发系统可以提高开发效率。
2、容器(Containers)
容器类是可以包含其它对象的模板类,如向量类(vector)、链表类(list)、双向队列类(deque)、集合类(set)和映射类(map)等。其中vector、list、deque为序列式容器,set、map为关联式容器。如:
vector
vector
list
3、算法(Algorithms)
STL提供了非常多的数据结构算法,它们在std命名空间的范围内定义,通过#include
注意:算法都是全局函数模板,如:for_each( )、find()、count()和sort()等
4、迭代器(Iterator)
迭代器类似于C++的指针,是一个指示器,用来指示容器中的某个元素,迭代器的出现使得容器与算法的分离成为可能,即使用算法必须使用容器和迭代器。
5、函数对象:具有operator()运算符重载函数的对象。
二、vector技术
1、vector概述
vector是STL提供的最简单,也是最常用的容器类模板之一,类似于传统数组。
vector特点:提供了对数组元素的快速、随机访问,以及在序列尾部快速、随机的插入和删除;vector对象在运行时可以动态改变自身的大小以便容纳任何数目的元素。
vector头文件:vector是在标准头文件
2、vector的成员函数
(1)构造函数:
vector
vector
vector
vector
(2)操作
v.empty(); // 如果 v 为空,则返回 true,否则返回 false。
v.size(); // 返回 v 中元素的个数。
v.push_back(t); // 在 v 的末尾增加一个值为 t 的元素。
v.pop_back(); // 删除v的末尾元素
v.erase(iter);//删除iter指示器指示的元素
v.erase(iter_F,iter_L);//删除指示器iter_F和iter_L之间的所有元素
v.resize(10); //改变v的大小为10;
v[n]; // 返回 v 中位置为 n 的元素。
v1 = v2; // 把 v1 的元素替换为 v2 中元素的副本。
v1 == v2; // 如果 v1 与 v2 相等,则返回 true。
// !=, <, <=, >, 和>=保持这些操作符惯有的含义。
例题1基本操作练习
#include
#include
using namespace std;
void main()
{
vector
cout<<"v.size()="< v.push_back(10); v.push_back(12); cout<<"v.size()="< for ( int i=0;i cout< v.pop_back(); v.pop_back(); v.pop_back(); v.pop_back(); cout<<"v.size()="< for ( i=0;i cout< } 3、高级操作 迭代器和算法同样适用于其它容器。 (1)迭代器 迭代器类型: vector 举例: for (vector cout<<*iter< (2)算法 for_each 算法: for_each(起始iterator,末尾iterator,函数模板); 举例: #pragma warning(disable:4786) #include #include #include #include using namespace std; void PrintIt(string & S) { cout< } void main() { vector v.push_back("English"); v.push_back("Math"); v.push_back("Chinese"); v.push_back("Program"); for_each (v.begin(),v.end(),PrintIt); } sort算法 sort((起始iterator,末尾iterator); 举例: sort(v.begin(),v.end()); count算法 count(起始iterator,末尾iterator,某个值)统计某个值的出现次数 举例: #pragma warning(disable:4786) #include #include #include using namespace std; void PrintIt(string & S) { cout< } void main() { vector v.push_back(100); v.push_back(80); v.push_back(90); v.push_back(100); v.push_back(80); cout< } find算法 find(起始iterator,末尾iterator,某个值)查找某个值是否出现 举例: vector iter=find(v.begin(),v.end(),100); if (iter==v.end()) cout<<"No found!"< else cout<<*iter< count_if和find_if算法:这两个算法的使用需要借助函数对象完成。 4、vector应用 练习1:vector综合练习 //文件名:CHAPTER6-24.cpp #include #include #include using namespace std; void pause() //程序暂停 { char c; cout << "\n\nPress return to continue: "; cin.get(c); cout << "\n\n"; } int main() { vector ostream_iterator copy(v.begin(), v.end(), out);// 通过算法函数copy输出v中全部的数据 pause(); //程序输出为:0 0 0 0 0 0 0 0 0 0 vector i += 4; //指向第5个元素 *i++ = 7; // or v[4] = 7; //使第5个元素值为7,同时迭代器指向下一个元素 *i = 9; // or v[5] = 9; //赋值第6个元素大小为9 copy(v.begin(), v.end(), out); // 把通过迭代器赋值后的所有元素打印出来 pause();//程序输出为: 0 0 0 0 7 9 0 0 0 0 vector copy(where, v.end(), out);// 把查找到的元素及其该元素后的数据全部显示出来。 pause();//程序输出为:9 0 0 0 0 where = v.insert(where, 8); //在迭代器指示的元素前插入一个元素,其值为8 copy(v.begin(), v.end(), out); //检验insert函数的效果 pause();//程序输出为:0 0 0 0 7 8 9 0 0 0 0 where += 3; //迭代器指示当前元素后的第三个元素为当前元素 where = v.insert(where, 4); //在当前元素前插入一个元素,值为4 copy(v.begin(), v.end(), out); pause();//程序输出为:0 0 0 0 7 8 9 0 4 0 0 0 where -= 6;//迭代器前移6个元素 where = v.insert(where, 11); //插入元素11到vector中 copy(v.begin(), v.end(), out); pause();//程序输出为:0 0 11 0 0 7 8 9 0 4 0 0 0 v.erase(where+2); // 删除迭代器后的第2个元素 copy(v.begin(), v.end(), out); pause();//程序输出为:0 0 11 0 7 8 9 0 4 0 0 0 sort(v.begin(), v.end()); //对vector进行由大到小排序 copy(v.begin(), v.end(), out); pause();//程序输出为:0 0 0 0 0 0 0 4 7 8 9 11 if (binary_search(v.begin(), v.end(), 8)) // vector的查找 cout << "Yes, 8 occurs in vector v."; else cout << "No, didn't find 8 in vector v."; pause();//程序输出为:Yes, 8 occurs in vector v. if (binary_search(v.begin(), v.end(), 12)) // vector的查找 cout << "Yes, 12 occurs in vector v."; else cout << "No, didn't find 12 in vector v."; pause();//程序输出为:No, didn't find 12 in vector v. where = lower_bound(v.begin(), v.end(), 8); //查找第一次出现8的位置 copy(where, v.end(), out); pause();//程序输出为:8 9 11 where = lower_bound(v.begin(), v.end(), 0); //查找第一次出现0的位置 copy(where, v.end(), out); pause();//程序输出为:0 0 0 0 0 0 0 4 7 8 9 11 where = upper_bound(v.begin(), v.end(), 0); //查找第一次不出现0时的位置 copy(where, v.end(), out); pause();//程序输出为:4 7 8 9 11 vector if (v == w) //两个vector直接比较 cout << "v and w have the same contents"; else cout << "v and w have different contents"; pause();//程序输出为:v and w have the same contents w[5] = 17; if (v == w) cout << "v and w have the same contents"; else cout << "v and w have different contents"; pause();//程序输出为:v and w have different contents v[5] = 17; if (v == w) cout << "v and w have the same contents"; else cout << "v and w have different contents"; pause();//程序输出为:v and w have the same contents return 0; } 练习2 读入一段文本到vector对象,每个单词存储为vector中的一个元素。把vector对象中每个单词转化为大写字母。输出vector对象中转化后的元素,每8个单词为一行输出。 三、deque技术 1、deque概述 deque(double-ended queue)是一种动态的数组形式,可以向两端发展。 deque特点:也是随机访问的数据类型;提供了在序列两端快速的插入和删除操作的功能;可以在需要时修改其自身大小。 deque头文件:deque是在标准头文件 2、deque的成员函数 (1)构造函数: deque deque deque deque 说明: 第一种创建了一个可容纳类型为T的空deque对象name1; 第二种用拷贝构造函数从现有的name1创建了新的deque对象name2; 第三种创建了一个初始大小为size的deque对象name3; 第四种创建了一个初始大小为size,每个元素初始化值为value的deque对象name4; (2)操作 d.empty(); // 如果 d 为空,则返回 true,否则返回 false。 d.size(); // 返回 d 中元素的个数。 d.push_back(t); // 在 d 的末尾增加一个值为 t 的元素。 d.push_front(t); // 在 d 的头部增加一个值为 t 的元素。 d.pop_back(); // 删除d的末尾元素 d.pop_front(); // 删除d的第一个元素 d.insert(iterator , t); //在d的iterator处插入t。 d.insert(iterator, iter_F,iter_L); //在d的iterator处插入iter_F到iter_L之间的元素。 d.erase(iter); //删除iter指示器指示的元素 d.erase(iter_F,iter_L);//删除指示器iter_F和iter_L之间的所有元素 d.resize(10); //改变d的大小为10; d[n] // 返回 d 中位置为 n 的元素。 d1=d2 // 把 d1 的元素替换为 d2 中元素的副本。 d1==d2 // 如果 d1 与 d2 相等,则返回 true。 // !=, <, <=, >, 和>=保持这些操作符惯有的含义。 d.swap(d1); //d和d1容器中的内容互换。 3、高级操作 (1)迭代器 deque 举例: for (deque cout<<*iter< (2)算法 for_each()算法、sort()算法、count()算法、find()算法同样适用于deque容器; 3、deque应用 练习:deque综合练习 #include #include #include #include using namespace std; int main() { //create empty deque of strings deque //insert several elements coll.assign (3, string("string")); coll.push_back ("last string"); coll.push_front ("first string"); //print elements separated by newlines copy (coll.begin(), coll.end(), ostream_iterator cout << endl; //remove first and last element coll.pop_front(); coll.pop_back(); //insert ''another'' into every element but the first for (int i=1; i coll[i] = "another " + coll [i]; } //change size to four elements coll.resize (5, "resized string"); //print elements separated by newlines copy (coll.begin(), coll.end(),ostream_iterator } 四、list技术 1、list概述 list是一个双向链表容器,不支持随机访问。 list特点:不支持随机访问,访问链表元素要从链表的某个端点开始,插入和删除操作所花费的时间是固定的,即与元素在链表中的位置无关;优势是在任何位置执行插入或删除动作都非常迅速;可以在需要时修改其自身大小。 list头文件:list是在标准头文件 2、list的成员函数 (1)构造函数: list list list list 说明: 第一种创建了一个可容纳类型为T的空list对象name1; 第二种用拷贝构造函数从现有的name1创建了新的list对象name2; 第三种创建了一个初始大小为size的list对象name3; 第四种创建了一个初始大小为size,每个元素初始化值为value的list对象name4; (2)操作 d.empty(); // 如果 d 为空,则返回 true,否则返回 false。 d.size(); // 返回 d 中元素的个数。 d.push_back(t); // 在 d 的末尾增加一个值为 t 的元素。 d.push_front(t); // 在 d 的头部增加一个值为 t 的元素。 d.pop_back(); // 删除d的末尾元素 d.pop_front(); // 删除d的第一个元素 d.front(); //返回d的第一个元素的引用 d.back(); //返回d的最后一个元素的引用 d.insert(iterator , t); //在d的iterator处插入t。 d.insert(iterator, iter_F,iter_L); //在d的iterator处插入iter_F到iter_L之间的元素。 d.erase(iter);//删除iter指示器指示的元素 d.erase(iter_F,iter_L);//删除指示器iter_F和iter_L之间的所有元素 d.swap(d1); //d和d1容器中的内容互换。 d.sort(); //list类的排序使用成员函数完成。而不是用通用算法函数。 d.resize(10); //改变d的大小为10; d.merge(d1); //合并d1和d,以升序排列存储到d中 d.splice(iterator, T);//把另一个list对象T插入到iterator位置 d.splice(iterator,T,iter);//把另一个list对象T的iter位置的元素插入到d的iterator位置。 迭代器 begin()和end()返回头尾的迭代器; rbegin()和rend()返回尾头的反向迭代器:rbegin()返回最后一个元素的迭代器,rbegin++返回倒数第二个元素。(注意:迭代器只能使用==和!=比较,不能使用>或<比较)。 3、list应用 #include #include #include #if _MSC_VER > 1020 // if VC++ version is > 4.2 using namespace std; // std c++ libs implemented in std #endif void printLists(const list { cout << "list1: "; copy (l1.begin(), l1.end(), ostream_iterator cout << endl << "list2: "; copy (l2.begin(), l2.end(), ostream_iterator cout << endl << endl; }; int main() { //create two empty lists list //fill both lists with elements for (int i=0; i<6; ++i) { list1.push_back(i); list2.push_front(i); } printLists(list1, list2); //insert all elements of list1 before the first element with value 3 of list2 //-find() returns an iterator to the first element with value 3 list2.splice(find(list2.begin(),list2.end(), // destination position 3), list1); // source list printLists(list1, list2);//move first element to the end list2.splice(list2.end(), // destination position list2, // source list list2.begin()); // source position printLists(list1, list2); //sort second list, assign to list1 and remove duplicates list2.sort(); list1 = list2; list2.unique(); printLists(list1, list2); //merge both sorted lists into the first list list1.merge(list2); printLists(list1, list2); return 0; } 五、set技术 1、set概述 set是一种关联式容器,关联式容器依据特定的排序准则,自动为其元素排序。set中每个元素只能出现一次。即数学中的集合。 set头文件:set是在标准头文件 2、set的成员函数 (1)构造函数: set set (2)操作 s.empty(); // 如果 s 为空,则返回 true,否则返回 false。 s.size(); // 返回 s 中元素的个数。 s.insert( t); //在s中插入t。 s.insert(iter_F,iter_L); //在s中插入iter_F到iter_L之间的元素。 s.erase(iter); //删除iter指示器指示的元素 s.erase(iter_F,iter_L);//删除指示器iter_F和iter_L之间的所有元素 s.erase(key); //删除s中的key元素。 s.lower_bound(key);//返回key前面的元素的迭代器 s.upper_bound(key);//返回key后面的元素的迭代器 s.find(key); //在s中查找键值key,找到返回iterator,否则返回end()。 s.resize(10); //改变s的大小为10; 3、set应用 编写程序通过删除单词尾部的’s’生成该单词的非复数版本。同时建立一个单词排除集,用于识别以’s’结尾、但这个结尾的’s’又不能删除的单词。例如,放在该排除集中的单词可能有success和class。使用这个排除集编写程序,删除输入单词的复数后缀,而如果输入的是排除集的单词,则保持该单词不变。 #pragma warning(disable: 4786) #include #include int main() { std::set int ai[] = {0, 1, 2, 3} ; //construct from a range std::set //copy constructor std::set std::set std::set //判断c1是否为空 if(c1.empty()) { std::cout << "set c1 is empty" << std::endl ; } else { std::cout << "set c1 is not empty" << std::endl ; } //使用begin, end显示c2所有元素 std::cout << "c2 (using begin, end) = " ; for(Iter = c2.begin(); Iter != c2.end(); Iter++) { std::cout << *Iter << " " ; } std::cout << std::endl ; //使用rbegin,rend显示c2所有元素 std::cout << "c2 (using rbegin, rend) = " ; for(RevIter = c2.rbegin(); RevIter != c2.rend(); RevIter++) { std::cout << *RevIter << " " ; } std::cout << std::endl ; //使用find进行元素的查找 std::set if(constIter != c1.end()) { std::cout << "c1 contains element 3, *constIter = " << *constIter << std::endl ; } //使用size返回c1的最大元素大小 std::cout << "c1.size() = " << c1.size() << std::endl ; //使用swap把c1和c2进行元素交换 c1.insert(4) ; c2.swap(c1) ; std::cout << "The last element of c2 = " << *(c2.rbegin()) << std::endl ; //使用clear进行c1元素的清除 c1.clear() ; std::cout << "After calling c1.clear(), c1.size() = " << c1.size() << std::endl ; //使用upper_bound返回c2当前值的最近增值迭代器 std::cout << "* (c2.upper_bound(3)) = " << *(c2.upper_bound(3)) << std::endl ; //使用lower_bound返回c2当前值的最近降值迭代器 std::cout << "* (c2.lower_bound(3)) = " << *(c2.lower_bound(3)) << std::endl ; //使用erase进行元素的删除操作 if(c3.erase(1) != 0) { std::cout << "c3 does not contain 1 any more" << std::endl ; } else { std::cout << "No elements in c3 match key 1" << std::endl ; } if((c2.erase(c2.begin())) != c2.end()) { std::cout << "c2 does not contain 0 any more" << std::endl ; } else { std::cout << "No elements in c2 match key 0" << std::endl ; } c3.erase(c3.begin(), c3.end()) ; std::cout << "after c3.erase(c3.begin(), c3.end()), c3.size() = " << c3.size() << std::endl ; return 0 ; } 六、map技术 1、map概述 map是一种关联式容器,set中每个元素都是由“键值/实值”所形成的一对组合,每个键值只能出现一次,不能重复。 map头文件:map是在标准头文件 2、map的成员函数 (1)构造函数: map // 创建一个名为m2的空map对象,其键和值的类型分别为k和v map // 创建m2的副本m,m与m2必须有相同的键类型和值类型 map // 创建map类型的对象m,存储迭代器iter_F和 iter_L标记的范围内所有元素的副本。元素的类型必须能转换为pair 对于键类型,唯一的约束就是必须支持 < 操作符,至于是否支持其他的关系或相等运算,则不作要求。 (2)操作: m.empty()、m.size()、m.begin()、m.end()、m.rbegin()、m.rend()、m.swap(m1)、m.lower_bound(key)、m.upper_bound(key)、、 m.insert(pair m.insert(iterator, pair m.erase(iterator)、m.erase(key)、m.erase(iter_F,iter_L)、 m[key] //如果下标所表示的键在容器中不存在,则添加新元素 3、map应用 (1)编写程序统计并输出所读入的单词出现次数。 (2)输入两个多项式,计算两个多项式的加法运算结果。
或在非标准向后兼容头文件list.h中定义。