C++学习笔记
----标准模板库STL
一.标准模板库
- 介绍
标准模板库将常用的数据结构( vector封装数组, list封装了链表, map和 set封装了二叉树等)以及对这些数据结构进行操作(插入 排序 删除 查找等)的基本算法用C++的类模板的形式加以实现供人们复用, 体现了泛型编程的思想。 - 组成
(1)容器
容器以常用的数据结构的形式管理某种类型的若干对象, 这些数据结构包括list(链表), vector(类似于动态数组), deque(双端队列), 集合(set), 映射(map), queue(队列) , stack(堆栈)等等。容器是用类模板实现的,容器管理的对象也称为元素, 其类型可以是任意的。
(2)算法
算法通过迭代器操控各种容器中的元素,如: find用于在容器中查找等于某个特定值的元素, for_each用于将某个函数应用到容器中的各个元素上, sort用于对容器中的元素排序, 等等。每个算法都可用于所有的容器,算法是用函数模板实现的。
(3)迭代器
迭代器是一个能以相同的方式访问遍历所有不同类型容器的元素的对象。一个迭代器指出容器中的一个特定位置, 算法通过迭代器来定位和操控容器中的元素。
二.迭代器
- STL中的每个容器都有一个名为iterator的迭代器成员, 其类型由容器类名<类型名>确定。要用迭代器访问容器的元素必须先定义迭代器变量, 迭代器变量定义的格式为:
容器类名<类型名>::iterator 迭代器名;
容器类名<类型名>::reverse_iterator 迭代器名;
vector<int> vec;
vector<int>::iterator it = vec.begin();

- 用法:
类似指针:
begin() 返回指向第一个元素的迭代器
end() 返回指向最后一个元素的迭代器
rbegin() 返回指向最后一个元素的逆序迭代器
rend() 返回指向第一个元素前面位置的逆序迭代器
迭代器重载了*, ++, --, ==, !=, =运算符:
operator *返回当前位置上的元素值
operator ++, operator --让迭代器指向下一个,上一个元素
operator ==, operator !=判断两个迭代器是否指向同一个元素
operator =为迭代器赋值
三.vector容器
-
简介
(1)vector容器模拟动态数组,支持随机存取。
(2)vector容器类在内存不够时能够自动重新分配,支持reallocation。
(3)vector容器类的元素可以是任意类型的T,但需定义赋值和拷贝功能。
(4)vector容器类的元素支持迭代器访问,也支持下标访问。
(5)头文件#include<vector>
-
操作
(1)构造和析构
(2)非变动操作
(3)赋值操作
(4)元素存取
(5)插入删除元素
#include<iostream>
#include<vector>
using namespace std;
int main()
{
vector<int> vec1; //vec1对象初始为空
vector<int> vec2(10, 6); //vec2最初有10个值为6的元素
vector<int> vec3(vec2.begin(), vec2.begin()+3); //拷贝构造,vec3最初有3个值为6的元素
vector<int>::iterator i; //声明迭代器i
//从前向后显示vec1中的数据
cout << "vec1.begin()--vec1.end():" << endl;
for(i=vec1.begin(); i!=vec1.end(); ++i)
cout << *i << " ";
cout << endl;
//从前向后显示vec2中的数据
cout << "vec2.begin()--vec2.end():" << endl;
for(i=vec2.begin(); i!=vec2.end(); ++i)
cout << *i << " ";
cout << endl;
//从前向后显示vec3中的数据
cout << "vec3.begin()--vec3.end():" << endl;
for(i=vec3.begin(); i!=vec3.end(); ++i)
cout << *i << " ";
cout << endl;
//测试添加和插入成员函数,vector不支持从前插入
vec1.push_back(2); //从后面添加一个成员
vec1.push_back(4);
//在vec1的第一个位置上插入5
vec1.insert(vec1.begin()+1, 5);
//从vec1第一的位置开始插入vec3的所有成员
vec1.insert(vec1.begin()+1, vec3.begin(), vec3.end());
cout << "after push() and insert() now the vec1 is: ";
for(i=vec1.begin(); i!=vec1.end(); ++i)
cout << *i << " ";
cout << endl;
//测试赋值成员函数,重新给vec2赋值,8个成员的初始值为1
vec2.assign(8, 1);
cout << "vec2.assign(8, 1): " << endl;
for(i=vec2.begin(); i!=vec2.end(); ++i)
cout << *i << " ";
cout << endl;
//测试引用类函数,vec1第零个成员
cout << "vec1.front()=" << vec1.front() << endl;
//vec1的最后一个成员
cout << "vec1.back()=" << vec1.back() << endl;
//vec1的第五个成员
cout << "vec1.at(4)=" << vec1.at(4) << endl;
cout << "vec1[4]=" << vec1[4] << endl;
//测试移出和删除,将最后一个成员移出vec1
vec1.pop_back();
//删除成员
vec1.erase(vec1.begin()+1, vec1.end()-2);
//显示序列的状态信息
cout << "vec1.pop_back() and vec1.erase():" << endl;
for(i=vec1.begin(); i!=vec1.end(); ++i)
cout << *i << " ";
cout << endl;
//打印成员个数
cout << "vec1.size()=" << vec1.size() << endl;
//清空
cout << "vec1.empty():" << vec1.empty() << endl;
return 0;
}

#include<iostream>
#include<vector>
#include<string>
#include<algorithm>
using namespace std;
int main()
{
vector<string> sentence;
sentence.reserve(5); //为五个元素预留内存以避免重新分配
//添加元素
sentence.push_back("Hello, ");
sentence.push_back("how");
sentence.push_back("are");
sentence.push_back("you");
sentence.push_back("?");
vector<string>::iterator it;
for(it=sentence.begin(); it<sentence.end(); it++)
cout << *it << " ";
cout << endl;
cout << "max_size(): " << sentence.max_size() << endl;
cout << "size(): " << sentence.size() << endl;
cout << "capacity(): " << sentence.capacity() << endl;
//交换第二个和第四个元素
swap(sentence[1],sentence[3]);
//插入
sentence.insert(find(sentence.begin(),sentence.end(),"?"),"always");
sentence.back()="!";
for(it=sentence.begin(); it<sentence.end(); it++)
cout << *it << " ";
cout << endl;
cout << "max_size(): " << sentence.max_size() << endl;
cout << "size(): " << sentence.size() << endl;
cout << "capacity(): " << sentence.capacity() << endl;
return 0;
}

四.List容器
- 简介
(1)list容器类使用双向链表管理元素,不支持随机存取(无下标) 。
(2)list容器类的元素可以是任意类型T,但需定义赋值和拷贝功能。
(3)list容器类的元素只能用迭代器访问。
(4)头文件#include<list>
- 操作
(1)构造,析构
(2)非变动操作
(3)赋值操作
(4)元素存取
(5)插入删除元素
(6)其他特殊操作
#include <iostream>
#include <list>
using namespace std;
int main(){
list<char> coll;
//append elements from 'a' to 'z'
for(char c='a'; c<='z'; ++c)
coll.push_back(c);
list<char>::const_iterator pos;
for(pos=coll.begin(); pos!=coll.end(); ++pos)
cout << *pos << ' ';
cout << endl;
return 0;
}

#include <iostream>
#include <list>
#include <algorithm>
using namespace std;
void printLists(const list<int>& l1, const list<int>& l2){
list<int>::const_iterator it;
cout << "list1: ";
for(it=l1.begin(); it!=l1.end(); it++)
cout << *it << " ";
cout << endl << "List2: ";
for(it=l2.begin(); it!=l2.end(); it++)
cout << *it << " ";
cout << endl << endl;
}
int main(){
list<int> list1, list2;
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(), 3), list1);
printLists(list1, list2);
//move first element to the end
list2.splice(list2.end(), list2, list2.begin());
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;
}

五.Stack容器
- 简介
(1)后进先出。
(2)不支持迭代器。
(3)头文件#include<stack>
- 操作
(1)push(value) :将元素压栈
(2)top() :返回堆栈顶元素,但不删除
(3)pop() :删除栈顶元素,但不返回
(4)size() :返回堆栈元素个数
(5)empty() :判断容器是否为空
#include <iostream>
#include <stack>
using namespace std;
int main(){
stack<int> st;
//push three elements into the stack
st.push(1);
st.push(2);
st.push(3);
//top and pop
cout << st.top() << ' ';
st.pop();
cout << st.top() << ' ' << endl;
st.pop();
//modify
st.top() = 77;
//push
st.push(4);
st.push(5);
//only pop
st.pop();
//top, pop and cout
while(!st.empty()){
cout << st.top() << ' ';
st.pop();
}
cout << endl;
return 0;
}

六.Queue容器
- 简介
(1)先进先出
(2)不支持迭代器
(3)头文件#include<queue>
- 操作
(1)push(value) :将元素置入队列
(2)front() :返回队列头部元素,但不删除
(3)back() :返回队列尾部元素,但不删除
(4)pop() :删除队列头部元素,但不返回
(5)size() :返回堆栈元素个数
(6)empty() :判断容器是否为空
#include <iostream>
#include <queue>
#include <string>
using namespace std;
int main(){
queue<string> q;
//push
q.push("These ");
q.push("are ");
q.push("more than ");
//front and pop
cout << q.front();
q.pop();
cout << q.front();
q.pop();
//push
q.push("four ");
q.push("words!");
//pop to skip
q.pop();
cout << q.front();
q.pop();
cout << q.front() << endl;
q.pop();
//size
cout << "Number of elements in the queue: " << q.size() << endl;
return 0;
}

七.Map容器
- 简介
(1)Map是STL的一个关联容器,它提供一对一(其中第一个可称为关键字,每个关键字只能在map中出现一次,第二个可称为该关键字的值)的数据处理能力。
(2)支持迭代器
(3)头文件#include<map>
- 操作
(1)clear() :将一个map容器的全部元素删除
(2)erase(关键字值) :通过关键字删除元素
(3)count(关键字值) :返回对应某个关键字的元素个数
(4)find(关键字值) :返回指向对应某个关键字的元素的迭代器
(5)insert() :将一个或多个元素插入容器
(6)size() :返回map容器元素个数
(7)empty() :判断map是否为空
#include <iostream>
#include <map>
#include <string>
using namespace std;
int main(){
map<int, string> mapStudent;
pair<map<int, string>::iterator ,bool> Insert_Pair;
//first method of insert
Insert_Pair = mapStudent.insert(pair<int, string>(1, "student_one"));
if(Insert_Pair.second==true)
cout << "Insert successfully" << endl;
else
cout << "Insert Failure" << endl;
//second method of insert
mapStudent.insert(map<int, string>::value_type(2, "student_two"));
//third method of insert
mapStudent[3] = "student_three";
map<int, string>::iterator iter;
iter = mapStudent.find(1);
if(iter!=mapStudent.end())
cout << "Find, the value is " << iter->second << endl;
else
cout << "Do not find" << endl;
for(iter=mapStudent.begin(); iter!=mapStudent.end(); iter++)
cout << iter->first << " " << iter->second << endl;
return 0;
}

八.STL算法
- 简介
(1)STL以函数模板的形式提供了一些标准算法来处理容器内的元素
(2)算法通过迭代器来处理容器中的元素,所有算法的前两个参数都是一对iterators:[first, last),用来指出容器内一个半开区间范围内的元素
(3)头文件#include<algorithm> - 类型
(1)非修改算法
(2)修改算法
(3)删除算法
(4)变异算法
(5)排序算法
用于排序区间的算法:
(6)数字算法
- sort()算法
STL中的sort算法根据排序元素的多少自动选择插入排序或者快速排序算法,它是一个函数模板,sort(begin, end, cmp),三个参数的意义为:
- 第一个参数为首个元素的迭代器位置,可以是数组的首地址。
- 第二个参数为最后一个元素的迭代器位置,可以是数组中最后一个元素的地址。
- 第三个参数为比较函数的地址,表示排序的方法。第三个参数可以缺省,表示按前面元素小于后面元素的递增方式排序,若元素是用户自定义的类对象则需要在类中以友元或成员函数的形式重载“<”运算符。
- 比较函数的原型为“bool 函数名(T &a, T &b)”,函数返回值表示a元素排在b元素之前的条件。若要递增排序则可表示为当a < b时返回true;若要递减排序则可表示为当a < b时返回false。若元素的类型为用户自定义的类对象,则不能将比较函数定义为类成员函数,只能将其定义为静态成员函数或者是友元函数。
//compare不能定义为Student类的成员函数
bool compare(const Student& s1, const Student& s2){
return s1.name < s2.name; //从小到大排序
}
sort(vector1.begin(), vector1.end, compare); //也可以在类中重载<,实现对Student对象的递增或递减排序
- sort只适用于STL的vector,string和deque容器,不能用于set,map等容器。
- for_each()算法举例
for_each(beginIterator beg, endIterator end, Proc op)
- 对区间[beg, end)中的每一个元素调用op(elem)。
- 返回op之后的容器副本。
- op可以改变元素。
- op的返回值被忽略。
void print(){ ... }
void square(int &n){ n=n*n; }
vector<it> coll;
......INSERT_ELEMENTS(coll, 1, 9);
//call print() for each element
for_each(coll.begin(), coll.end(), print);
for_each(coll.begin(), coll.end(), square);