STL主要包含容器、算法、迭代器三大核心部分
常用的容器和容器适配器对应的头文件,容器适配器可以看做由其他容器实现的容器。关联类容器一是要注意这类容器具有自动排序能力,即它们内部的元素总是时刻自动有序的;二是要注意使用Set(集合) 和Multisets(多重集合)之前,必须先包含头文件<set>,而使用Map 和Multimap之前,必须先包含头文件<map>;三是要注意它们支持双向迭代器,但不支持随即迭代器,因此不能随即存取其元素。
容器类别 | 数据结构(容器类) | 实现头文件 |
序列式容器 | 向量(vector) | <vector> |
双向队列(deque) | <deque> | |
双向链表(list) | <list> | |
关联式容器 | 集合(set)、多重集合(multiset) | <set> |
映射(map)、多重映射(multimap) | <map> | |
容器适配器 | 栈(stack) | <stack> |
队列(queue)、优先级队列(priority_queue) | <queue> |
1、容器
· c1.empty(): 若c1内没有数据元素存在返回true,否则返回false
· c1.max_size(): 返回c1中的最大元素个数
· c1.size(): 返回c1中当前实有元素个数
· c1.swap(c2): 交换c1和c2的元素
(1) vector
vector容器是数组的一个泛化推广。由于vector容器内的数据元素被存放在一块连续的内存里,所以,对vector容器内的数据元素可以通过下标法进行随机访问。
push_back(i)在容器尾端插入新元素i等;
还可以使用它的其它相关成员函数在vector的头部或其它任何位置进行插入、删除操作,如insert()
vector实际上是一个动态数组,具有内存自动管理功能。
声明初始化的方法:
vector<elementType> vecList; | 创建一个没有任何元素的空向量vecList(使用默认构造函数) |
vector<elementType> vecList(otherVecList) | 创建一个向量vecList,并使用向量otherVecList中的元素初始化该向量。向量vecList与向量otherVecList的类型必须相同 |
vector<elementType> vecLIst(size); | 创建一个大小为size的向量vecList,并使用默认构造函数初始化该向量 |
vector<elementType> vecList(n,elem); | 创建一个大小为n的向量vecList,该向量中所有的n个元素都初始化为elem |
vector<elementType> vecList(begin,end); | 创建一个向量vecList,以区间(begin,end)做为元素的初值。 |
操作类型 | 成员函数 | 作 用 |
删除 | vecList.clear() | 从容器中删除所有元素 |
vecList.erase(position) | 删除由position指定位置上的元素 iterator! | |
vecList.erase(beg, end) | 删除从beg到end-1区间内的所有元素 | |
vecList.pop_back() | 删除最后一个元素 | |
插入 | vecList.insert(position, elem) | 将elem的一个副本插入到由position指定的位置上,并返回新元素的位置 |
vecList.insert(position, n, elem) | 将elem的n个副本插入到由 position指定的位置上 | |
vecList.insert(position, beg, end) | 将从beg到end-1之间的所有元素的副本插入到vecList中由position指定的位置上 | |
vecList.push_back(elem) | 将elem的一个副本插入到向量容器的末尾 | |
重置大小 | vecList.resize(num) | 将元素个数改为num。如果size()增加,默认的构造函数负责创建这些新元素 |
vecList.resize(num, elem) | 将元素个数改为num。如果size()增加,默认的构造函数将这些新元素初始化为elem |
迭代器:
vector<int>::iteratorintVeciter;
++intVecIter 将迭代器intVecIter前移一个位置,使其指向容器中的下一个元素;
--intVecIter 将迭代器intVecIter后移一个位置,使其指向容器中的前一个元素;
*intVecIter 返回当前迭代器位置上的元素值。
容器的成员函数begin()和end()
(2)Deque
Deque(发音类似“deck”)是“double-ended queue” 的缩写,即 “双端队列”。可以在其头尾两端插入或删除元素,而且十分迅速。而在头部和中间部分插入或删除元素则要移动元素,所以比较费时。deque由动态分配的连续空间组合而成,随时可以增加一段新的空间链接起来。它没有必要像vector那样“因旧空间不足而重新分配2倍的空间,然后复制元素,再释放旧空间”。
函 数 | 描 述 | 备注 |
assign(beg,end) assign(n,elem) | 给[beg; end) 区间赋值 将n个elem 的拷贝赋值 |
|
at(idx) | 传回索引 idx 所指的数据,若idx 越界,抛出out_of_range |
|
back() | 传回最后一个数据,不检查这个数据是否存在 |
|
begin() | 传回迭代器重的可一个数据 |
|
clear() | 移除容器中所有数据 |
|
deque c1(c2) deque c(n) deque c(n, elem) deque c(beg,end) ~deque() | 复制一个deque 创建一个deque,含有n个数据,数据均已缺省构造产生 创建一个含有n个elem 拷贝的 deque 创建一个以[beg;end)区间的 deque 销毁所有数据,释放内存 | 构造函数 构造函数 构造函数 构造函数 析构函数 |
empty() | 判断容器是否为空 |
|
end() | 指向迭代器中的最后一个数据地址 |
|
erase(pos) erase(beg,end) | 删除pos位置的数据,传回下一个数据的位置 删除[beg,end)区间的数据,传回下一个数据的位置 |
|
front() | 传回地一个数据 |
|
get_allocator | 使用构造函数返回一个拷贝 |
|
insert(pos,elem) insert(pos,n,elem) insert(pos,beg,end) | 在pos位置插入一个elem拷贝,传回新数据位置 在pos位置插入n 个elem数据,无返回值 在pos位置插入在[beg,end)区间的数据,无返回值 |
|
max_size() | 返回容器中最大数据的数量 |
|
pop_back() | 删除最后一个数据 |
|
pop_front() | 删除头部数据 |
|
push_back(elem) | 在尾部加入一个数据 |
|
push_front(elem) | 在头部插入一个数据 |
|
rbegin() | 传回一个逆向队列的第一个数据 |
|
rend() | 传回一个逆向队列的最后一个数据的下一个位置 |
|
resize(num) | 重新指定队列的长度 |
|
size() | 返回容器中实际数据的个数 |
|
c1.swap(c2) swap(c1,c2) | 将 c1 和 c2 元素互换 同上操作 |
|
operator [] | 返回容器中指定位置的一个引用 |
|
(3)list
List是(带头结点的)双向链表(doublelinked list),它是一种双线性列表。只能顺序访问它(从前向后或者从后向前逐个访问)。它不支持随机访问,要访问list中某个数据元素只能从表头或表尾处开始循环进行(可以通过迭代器来双向遍历读取)
list容器不提供对capacity()和内存维护相关的接口,因为list容器中的每个元素分配自己的内存空间,当元素删除时,其对应的内存空间自动销毁。List的优势是可以在其任何位置上插入或删除元素,而且比较迅速(不需要移动元素)。
成员函数如下:
assign()分配值,有两个重载L1.assign(4,3); // L1(3,3,3,3) L1.assign(++list1.beging(), list2.end()); //L1(2,3)
operator= 赋值重载运算符
front()返回第一个元素的引用
back()返回最后一元素的引用
begin()返回第一个元素的指针(iterator)
end()返回最后一个元素的下一位置的指针(list为空时end()=begin())
rbegin()返回链表最后一元素的后向指针(reverse_iteratoror const)
rend()返回链表第一元素的下一位置的后向指针
push_back()增加一元素到链表尾
push_front()增加一元素到链表头
pop_back()删除链表尾的一个元素
pop_front()删除链表头的一元素
clear()删除所有元素
erase()删除一个元素或一个区域的元素(两个重载函数)list1.erase(list1.begin()); list1.erase(++list1.begin(),list1.end()); // list1(1)
remove(val): 删除容器c中所有值为val的元素
c.remove_if(op):删除容器c中所有使op为true的元素
// 小于2的值删除
bool myFun(const int& value) { return (value < 2);}
list1.remove_if(myFun); // list1(3)
empty()判断是否链表为空
max_size()返回链表最大可能长度
size()返回链表中元素个数
resize()重新定义链表长度(两重载函数)
reverse()反转链表
sort()对链表排序,默认升序(可自定义回调函数)
merge()合并两个有序链表并使之有序
insert()在指定位置插入一个或多个元素(三个重载函数)
swap()交换两个链表(两个重载)
c.unique(): 删除容器中值相同位置相邻的额外元素,只保留一个元素
c.unique(op): 删除容器中同时满足op条件位置相邻的额外元素,只保留一个元素
(4)set和multiset
一个集合(set)是一个容器,其所包含的元素的值是唯一的,而Multisets所包含的元素的值可以不唯一(即可以有重复元素)。注意,集合(set)与多重集合(Multisets)的内部数据组织是一颗红黑树(一种非严格意义上的平衡二叉树),这颗树具有对数据自动排序的功能,因此,set和Mutilset内部的所有数据元素是自动有序的。
Ø 插入元素i:intSet.insert(i);
Ø 删除元素i(如果存在):intSet.erase(i);
Ø 判断元素i是否属于集合: if (intSet.find(i) != intSet.end()) ...
Ø 返回集合元素的个数:intSet.size();
Ø 判断集合是否空:bool empty() const;
Ø 将集合清为空集:intSet.clear()。
如何判断一个元素是否在Set中?
用成员函数find()来定位数据元素出现位置,它返回一个迭代器,当set中包含该数据元素时,返回数据元素所在位置的迭代器;如果不包含,返回的迭代器等于end
遍历方面的成员函数
·iterator begin(); //返回首元素的迭带器指针
·iterator end(); //返回尾元素后的迭带器指针,而不是尾元素的迭带器指针
·reverse_iterator rbegin(); //返回尾元素的逆向迭带器指针,用于逆向遍历容器
·reverse_iterator rend(); //返回首元素前的逆向迭带器指针,用于逆向遍历容器
其它操作方面的成员函数
·const_iteratorlower_bound(const Key& key); //返回容器元素等于key迭代指针,//否则返回end()
·const_iteratorupper_bound(const Key& key);
·int count(const Key&key) const; //返回容器中元素值等于key的元素个数
·pair<const_iterator ,const_iterator> equal_range(const Key& key) const; // 返回//容器中元素值等于key的迭代指针[first, last)
·const_iterator find(constKey& key) const; //查找功能返回元素值等于key迭代器指针
·void swap(set& s); //交换单集合元素
·void swap(multiset& s); //交换多集合元素
集合的算法
STL中的算法包含在<algorithm> 头文件中,集合的算法也包含在该头文件中。
Ø 集合的并:set_union
Ø 集合的交:set_intersection
Ø 集合的差:set_difference
(5)maps和multimap
map内部数据的组织也是一棵红黑树,所以map内部所有的数据元素都是自动有序的。
结构体pair与函数make_pair(),它们定义在通用工具头文件<utility>内,Pair的用途是将2个数据构造为一个数据元素(通过其构造函数)。如STL中的容器map就是将key和value放在一起作为一个元素来保存的。pair的另一个应用是,当一个函数需要返回2个值的时候,可以选择pair这种数据类型。pair的实现是一个结构体,主要的两个成员变量是first 和second。std::make_pair(42,‵@′);与std::pair<int, char>(42,‵@′);都是返回一个由(42, ‵@′)组成的数对(42,‵@′),显然,std::make_pair(42,‵@′)更简便,而pair在有些编译器下不允许这么简便写。
map<int, char*> mapStudent;
数据的插入的三种方法
第一种方法:用insert函数插入pair数据
mapStudent.insert(pair<int, char*>(1,“student_one”));
第二种方法:用insert函数插入value_type数据
mapStudent.insert(map<int,char*>::value_type(1, “student_one”));
第三种方法:用数组方式插入数据
mapStudent[1]= “student_one”;
mapStudent[2]= “student_two”;
数据的删除
//如果要删除数据元素1,用迭代器删除
map<int,string>::iterator iter;
iter =mapStudent.find(1);
mapStudent.erase(iter);
数据的查找
第一种方法:用count函数
第二种方法:用find函数
数据的其它基本操作
Ø 返回map元素的个数: mapStudent.size();
Ø 将map清为空集:mapStudent.clear() ;
Ø 判断map是否为空:mapStudent.Empty() ;
Ø 数据的遍历:比如用数组方式
int nSize =mapStudent.size();
for(int nIndex = 0; nIndex < nSize; nIndex++)
{
cout<<mapStudent[nIndex]<<end;
}//结果由小到大
(6)stack
Stack容器是一个先进后出(FILO)的数据结构,值得注意的是迭代器不能在堆栈中使用,因为只有栈顶的元素才可以访问。
构造函数
构造函数用于声明一个堆对象,如:
stack(); //声明一个空栈
stack(copy); //用一个栈对象copy初始化新栈
stack<int> s1;
stack<string> s2;
stack模板类需要2个模板参数,第一个为元素类型,第二个为容器类型。其中元素类型是必要的。而容器类型缺省时,默认为deque。
成员函数
empty() 语法: bool empty();
pop() 语法: void pop(); 功能: 退栈。pop() 函数移除栈顶元素。
push(x) 语法: void push( const TYPE &val );功能: push(x) 函数将x压栈,使其成为栈顶元素。
size()语法: int size();功能:size()函数返当前堆栈中的元素数目。
读取栈顶元素top()语法: TYPE & top();功能:top() 函数栈顶元素的引用。
(7)Queue
①push(): //将一个新元素加入到队列的末端;
②pop(): //弹出队列中的第一个元素,返回的是一个void;
③front(): //存取队列中的第一个元素,返回的是一个引用;
④back(): //存取队列中的最后一个元素,返回的是一个引用;
⑤empty(): //测试队列是否为空;
⑥size(): //获得队列中元素的个数;
(8)优先级Queue
priority_queue也是一个队列,不过该模版类可以保证每次通过pop(出队)从它里面取得的元素都是剩下元素中优先级最高的,在每次通过push(入队)添加元素时,整个序列都会在必要时进行重排,它使用堆算法保持序列的有序化。使用priority_queue时必须包含头文件<queue>,并使用统一命名空间。
(9)String
操作接口示例 s1、s2均为string对象 | 说 明 |
s1=s2 | 将s2的副本赋值给s1 |
s1.empty() | 如果s1为空串,返回true,否则返回false |
s1.size() | 返回s1中字符的个数 |
s1[n] | 返回s1中位置为n的字符,位置从0开始计 |
==,!=,<,<=,>,>=, | 关系运算符保持原有的含义 |
s1+=s2或s1=s1+s2 | 将s2表示的串追加到s1的后面形成新串 |
s1.insert(pos, s2) | 在下标为pos的元素前插入s2表示的串 |
s1.insert(pos, cp, len) | 在下标为pos的元素前插入cp所指串的前n个字符 insert操作还有很多用法,在这里不再一一列举 |
s1.c_str() | 返回s1表示的串的首地址 |
s1.substr(pos, n); | 返回一个string类型的字符串,包含s1中从下标pos开始连续n个字符 |
s1.append(s2) | 将s2表示的串追加到s1的后面形成新串 |
s1.append(cp) | 将字符指针cp指向的串追加到s1的后面形成新串 |
s1.replace(pos, len, s2) | 删除s1中从下标pos开始的len个字符,并用s2替换之 |
s1.find(s2, pos) | 从s1下标为pos的位置开始查找s2,找到后返回s2第一次出现的位置,若没找到,返回值string::npos |
s1.rfind(s2, pos) | 从s1下标为pos的位置开始查找s2,找到后返回s2最后一次出现的位置,若没找到,返回值string::npos |
s1.find_first_of(s2,pos) | 从s1下标为pos的位置开始查找s2中的任意字符,找到后返回第一次出现的位置。 |
s1.find_last_of(s2,pos) | 从s1下标为pos的位置开始查找s2中的任意字符,找到后返回最后一次出现的位置。 |