向量
1)基本特性
A.连续内存,下标访问。
B.动态内存管理,静态预分配。
2)实例化
#include <vector>
using namespace std;
A.空向量
vector<元素类型> 向量对象;
vector<int> vi;
大小为0,元素数为0,向量对象的字节大小是一个常量——12字节。
B.初始大小
vector<元素类型> 向量对象 (元素数);
vector<int> vi (5); // 0 0 0 0 0
基本类型元素,用"0"初始化,类类型元素,用缺省构造函数初始化。
C.初始值
vector<元素类型> 向量对象 (元素数, 初值);
vector<int> vi (5, 10); // 10 10 10 10 10
D.范围初始化
vector<元素类型> 向量对象 (起始迭代器, 终止迭代器);
int ai[5] = {1, 2, 3, 4, 5};
vector<int> vi (ai, ai + 5); // 1 2 3 4 5
vector<int> vi (&ai[0], &ai[5]);
#include <iostream> #include <vector> using namespace std; void print (vector<int> const& vi) { cout << "字节数:" << sizeof (vi) << endl; size_t size = vi.size (); cout << "元素数:" << size << endl; cout << "元 素:" << flush; for (size_t i = 0; i < size; ++i) cout << vi[i] << ' '; cout << endl; } int main (void) { vector<int> v1; print (v1); vector<int> v2 (5); print (v2); vector<int> v3 (5, 10); print (v3); int ai[5] = {10, 20, 30, 40, 50}; vector<int> v4 (ai, ai + 5); print (v4); // vector<int> v5 (ai + 1, ai + 4); vector<int> v5 (&ai[1], &ai[4]); print (v5); return 0; }
注意在STL中用两个迭代器表示一个范围时,其终止迭代器永远是该范围中最后一个元素下一个位置的迭代器。
1 2 3 [4 5 6 7] 8 9 10
^ ^
| |
起始迭代器 终止迭代器
3)迭代器
A.四个迭代器类型
正向可写迭代器:iterator
正向只读迭代器:const_iterator
反向可写迭代器:reverse_iterator
反向只读迭代器:const_reverse_iterator
B.八个特征迭代器
begin (void); // 正向可写起始迭代器
end (void); // 正向可写终止迭代器
begin (void) const;
end (void) const;
rbegin (void);
rend (void);
rbegin (void) const;
rend (void) const;
--------------------
begin - 起始
end - 终止
不带const - 可写
带const - 只读
不带r - 正向
带r - 反向
对于正向迭代器而言,起始位置在首元素,终止位置在尾元素之后;对于反向迭代器而言,起始位置在尾元素,终止位置在首元素之前。
C.随机迭代器
所有顺序迭代器的功能随机迭代器都支持,同时还提供更多功能:和整数加减运算、同型迭代器之间的大小比较和相减运算
*****************D.任何可能导致容器内存布局发生变化的结构性改变,如增删元素等,都可能使原先获得的迭代器失效,因此稳妥起见,在这样的改变发生以后应该重新获得反应新内存布局的迭代器,保证元素访问正确。
#include <iostream> #include <vector> using namespace std; void print (vector<int> const& vi) { for (vector<int>::const_iterator it = vi.begin (); it != vi.end (); ++it) cout << /*++*/*it << ' '; cout << endl; } void rprint (vector<int> const& vi) { for (vector<int>::const_reverse_iterator it =vi.rbegin (); it != vi.rend ();++it) cout << *it << ' '; cout << endl; } int main (void) { vector<int> vi; for (int i = 1; i <= 10; ++i) vi.push_back (i); size_t size = vi.size (); for (size_t i = 0; i < size; ++i) cout << vi[i] << ' '; cout << endl; for (vector<int>::iterator it = vi.begin (); it != vi.end (); ++it) cout << *it << ' '; cout << endl; print (vi); for (vector<int>::reverse_iterator it = vi.rbegin (); it != vi.rend (); ++it) cout << *it << ' '; cout << endl; rprint (vi); // vi: 1 2 3 4 5 6 7 8 9 10 /* vi[4] = 50; print (vi); */ vector<int>::iterator it1 = vi.begin (); /* *++++++++it1 = 50; */ *(it1 + 4) = 50; print (vi); vector<int>::iterator it2 = vi.end () - 1; // 越靠近起始位置的迭代器越小,越靠近终止位置的迭代器越大 cout << boolalpha << (it1 < it2) << endl; // true // it1 + 9 == it2 cout << it2 - it1 << endl; // 9 vector<int>::reverse_iterator it3 = vi.rbegin (), it4 = vi.rend () - 1; cout << (it4 < it3) << endl; // false cout << it3 - it4 << endl; // -9 vector<int> vn; vn.push_back (100); it1 = vn.begin (); cout << *it1 << endl; // 100 vn.push_back (200); it1 = vn.begin (); cout << *it1 << endl; // 100 vn.clear (); vn.push_back (11); vn.push_back (22); vn.push_back (44); vn.push_back (33); vn.push_back (55); print (vn); it1 = vn.begin (); while (it1 != vn.end ()) if (*it1 % 2) ++it1; else // vn.erase (it1); it1 = vn.erase (it1); print (vn); return 0; }
4)成员函数
front/back
push_back/pop_back(没有push_front/pop_front)
insert/erase
size/empty/clear
begin/end
rbegin/rend
operator[]
所有的STL都有支持深拷贝的拷贝构造和拷贝赋值
#include <iostream> #include <vector> using namespace std; void print (vector<int> const& vi) { for (vector<int>::const_iterator it = vi.begin (); it != vi.end (); ++it) cout << /*++*/*it << ' '; cout << endl; } void rprint (vector<int> const& vi) { for (vector<int>::const_reverse_iterator it =vi.rbegin (); it != vi.rend ();++it) cout << *it << ' '; cout << endl; } int main (void) { vector<int> vi; for (int i = 1; i <= 10; ++i) vi.push_back (i); size_t size = vi.size (); for (size_t i = 0; i < size; ++i) cout << vi[i] << ' '; cout << endl; for (vector<int>::iterator it = vi.begin (); it != vi.end (); ++it) cout << *it << ' '; cout << endl; print (vi); for (vector<int>::reverse_iterator it = vi.rbegin (); it != vi.rend (); ++it) cout << *it << ' '; cout << endl; rprint (vi); // vi: 1 2 3 4 5 6 7 8 9 10 /* vi[4] = 50; print (vi); */ vector<int>::iterator it1 = vi.begin (); /* *++++++++it1 = 50; */ *(it1 + 4) = 50; print (vi); vector<int>::iterator it2 = vi.end () - 1; // 越靠近起始位置的迭代器越小,越靠近终止位置的迭代器越大 cout << boolalpha << (it1 < it2) << endl; // true // it1 + 9 == it2 cout << it2 - it1 << endl; // 9 vector<int>::reverse_iterator it3 = vi.rbegin (), it4 = vi.rend () - 1; cout << (it4 < it3) << endl; // false cout << it3 - it4 << endl; // -9 vector<int> vn; vn.push_back (100); it1 = vn.begin (); cout << *it1 << endl; // 100 vn.push_back (200); it1 = vn.begin (); cout << *it1 << endl; // 100 vn.clear (); vn.push_back (11); vn.push_back (22); vn.push_back (44); vn.push_back (33); vn.push_back (55); print (vn); it1 = vn.begin (); while (it1 != vn.end ()) if (*it1 % 2) ++it1; else // vn.erase (it1); it1 = vn.erase (it1); print (vn); return 0; }
5)全局函数
A.排序
template<typename IT>
void sort(IT begin, IT end);
对[begin,end)区间内的元素做快速排序。
在排序过程中,通过小于运算符比大小。
template<typename IT, typename LESS>
void sort (IT begin, IT end, LESS less);
在排序过程中,通过小于比较器比大小。
小于比较器可以是函数指针也可以是仿函数。
B.find
template<typename IT, typename KEY>
IT find (IT begin, IT end, KEY key);
如果查找成功返回在[begin,end)区间内第一个和key匹配的元素的迭代器,否则返回end。容器中元素的类型必须支持"=="运算符。
#include <iostream> #include <vector> #include <algorithm> // 泛型算法 using namespace std; template<typename T> ostream& operator<< (ostream& os,vector<T> const& vec) { for (typename vector<T>::const_iterator it = vec.begin ();it != vec.end (); ++it) os << *it << ' '; return os; } bool intCmp (int a, int b) { return a > b; } class IntCmp { public: bool operator() (int a, int b) const{ return a > b; } }; int main (void) { int ai[] = {13, 27, 17, 19, 51, 33}; vector<int> v1 (ai, ai + sizeof (ai) / sizeof (ai[0])); cout << v1 << endl; sort (v1.begin (), v1.end ()); cout << v1 << endl; // sort (v1.rbegin (), v1.rend ()); // sort (v1.begin (), v1.end (), // intCmp); sort (v1.begin (), v1.end (), IntCmp ()); cout << v1 << endl; return 0; }