STL不同容器的使用方法
以下内容摘自:http://blog.csdn.net/u014465639/article/details/70241850
1、vector(需要导入头文件#include <vector>)
①定义与初始化
如果没有指定元素的初始化式,那么标准库将自行提供一个元素初始值进行,具体值为何,取决于存储在vector 中元素的数据类型;如果为int型数据,那么标准库将用 0 值创建元素初始化式;如果 vector 保存的是含有构造函数的类类型(如 string)的元素,标准库将用该类型的默认构造函数创建元素初始化式;元素类型可能是没有定义任何构造函数的类类型。这种情况下,标准库仍产生一个带初始值的对象,这个对象的每个成员进行了值初始化。
vector<int> vec1; //默认初始化,vec1为空 vector<int> vec2(vec1); //使用vec1初始化vec2 vector<int> vec3(vec1.begin(),vec1.end());//使用vec1初始化vec2 vector<int> vec4(); //10个值为0的元素 vector<int> vec5(,); //10个值为4的元素 vector<string> vec6(,"null"); //10个值为null的元素 vector<string> vec7(,"hello"); //10个值为hello的元素
②常用的操作方法
vec1.push_back(); //添加元素 int size = vec1.size(); //元素个数 bool isEmpty = vec1.empty(); //判断是否为空 cout<<vec1[]<<endl; //取得第一个元素 vec1.insert(vec1.end(),,); //从vec1.back位置插入5个值为3的元素 vec1.pop_back(); //删除末尾元素 vec1.erase(vec1.begin(),vec1.end());//删除之间的元素,其他元素前移 cout<<(vec1==vec2)?true:false; //判断是否相等==、!=、>=、<=... vector<int>::iterator iter = vec1.begin(); //获取迭代器首地址 vector<int>::const_iterator c_iter = vec1.begin(); //获取const类型迭代器 vec1.clear(); //清空元素
- 反向迭代器的概念点此进入
③遍历方法
//下标法(vector的特有访问方法,一般容器只能通过迭代器访问)
int length = vec1.size();
for(int i=;i<length;i++)
{
cout<<vec1[i];
}
cout<<endl<<endl;
//迭代器法
vector<int>::const_iterator iterator = vec1.begin();
for(;iterator != vec1.end();iterator++)
{
cout<<*iterator; }
2、list(需要导入头文件#include <list>)
①定义与初始化
list<int> lst1; //创建空list list<int> lst2(); //创建含有三个元素的list list<int> lst3(,); //创建含有三个元素的值为2的list list<int> lst4(lst2); //使用lst2初始化lst4 list<int> lst5(lst2.begin(),lst2.end()); //同lst4
②常用的操作方法
lst1.assign(lst2.begin(),lst2.end()); //分配值 lst1.push_back(); //添加值 lst1.pop_back(); //删除末尾值 lst1.begin(); //返回首值的迭代器 lst1.end(); //返回尾值的迭代器 lst1.clear(); //清空值 bool isEmpty1 = lst1.empty(); //判断为空 lst1.erase(lst1.begin(),lst1.end()); //删除元素 lst1.front(); //返回第一个元素的引用 lst1.back(); //返回最后一个元素的引用 lst1.insert(lst1.begin(),,); //从指定位置插入3个值为2的元素 lst1.rbegin(); //返回第一个元素的前向指针 lst1.remove(); //相同的元素全部删除 lst1.reverse(); //反转 lst1.size(); //含有元素个数 lst1.sort(); //排序 lst1.unique(); //删除相邻重复元素
③遍历方法
//迭代器法 for(list<int>::const_iterator iter = lst1.begin();iter != lst1.end();iter++) { cout<<*iter; } cout<<endl;
3、deque(需要导入头文件#include <deque>)
deque容器类与vector类似,支持随机访问和快速插入删除,它在容器中某一位置上的操作所花费的是线性时间。与vector不同的是,deque还支持从开始端插入数据:push_front()。其余类似vector操作方法的使用。
4、顺序容器使用方法小结(操作的共同点)
①添加元素
函数名 | 意义 |
c.push_back(t) |
在容器c的尾部添加值为t的元素。返回void 类型 |
c.push_front(t) |
在容器c的前端添加值为t的元素。返回void 类型 只适用于list和deque容器类型。 |
c.insert(p,t) |
在迭代器p所指向的元素前面插入值为t的新元素。返回指向新添加元素的迭代器。 |
c.insert(p,n,t) |
在迭代器p所指向的元素前面插入n个值为t的新元素。返回void 类型 |
c.insert(p,b,e) |
在迭代器p所指向的元素前面插入由迭代器b和e标记的范围内的元素。返回 void 类型 |
//在容器首部或者尾部添加数据
list<int> ilist; ilist.push_back(ix);//尾部添加 ilist.push_front(ix);//首部添加 //在容器中指定位置添加元素 list<string> lst; list<string>::iterator iter = lst.begin(); while (cin >> word) iter = lst.insert(iter, word); // 和push_front意义一样 //插入一段元素 list<string> slist; string sarray[] = {"quasi", "simba", "frollo", "scar"}; slist.insert(slist.end(), , "A");//尾部前添加十个元素都是A list<string>::iterator slist_iter = slist.begin(); slist.insert(slist_iter, sarray+, sarray+);//指针范围添加
②容器大小的操作
函数名 | 意义 |
c.size() |
返回容器c中元素个数。返回类型为 c::size_type |
c.max_size() |
返回容器c可容纳的最多元素个数,返回类型为c::size_type |
c.empty() |
返回标记容器大小是否为0的布尔值 |
c.resize(n) |
调整容器c的长度大小,使其能容纳n个元素,如果n<c.size(),则删除多出来的元素;否则,添加采用值初始化的新元素 |
c.resize(n,t) |
调整容器c的长度大小,使其能容纳n个元素。所有新添加的元素值都为t |
list<int> ilist(, ); ilist.resize(); // 尾部添加五个元素,值都为0 ilist.resize(, -); // 再在尾部添加十个元素,元素为-1 ilist.resize(); // 从尾部删除20个元素③访问元素
函数名 | 意义 |
c.back() |
返回容器 c 的最后一个元素的引用。如果 c 为空,则该操作未定 义 |
c.front() | 返回容器 c 的第一个元素的引用。如果 c 为空,则该操作未定义 |
c[n] |
返回下标为 n 的元素的引用。如果 n <0 或 n >= c.size(),则该操作未定义 只适用于 vector 和 deque 容器 |
c.at(n) |
返回下标为 n 的元素的引用。如果下标越界,则该操作未定义 只适用于 vector 和 deque 容器 |
vector<int> vi; for(int i=;i<;i++)vi.push_back(i); cout<<vi[]<<endl; cout<<vi.at()<<endl; cout<<vi[]<<endl; //越界错误 cout<<vi.at()<<endl;//越界错误
④删除元素
函数名 | 意义 |
c.erase(p) |
删除迭代器p所指向的元素。返回一个迭代器,它指向被删除元素后面的元素。如果p指向容器内的最后一个元素,则返回的迭代器指向容器超出末端的下一位置。如果p本身就是指向超出末端的下一位置的迭代器,则该函数未定义 |
c.erase(b,e) |
删除迭代器b和e所标记的范围内所有的元素。返回一个迭代器,它指向被删除元素段后面的元素。如果e本身就是指向超出末端的下一位置的迭代器,则返回的迭代器也指向容器的超出末端的下一位置 |
c.clear() | 删除容器c内的所有元素。返回void |
c.pop_back() |
删除容器c的最后一个元素。返回void。如果c为空容器,则该函数未定义 |
c.pop_front() |
删除容器c的第一个元素。返回void。如果c为空容器,则该函数未定义 只适用于 list 或 deque 容器 |
//删除第一个或最后一个元素
list<int> li; for(int i=;i<;i++)list.push_back(i); li.pop_front();//删除第一个元素 li.pop_back(); //删除最后一个元素 //删除容器内的一个元素 list<int>::iterator iter =li.begin(); if(iter!= li.end())li.erase(iter); //删除容器内所有元素 li.clear();
⑤赋值与swap
函数名 |
意义 |
c1 = c2 |
删除容器c1的所有元素,然后将c2的元素复制给c1。c1和c2的类型(包括容器类型和元素类型)必须相同 |
c1.swap(c2) |
交换内容:调用完该函数后,c1中存放的是 c2 原来的元素,c2中存放的则是c1原来的元素。c1和c2的类型必须相同。该函数的执行速度通常要比将c2复制到c1的操作快 |
c.assign(b,e) |
重新设置c的元素:将迭代器b和e标记的范围内所有的元素复制到c中。b和e必须不是指向c中元素的迭代器 |
c.assign(n,t) | 将容器c重新设置为存储n个值为t的元素 |
list<string> sl1,sl2;
for(int i=;i<;i++)
sl2.push_back("a");
sl1.assign(sl2.begin(),sl2.end());//用sl2的指针范围赋值,sl1中十个元素都为a
sl1.assign(, "A"); //s1被重新赋值,拥有十个元素,都为A
vector<string> vs1(); // vs1有3个元素
vector<string> vs(); // vs2有5个元素
vs1.swap(vs2);//执行后,vs1中5个元素,而vs2则存3个元素。
5、map(需要导入头文件#include <map>)
C++中map容器提供一个键值对(key/value)容器,map与multimap差别仅仅在于multiple允许一个键对应多个值。对于迭代器来说,可以修改实值,而不能修改key。Map会根据key自动排序。
map 是键-值对的集合。map 类型通常可理解为关联数组:可使用键作为下标来获取一个值,正如内置数组类型一样。而关联的本质在于元素的值与某个特定的键相关联,而并非通过元素在数组中的位置来获取。
①定义与初始化
map<int,string> map1; //空map
函数名 | 意义 |
map<k, v>m |
创建一个名为m的空map对象,其键和值的类型分别为k和v |
map<k, v> m(m2) |
创建m2的副本m,m与m2必须有相同的键类型和值类型 |
map<k, v> m(b, e) |
创建map类型的对象m,存储迭代器b和e标记的范围内所有元素的副本。元素的类型必须能转换为pair<const k, v> |
在使用关联容器时,它的键不但有一个类型,而且还有一个相关的比较函数。所用的比较函数必须在键类型上定义严格弱排序(strict weak ordering):可理解为键类型数据上的“小于”关系,虽然实际上可以选择将比较函数设计得更复杂。
对于键类型,唯一的约束就是必须支持 < 操作符,至于是否支持其他的关系或相等运算,则不作要求。
②常用的操作方法
添加元素有两种方法:1、先用下标操作符获取元素,然后给获取的元素赋值 2、使用insert成员函数实现
下标操作添加元素:如果该键已在容器中,则 map 的下标运算与 vector 的下标运算行为相同:返回该键所关联的值。只有在所查找的键不存在时,map 容器才为该键创建一个新的元素,并将它插入到此 map 对象中。此时,所关联的值采用值初始化:类类型的元素用默认构造函数初始化,而内置类型的元素初始化为 0。
insert 操作:
函数名 | 意义 |
m.insert(e) |
e是一个用在m上的value_type 类型的值。如果键(e.first不在m中,则插入一个值为e.second 的新元素;如果该键在m中已存在,则保持m不变。该函数返回一个pair类型对象,包含指向键为e.first的元素的map迭代器,以及一个 bool 类型的对象,表示是否插入了该元素 |
m.insert (beg,end) |
beg和end是标记元素范围的迭代器,其中的元素必须为m.value_type 类型的键-值对。对于该范围内的所有元素,如果它的键在 m 中不存在,则将该键及其关联的值插入到 m。返回 void 类型 |
m.insert (iter,e) |
e是一个用在m上的 value_type 类型的值。如果键(e.first)不在m中,则创建新元素,并以迭代器iter为起点搜索新元素存储的位置。返回一个迭代器,指向m中具有给定键的元素 |
例1:
word_count.insert(map<string, int>::value_type("Anna", ));
word_count.insert(make_pair("Anna", ));//返回false,且键值仍为1.
word_count["Anna"] = ;//键值变为2
insert的返回值:包含一个迭代器和一个bool值的pair对象,其中迭代器指向map中具有相应键的元素,
而bool值则表示是否插入了该元素。如果该键已在容器中,则其关联的值保持不变,返回的bool值为false。
在这两种情况下,迭代器都将指向具有给定键的元素。 例2:
pair<map<string, int>::iterator, bool> ret =
word_count.insert(make_pair(word, )); ret存储insert函数返回的pair对象。该pair的first成员是一个map迭代器,指向插入的键。
ret.first从insert返回的pair对象中获取 map 迭代器;ret.second从insert返回是否插入了该元素。 例3: map1[] = "Saniya"; //添加元素 map1.insert(map<int,string>::value_type(,"Diyabi"));//插入元素 map1.insert(pair<int,string>(,"Siqinsini")); map1.insert(make_pair<int,string>(,"V5")); string str = map1[]; //根据key取得value,key不能修改 map<int,string>::iterator iter_map = map1.begin();//取得迭代器首地址 int key = iter_map->first; //取得key string value = iter_map->second; //取得value map1.erase(iter_map); //删除迭代器数据 map1.erase(); //根据key删除value map1.size(); //元素个数 map1.empty(); //判断空 map1.clear(); //清空所有元素③遍历
map中使用下标存在一个很危险的副作用:如果该键不在 map 容器中,那么下标操作会插入一个具有该键的新元素。所以map 容器提供了两个操作:count 和 find,用于检查某个键是否存在而不会插入该键。
函数名 | 意义 |
m.count(k) |
返回 m 中 k 的出现次数 |
m.find(k) | 如果m容器中存在按k索引的元素,则返回指向该元素的迭代器。如果不存在,则返回超出末端迭代器。 |
例1: int occurs = ;
if (word_count.count("foobar"))occurs = word_count["foobar"];
map<string,int>::iterator it = word_count.find("foobar");
if (it != word_count.end())occurs = it->second; 例2: for(map<int,string>::iterator iter = map1.begin();iter!=map1.end();iter++)
{
int keyk = iter->first;
string valuev = iter->second;
}
④从map对象中删除元素
函数名 | 意义 |
m.erase(k) |
删除m中键为k的元素。返回size_type类型的值,表示删除的元素个数 |
m.erase(p) |
从m中删除迭代器p所指向的元素。p必须指向m中确实存在的元素,而且不能等于m.end()。返回void |
m.erase(b, e) |
从m中删除一段范围内的元素,该范围由迭代器对b和e标记。b和e必须标记m中的一段有效范围:即b和e都必须指向m中的元素或最后一个元素的下一个位置。而且,b和e要么相等(此时删除的范围为空),要么b所指向的元素必须出在e所 指向的元素之前。返回 void 类型 |
string removal_word = "a";
if (word_count.erase(removal_word))
cout << "ok: " << removal_word << " removed\n";
else
cout << "oops: " << removal_word << " not found!\n";
6、set(需要导入头文件#include <set>)
set的含义是集合,它是一个有序的容器,里面的元素都是排序好的,支持插入,删除,查找等操作,就像一个集合一样。所有的操作的都是严格在logn时间之内完成,效率非常高。set和multiset的区别是:set插入的元素不能相同,但是multiset可以相同。Set默认自动排序。使用方法类似list。
①set容器的定义和使用
set 容器的每个键都只能对应一个元素。以一段范围的元素初始化set对象,或在set对象中插入一组元素时,对于每个键,事实上都只添加了一个元素。
vector<int> ivec; for (vector<int>::size_type i = ; i != ; ++i) {
ivec.push_back(i);
ivec.push_back(i);
} set<int> iset(ivec.begin(), ivec.end());
cout << ivec.size() << endl; //20个
cout << iset.size() << endl; // 10个
②在set中添加元素
set<string> set1; set1.insert("the"); //第一种方法:直接添加
set<int> iset2;
iset2.insert(ivec.begin(), ivec.end());//第二中方法:通过指针迭代器
③从set中获取元素
set 容器不提供下标操作符。为了通过键从 set 中获取元素,可使用 find运算。
如果只需简单地判断某个元素是否存在,同样可以使用 count 运算,返回 set 中该键对应的元素个数。
当然,对于 set 容器,count 的返回值只能是1(该元素存在)或 0(该元素不存在)。
set<int> iset; for(int i = ; i<; i++)iset.insert(i);
iset.find() // 返回指向元素内容为1的指针
iset.find() // 返回指针iset.end()
iset.count() // 存在,返回1
iset.count() // 不存在,返回0
- set<int>::iterator it=iset.begin()
*it就是当前迭代器指向的值
- set默认是从小到大排列值,定义时set<int,greater<int>> iset;则此时默认是从大到小排列值。
④迭代器的关联容器操作
函数名 | 意义 |
m.lower_bound(k) |
返回一个迭代器,指向键不小于 k 的第一个元素 |
m.upper_bound(k) | 返回一个迭代器,指向键大于 k 的第一个元素 |
m.equal_range(k) |
返回一个迭代器的 pair 对象。它的 first 成员等价于 m.lower_bound(k)。而 second 成员则等价于 m.upper_bound(k) |
四、各种容器的元素在内存中的储存方式
1、vector(向量):相当于数组,但其大小可以不预先指定,并且自动扩展。它可以像数组一样被操作,
由于它的特性我们完全可以将vector 看作动态数组。在创建一个vector 后,它会自动在内存中分配一块连续的
内存空间进行数据存储,初始的空间大小可以预先指定也可以由vector 默认指定,这个大小即capacity ()函数
的返回值。当存储的数据超过分配的空间时vector 会重新分配一块内存块,但这样的分配是很耗时的,效率非常低。
2、deque(队列):它不像vector 把所有的对象保存在一块连续的内存块,而是采用多个连续的存储块,并且在一个
映射结构中保存对这些块及其顺序的跟踪。向deque 两端添加或删除元素的开销很小,它不需要重新分配空间。
3、list(列表):是一个线性链表结构,它的数据由若干个节点构成,每一个节点都包括一个信息块(即实际存储的数据)、
一个前驱指针和一个后驱指针。它无需分配指定的内存大小且可以任意伸缩,这是因为它存储在非连续的内存空间中,
并且由指针将有序的元素链接起来。
4、set, multiset, map, multimap 是一种非线性的树结构,具体的说采用的是一种比较高效的特殊的
平衡检索二叉树—— 红黑树结构。
五、各种容器优劣分析
1、Vector:
优点:
A、支持随机访问,访问效率高和方便,它像数组一样被访问,即支持[ ] 操作符和vector.at()。
B、节省空间,因为它是连续存储,在存储数据的区域都是没有被浪费的,但是要明确一点vector 大多情况下并不是满存的,在未存储的区域实际是浪费的。
缺点:
A、在内部进行插入、删除操作效率非常低。
B、只能在vector 的最后进行push 和pop ,不能在vector 的头进行push 和pop 。
C、 当动态添加的数据超过vector 默认分配的大小时要进行内存的重新分配、拷贝与释放,这个操作非常消耗能。
2、List:
优点:
不使用连续的内存空间这样可以随意地进行动态操作,插入、删除操作效率高;
缺点:
A、不能进行内部的随机访问,即不支持[ ] 操作符和vector.at(),访问效率低。
B、相对于verctor 占用更多的内存。
3、Deque:
优点:
A、支持随机访问,方便,即支持[ ] 操作符和vector.at() ,但性能没有vector 好;
B、可以在两端进行push 、pop 。
缺点:
在内部进行插入、删除操作效率低。
综合:
vector 的查询性能最好,并且在末端增加数据也很好,除非它重新申请内存段;适合高效地随机存储。
list 是一个链表,任何一个元素都可以是不连续的,但它都有两个指向上一元素和下一元素的指针。所以它对插入、删除元素性能是最好的,而查询性能非常差;适合 大量地插入和删除操作而不关心随机存取的需求。
deque 是介于两者之间,它兼顾了数组和链表的优点,它是分块的链表和多个数组的联合。所以它有被list 好的查询性能,有被vector 好的插入、删除性能。 如果你需要随即存取又关心两端数据的插入和删除,那么deque 是最佳之选。
3、关联容器的特点是明显的,相对于顺序容器,有以下几个主要特点:
A, 其内部实现是采用非线性的二叉树结构,具体的说是红黑树的结构原理实现的;
B, set 和map 保证了元素的唯一性,mulset 和mulmap 扩展了这一属性,可以允许元素不唯一;
C, 元素是有序的集合,默认在插入的时候按升序排列。
基于以上特点,
A, 关联容器对元素的插入和删除操作比vector 要快,因为vector 是顺序存储,而关联容器是链式存储;比list 要慢,是因为即使它们同是链式结构,但list 是线性的,而关联容器是二叉树结构,其改变一个元素涉及到其它元素的变动比list 要多,并且它是排序的,每次插入和删除都需要对元素重新排序;
B, 关联容器对元素的检索操作比vector 慢,但是比list 要快很多。vector 是顺序的连续存储,当然是比不上的,但相对链式的list 要快很多是因为list 是逐个搜索,它搜索的时间是跟容器的大小成正比,而关联容器 查找的复杂度基本是Log(N) ,比如如果有1000 个记录,最多查找10 次,1,000,000 个记录,最多查找20 次。容器越大,关联容器相对list 的优越性就越能体现;
C, 在使用上set 区别于vector,deque,list 的最大特点就是set 是内部排序的,这在查询上虽然逊色于vector ,但是却大大的强于list 。
D, 在使用上map 的功能是不可取代的,它保存了“键- 值”关系的数据,而这种键值关系采用了类数组的方式。数组是用数字类型的下标来索引元素的位置,而map 是用字符型关键字来索引元素的位置。在使用上map 也提供了一种类数组操作的方式,即它可以通过下标来检索数据,这是其他容器做不到的,当然也包括set 。(STL 中只有vector 和map 可以通过类数组的方式操作元素,即如同ele[1] 方式)。
六、关于容器的sizeof、size()、capacity问题
vector<int> ivec; cout<<sizeof(ivec)<<endl; // cout<<ivec.size()<<endl; // cout<<ivec.capacity()<<endl; // for(int i=;i<;i++) ivec.push_back(); cout<<sizeof(ivec)<<endl; // Cout<<ivec.size()<<endl; // cout<<ivec.capacity()<<endl; //
这是container的实现问题,container肯定有些数据成员什么的,这可以是auto_ptr或者是普通的ptr指向一块内存区域,或者还有可能(应该)包括这个内存区域的长度,现在已经用的长度。sizeof操作符统计的只是数据成员的长度,不会与堆里面的数据长度有关,所以会出现你看到的结果。即作sizeof操作的大小是相同的。而vector::size()操作,才反映了具体数据长度。Capacity求的是容器(vector)的容量。
七、其它
1、STL中hashtable,hashset,hashmap,set,map,unordered_map、unordered_set的区别
①hashtable,hashset,hashmap,unordered_map、unordered_set与set,map的根本区别在于底层的实现不同,前者底层都是由hashtable来提供的,后者都是由红黑树来提供;前者查询时间虽然是O(1),但是并不是前者查询时间一定比后者短,因为实际情况中还要考虑到数据量,而且前者的hash函数的构造速度也没那么快,所以不能一概而论,应该具体情况具体分析。后者保证了一个稳定的动态操作时间,查询、插入、删除都是O(logN),最坏和平均都是。
②unordered_map、unordered_set在C++11的时候被引入标准库了,而hashset,hashmap没有,所以建议还是使用unordered_map比较好。
③hashset与set相比较,它里面的元素不一定是经过排序的,而是按照所用的hash函数分派的,它能提供更快的搜索速度(当然跟hash函数有关)。(hashmap与map区别一样)
STL不同容器的使用方法的更多相关文章
- C++ STL vector容器学习
STL(Standard Template Library)标准模板库是C++最重要的组成部分,它提供了一组表示容器.迭代器.函数对象和算法的模板.其中容器是存储类型相同的数据的结构(如vector, ...
- STL的容器算法迭代器的设计理念
1) STL的容器通过类模板技术,实现数据类型和容器模型的分离. 2) STL的迭代器技术实现了遍历容器的统一方法:也为STL的算法提供了统一性. 3) STL的函数对象实现了自定义数据类型的算法运算 ...
- STL基础--容器
容器种类 序列容器(数组,链表) Vector, deque, list, forward list, array 关联容器(二叉树),总是有序的 set, multiset根据值排序,元素值不能修改 ...
- c++复习:STL之容器
1 STL的string 1 String概念 string是STL的字符串类型,通常用来表示字符串.而在使用string之前,字符串通常是用char*表示的.string与char*都可以用来表示字 ...
- STL Queue 容器
STL Queue 容器 Queue简介 queue是队列容器,是一种“先进先出”的容器. queue是简单地装饰deque容器而成为另外的一种容器. # ...
- STL stack 容器
STL stack 容器 Stack简介 stack是堆栈容器,是一种“先进后出”的容器. stack是简单地装饰deque容器而成为另外的一种容器. #include <s ...
- STL Deque 容器
STL Deque 容器 Deque简介 deque是“double-ended queue”的缩写,和vector一样都是STL的容器,deque是双 端的,而vector是单端的. ...
- [STL] STL各容器实现原理
STL共有六大组件1.容器 2.算法 3.迭代器 4.仿函数 6.适配器 STL容器的实现原理 STL来管理数据十分方便,省去了我们自己构建数据结构的时间.其实,STL的实现也是基于我们常见的数据结构 ...
- 浅谈C++ STL string容器
浅谈C++ STL string容器 本篇随笔简单讲解一下\(C++STL\)中\(string\)容器的使用方法及技巧. string容器的概念 其实\(string\)并不是\(STL\)的一种容 ...
随机推荐
- 原生JS表单序列化
// 表单序列化,IE9+ HTMLFormElement.prototype.serialize = function() { var form = this; // 表单数据 var arrFor ...
- 【题解】Atcoder AGC#16 E-Poor Turkeys
%拜!颜神怒A此题,像我这样的渣渣只能看看题解度日╭(╯^╰)╮在这里把两种做法都记录一下吧~ 题解做法:可以考虑单独的一只鸡 u 能否存活.首先我们将 u 加入到集合S.然后我们按照时间倒序往回推, ...
- bzoj 3280: 小R的烦恼 (网络流)
和开发计划一样(数组开太小wa了好多次,然后为什么这么慢? type arr=record toward,next,cap,cost:longint; end; const maxm=; maxn=; ...
- CF9d How many trees?
题意:求节点数为n的,高度大于等于h的二叉树的个数. 题解: 一开始没看到二叉树的限制,,,想了好久.因为数据范围很小,所以可以考虑一些很暴力的做法. 有2种DP方式都可以过. 1,f[i][j]表示 ...
- 如何提升集群资源利用率? 阿里容器调度系统Sigma 深入解析
阿里妹导读:为了保证系统的在线交易服务顺利运转,最初几年,阿里都是在双11大促来临之前大量采购机器储备计算资源,导致了双11之后资源大量闲置点现象.是否能把计算任务与在线服务进行混合部署,在现有弹性资 ...
- 15ecjtu校赛1006 (dfs容斥)
Problem Description 在平面上有一个n*n的网格,即有n条平行于x轴的直线和n条平行于y轴的直线,形 成了n*n个交点(a,b)(1<=a<=n,1<=b<= ...
- 使用树莓派录音——USB声卡
原文链接:http://jingyan.eeboard.com/article/73723 我们都知道树莓派只有音频输出口,而没有音频输入的接口,怎么办呢?其实只要一个USB声卡就可以了. USB声卡 ...
- mysql绿色版安装,多实例安装
1.为什么要装多个mysql多实例? 关于这个的原因,我目前了解为建立一个主数据库,一个或者多个从库,实现一主多从或者主从复制的目的. 2.设么是mysql的多实例? MySQL多实例就是在一台机器上 ...
- hadoop压缩和解压
最近有一个hadoop集群上的备份需求.源文件有几百G,如果直接复制太占用磁盘空间.将文件从hadoop集群下载到本地,压缩之后再上传到hadoop则太耗时间.于是想到能否直接在HDFS文件系统上进行 ...
- FreeRTOS - 如何根据FreeRTOS提供的功能(信号量、任务通知、队列等)设计程序
原文地址:http://www.cnblogs.com/god-of-death/p/6917837.html 1.二值信号量 就像一个标志位,事件产生置一,事件处理后直零 用于任务之间的同步,即一个 ...