STL-vector,stack,list,queue Posted 2020-07-12
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了STL-vector,stack,list,queue相关的知识,希望对你有一定的参考价值。
vector是可以快速地在最后添加删除元素,并可以快速地访问任意元素 list是可以快速地在所有地方添加删除元素,但是只能快速地访问最开始与最后的元素 deque在开始和最后添加元素都一样快,并提供了随机访问方法,像vector一样使用[]访问任意元素,但是随机访问速度比不上vector快,因为它要内部处理堆跳转 deque也有保留空间.另外,由于deque不要求连续空间,所以可以保存的元素比vector更大,这点也要注意一下.还有就是在前面和后面添加元素时都不需要移动其它块的元素,所以性能也很高。
因此在实际使用时,如何选择这三个容器中哪一个,应根据你的需要而定,一般应遵循下面 的原则: 1、如果你需要高效的随即存取,而不在乎插入和删除的效率,使用vector 2、如果你需要大量的插入和删除,而不关心随即存取,则应使用list 3、如果你需要随即存取,而且关心两端数据的插入和删除,则应使用deque。
cber:很遗憾地告诉你,你的回答只对了一半:((,看来老虎也有打盹的时候啊。 下面是“GotW #074”的主要内容,我知道你一定更喜欢看原文,但我贴此文是为了照顾一些刚学C++的朋友。 GotW #074主要内容: // Example 1: [] vs. at() // void f( vector<int>& v ) { v[0]; // A v.at(0); // B } 在这个例子中,如果v不是空的,则A句和B句无分别。若v是空的,那么B句会throw一个std::out_of_range的exception;C++ Standard从效率和兼容‘内建型别’上考虑,并不要求A句throw出exception。即vector<T>::at()有下标越界检查(Bounds checking),而vector<T>::operator []()一般(注意是一般,C++ Standard并没有说operator[]一定不能做下标越界检查)没有做下标越界检查。如果向operator[]传入非法的下标,其行为“不可预测” // Example 2: Some fun with vectors vector<int> v; v.reserve( 2 ); assert( v.capacity() == 2 ); 1. 如cber所说,v.reserve(2)表示v的内部缓冲区至少能容纳2个元素,而不一定刚好容纳2个元素(可能更多)。vector的大小是按指数增长的,即cber所说“选择2的n次方来分配空间”,这句话应该改为assert( v.capacity() >= 2 ); 2. 其实这个assert( v.capacity() >= 2 );也是多余的,因为C++ Standard保证执行v.reserve(n);后, 一定有v.capacity() >= n;即在vector<T>::reserve()中已经做了类似的assert,你又何必自己再来做重复的工作呢?除非你对你的C++ Standard Libaray的健壮性不放心:)。 v[0] = 1; v[1] = 2; 这两条语句有明显的错误:v.reserve()只是增加了vector的存储空间,并没有增加其中元素的个数。这时v仍然是空的(v.size() == 0,v.capacity() >= 2),所以这里下标越界了。可以考虑改为v.push_back(1);v.push_back(2); for( vector<int>::iterator i = v.begin(); i < v.end(); i++ ) { cout << *i << endl; } 1. 这个循环不会打印任何东西,因为此时v是空的。 2. 尽量使用const,这里的iterator并没有改动v的元素,所以应该用const_iterator 3. 循环的结束条件处,比较两个iterators应该用 != 而非 < ,只有random-access iterator才能用 “<”来比较,而作为循环的结束条件,更加普遍的做法是用 “!=”来比较iter与v.end()。 4. 用++i取代i++,两者效率不同。 5. 避免不必要的重复计算,因为v.end()的值在循环中没有变,所以在循环之前对v.end()求一次值就可以了。 6. 用‘\n‘替代endl,因为使用endl会强制flush(冲洗) ostream的内部输出缓冲区,如果你不是每打印一个*i就需要flush一次缓冲区的话,用‘\n‘。 7. 使用标准的演算法,可以避免以上所有问题: copy( v.begin(), v.end(), ostream_iterator<int>(cout, "\n") ); 另外,似乎没有copy( v.begin(), v.end(), ostream_iterator<int>(cout, endl) );这种写法,所以当你确实需要每打印一行就flush一次缓冲区时,自己写一个copy()吧。 cout << v[0]; 一般情况下,输出1,其实v[0]是越界了。 v.reserve( 100 ); assert( v.capacity() == 100 ); 同上,这里的assert是不正确且多余的。 这里v重新分配(realloc)了缓冲区,但它认为自己只有0个元素,故原来的v[0] == 1并没有复制到新的缓冲区,所以新的v[0] == 0;所以下一句 cout << v[0]; 会打印0,这一定会气倒一片人的。 v[2] = 3; v[3] = 4; // ... v[99] = 100; 首先下标越界,其次按cber说的可以用for_each() for( vector<int>::iterator i = v.begin(); i < v.end(); i++ ) { cout << *i << endl; } 改为: copy( v.begin(), v.end(), ostream_iterator<int>(cout, "\n") ); 关于用STL演算法取代自己编写循环的进一步讨论,请参看CUJ 2001十月,Scott Meyers写的《STL Algorithms vs. Hand-Written Loops》一文 好多的陷阱啊,一不小心就掉进去了,非得好好看看Effective STL / Exceptional C++不可。 我晕了,你晕了没有?
vector:
Constructors 构造函数
Operators 对vector进行赋值或比较
assign() 对Vector中的元素赋值
at() 返回指定位置的元素
back() 返回最末一个元素
begin() 返回第一个元素的迭代器
capacity() 返回vector所能容纳的元素数量(在不重新分配内存的情况下)
clear() 清空所有元素
empty() 判断Vector是否为空(返回true时为空)
end() 返回最末元素的迭代器(译注:实指向最末元素的下一个位置)
erase() 删除指定元素
front() 返回第一个元素
get_allocator() 返回vector的内存分配器
insert() 插入元素到Vector中
max_size() 返回Vector所能容纳元素的最大数量(上限)
pop_back() 移除最后一个元素
push_back() 在Vector最后添加一个元素
rbegin() 返回Vector尾部的逆迭代器
rend() 返回Vector起始的逆迭代器
reserve() 设置Vector最小的元素容纳数量
resize() 改变Vector元素数量的大小
size() 返回Vector元素数量的大小
swap() 交换两个Vector
list:
assign() 给list赋值
back() 返回最后一个元素
begin() 返回指向第一个元素的迭代器
clear() 删除所有元素
empty() 如果list是空的则返回true
end() 返回末尾的迭代器
erase() 删除一个元素
front() 返回第一个元素
get_allocator() 返回list的配置器
insert() 插入一个元素到list中
max_size() 返回list能容纳的最大元素数量
merge() 合并两个list
pop_back() 删除最后一个元素
pop_front() 删除第一个元素
push_back() 在list的末尾添加一个元素
push_front() 在list的头部添加一个元素
rbegin() 返回指向第一个元素的逆向迭代器
remove() 从list删除元素
remove_if() 按指定条件删除元素
rend() 指向list末尾的逆向迭代器
resize() 改变list的大小
reverse() 把list的元素倒转
size() 返回list中的元素个数
sort() 给list排序
splice() 合并两个list
swap() 交换两个list
unique() 删除list中重复的元素
stack:
操作 比较和分配堆栈
empty() 堆栈为空则返回真
pop() 移除栈顶元素
push() 在栈顶增加元素
size() 返回栈中元素数目
top() 返回栈顶元素
queue:
back() 返回最后一个元素
empty() 如果队列空则返回真
front() 返回第一个元素
pop() 删除第一个元素
push() 在末尾加入一个元素
size() 返回队列中元素的个数 以上是关于STL-vector,stack,list,queue的主要内容,如果未能解决你的问题,请参考以下文章
stl-vector详解
STL-vector 模板类 模拟实现
STL-vector
STL-vector
bzoj2724[Violet 6]蒲公英 分块+STL-vector
C++提高编程STL-vector容器