STL容器使用总结
摘要:STL容器的简单总结 一、基本概念 容器(containers)即物之所在,它是STL的核心部件之一,是迭代器的依附,是算法作用的目标。 实际开发过程中,由于时间的约束和对效率的追求,数据结构的选择非常重要。但是我们常常重复着一些为了实现向量、链表等结构而编写的代码,不仅浪费了时间,更是增加了出错的可能性。STL容器就为我们提供了很大的方便,它允许我们重复利用已有的实现构造自己的特定类型下的数据结构。通过设置一些模板类,S
STL容器的简单总结
一、基本概念
容器(containers)即物之所在,它是STL的核心部件之一,是迭代器的依附,是算法作用的目标。
实际开发过程中,由于时间的约束和对效率的追求,数据结构的选择非常重要。但是我们常常重复着一些为了实现向量、链表等结构而编写的代码,不仅浪费了时间,更是增加了出错的可能性。STL容器就为我们提供了很大的方便,它允许我们重复利用已有的实现构造自己的特定类型下的数据结构。通过设置一些模板类,STL容器对最常用的数据结构提供了支持,这些模板的参数允许我们指定容器中元素的数据类型,可以将我们许多重复而乏味的工作简化。
二、容器分类与成员简介
容器主要分为序列式容器(Sequence Container)和关联式容器(Associative Container),适配器容器是对序列容器或关联容器进行包装而得到的一种具有更多约束力(或功能更强大)的容器。
1、序列式容器
其中的元素时可序的,即元素集合呈线性关系,包括向量(vector)、双端队列(deque)和双向链表(list):
①Vector:将元素置于一个动态数组中加以管理(连续存储结构,每个元素在内存上连续)。可以随机存取元素(用索引直接存取),数组尾部添加或移除元素非常快速,但是在其它位置安插或删除元素比较费时;
②Deque:将元素置于两级数组结构中进行管理,第一级类似于vector,另一极维护容器的首位地址。除了有vector的功能,还支持高效的首端插入/删除操作,但是在中部安插或删除元素比较费时;
③List:非连续性存储结构,每个元素维护一对前向、后向指针,支持前向和后向遍历,不提供随机存取(按顺序走到需存取的元素,O(n)),在任何位置上执行插入或删除动作都非常迅速,内部只需调整一下指针。
2、关联式容器
通过键值对的方式存储数据,可以通过键来读取数据,包括集合(set)、多重集合(multiset)、映射(map)和多重映射(multimap):
①Set/Multiset:内部的元素依据其值自动排序,Set内的相同数值的元素只能出现一次,Multiset内可包含多个数值相同的元素,内部由二叉树实现,便于查找;
②Map/Multimap:内部的元素是成对的键值/实值,内部的元素依据其键值自动排序,Map内的相同键值的元素只能出现一次,即一个键值只保留一个元素,Multimap内可包含多个数值相同的元素,即一个键值可保留多个元素,内部由二叉树实现,便于查找。
三、容器成员的使用
- Vector
(1)头文件包含:#include
(2)对象定义与初始化
vector vec1; // vec1保存类型为type的对象,默认构造函数,vec1为空
vector vec2(size); // vec2含有值初始化的元素的size个副本
vector vec3(size, value); // vec3包含值为value的size个元素
vector vec4(myvector); // vec4是myvector的一个副本,拷贝构造
vector vec5(first, last); // 用迭代器first和last之间的元素创建vec5
vector vec6 ={num1, num2}; //用num1,num2初始化vec6
(3)元素增加
Vectora;
尾部增加:a.push_back(1);
a.insert(a.end(), 2);
头部增加:a.insert(a.begin(),3);
指定位置插入:a.insert(pos, 4),其中pos需要用迭代器确定位置
注意:vector是一种向后扩充的容器,没有push_front(),也没有pop_front()
(4)元素删除
尾部删除:a.pop_back();
指定位置删除:a.erase(pos);
注意:无pop_front()
(5)元素改变
下标法:a[pos]=5;
Assign: 开辟新地址存放新元素
① a.assign(6, 7), 其中6表示元素个数,7表示要初始化的值;
② a.assign({8, 9, 10}),用8,9, 10重新初始化a;
③ int arr[]={11, 12, 13, 14, 15, 16}; a.assign(arr, arr+3); 则a[0]=11,a[1]=12,a[2]=13;
④ 用迭代器作参数,a.assign(iter, iter+3), 表示用迭代器范围内的数初始化a
(6)元素查找
vector::iterators=find(a.begin(),a.end(),50);//查找值为50的元素的个数;
(7)对象释放
a.clear();//清除所有元素
注意: 该操作使a.size()为0,但是a.capacity()大小不变(a.size()表示实际容器中保存元素的个数,a.capacity()表示在发生重新分配之前允许存放多少元素),即不可以用a[0]=1的方式赋值,可以用a.push_back(1)方式赋值。
- Deque:
(1)头文件包含:#include
(2)对象定义与初始化
deque deq 创建一个空的deque,类型为type
deque deq1(deq2) 复制一个deque。
deque deq3(n) 创建一个deque,含有n个数据,数据均已缺省构造产生。
deque deq4(n, elem) 创建一个含有n个elem拷贝的deque
deque deq5(beg,end) 创建一个以[beg;end)区间的deque
(3)元素增加
在尾部插入: deq.push_back(element);
在头部插入:deq.push_front(element);
指定位置插入元素:deq.insert(deq1.begin()+3, element);
(4)元素删除
弹尾元素: deq.pop_back();
弹头元素: deq.pop_front();
删除指定位置元素:deq.erase(deq1.begin()+3);
(5)元素改变
deque 的成员函数 assign() 可以替换现有的所有元素
如:
deque words {“one”, “two”, “three”, “four”};
words.assign({"seven”,“eight”,“nine”});//之后words含有”seven”,“eight”,"nine”三个元素
(6)元素查找
find(deq.begin(), deq.end(), value)//寻找值为value的元素
(7)对象释放
deq.clear();//清除所有元素
- List
(1)头文件包含:#include
(2)对象定义与初始化
list< type > list1; //定义一个空的链表
list< type > list2(count); //建一个含count个默认值是0的元素的链表
list< type > list3(count, info); //建一个含count个默认值是info的元素的链表
list< type > list(list2); //建一个的copy链表
list< type > list(list2.begin(),list2.end()); //含区间的元素[first,last]
(3)元素增加
list.push_back(info); //将会添加到末尾
list< type >::iterator iter; iter = list.insert(iter , info);// 插入后iter指向新插入的元素。
(4)元素删除
list.pop_back();//删除最后一个元素
(5)元素改变
list< type >list1;
list< type >list2;
list2.assign(list1.begin(), list1.end()); //用list1对list2进行元素重置
(6)元素查找
list< type >::iterator iter;
iter=find(list.begin(), list.end(), value)
(7)对象释放
list.clear();
- Set
(1)头文件包含:#include
(2)对象定义与初始化
①set<int,less > set1;
less是一个标准类,用于形成升序排列函数对象。降序排列是用greater。
②set<int ,less >set2(vector1.begin(),vector1.end());
通过指定某一预先定义的区间来初始化set对象的构造函数。
③set<int ,less >set3(set2);
复制构造函数。
(3)元素增加
方式1:pair<iterator,bool> insert (const value_type& val);
①返回一个pair,pair里面包含两种数据类型,一个是迭代器,一个是bool类型;
②pair的第一个参数为该set的迭代器,表示如果插入一个set里面不存在的数据,则迭代器指向这个新增结点,如果插入一个set里面已经存在的数据,则迭代器指向已经存在的数据;
③pair的第二个参数为bool类型,表示如果是true,则数据成功插入,如果为false则表示插入的数据已经存在。
方式2:在某个位置上插入一个数据,iterator insert (iterator position, const value_type& val);
方式3:将一个区间的数据插入
template
void insert (InputIterator first, InputIterator last);
(4)元素删除
删除某个位置:set1.erase(set1.find(5));
注意:如果利用该方式删除一个不存在的数据,应该要加判断
删除某个值(相当于Remove):size_type erase (const value_type& val);
删除某个区间:void erase (iterator first, iterator last);
利用该方式删除的是一个左闭右开的区间;(即last表示最后一个删除数据的下一个位置);
(5)元素查找
iterator find (const value_type& val) const;
(6)对象释放
set.clear();
- Map
(1)头文件包含:#include
(2)对象定义与初始化
map<class T1, class T2>
map(); // 默认构造函数
map(const map& m) // 拷贝构造函数
map(iterator begin, iterator end ); //区间构造函数
map(iterator begin, iterator end, const traits& _compare) //带比较谓词的构造函数
map(iterator begin, iterator end, const traits& _compare, const allocator& all) //带分配器
(3)元素增加
①用insert方法插入pair对象:
enumMap.insert(pair<int, String>(1, “One”));
②用insert方法插入value_type对象:
enumMap.insert(map<int, String>::value_type (1, “One”));
③用数组方式插入值:
enumMap[1] = “One”;
enumMap[2] = “Two”;
(4)元素删除
erase(iterator it); //通过一个条目对象删除
erase(iterator first, iterator last); //删除一个范围
erase(const Key& key); //通过关键字删除
(5)元素改变
pos= enumMap.find(old_key);
enumMap.insert( new_key,pos->second);
(6)元素查找
String tmp = enumMap[2]; //查找键“2”对应的值
map<int, CString> ::iterator it= enumMap.find(2);//查找键“2”对应的元素位置
(7)对象释放
enumMap.clear();