C++ Vector(向量容器)
是一個線性順序結(jié)構(gòu)。相當(dāng)于數(shù)組,但其大小可以不預(yù)先指定,并且自動擴展。它可以像數(shù)組一樣被操作,由于它的特性我們完全可以將vector 看作動態(tài)數(shù)組。
在創(chuàng)建一個vector 后,它會自動在內(nèi)存中分配一塊連續(xù)的內(nèi)存空間進行數(shù)據(jù)存儲,初始的空間大小可以預(yù)先指定也可以由vector 默認(rèn)指定,這個大小即capacity ()函數(shù)的返回值。當(dāng)存儲的數(shù)據(jù)超過分配的空間時vector 會重新分配一塊內(nèi)存塊,但這樣的分配是很耗時的,在重新分配空間時它會做這樣的動作:
首先,vector 會申請一塊更大的內(nèi)存塊;
然后,將原來的數(shù)據(jù)拷貝到新的內(nèi)存塊中;
其次,銷毀掉原內(nèi)存塊中的對象(調(diào)用對象的析構(gòu)函數(shù));
最后,將原來的內(nèi)存空間釋放掉。
如果vector 保存的數(shù)據(jù)量很大時,這樣的操作一定會導(dǎo)致糟糕的性能(這也是vector 被設(shè)計成比較容易拷貝的值類型的原因)。所以說vector 不是在什么情況下性能都好,只有在預(yù)先知道它大小的情況下vector 的性能才是最優(yōu)的。
vector 的特點:
(1) 指定一塊如同數(shù)組一樣的連續(xù)存儲,但空間可以動態(tài)擴展。即它可以像數(shù)組一樣操作,并且可以進行動態(tài)操作。通常體現(xiàn)在push_back() pop_back() 。
(2) 隨機訪問方便,它像數(shù)組一樣被訪問,即支持[ ] 操作符和vector.at()
(3) 節(jié)省空間,因為它是連續(xù)存儲,在存儲數(shù)據(jù)的區(qū)域都是沒有被浪費的,但是要明確一點vector 大多情況下并不是滿存的,在未存儲的區(qū)域?qū)嶋H是浪費的。
(4) 在內(nèi)部進行插入、刪除操作效率非常低,這樣的操作基本上是被禁止的。Vector 被設(shè)計成只能在后端進行追加和刪除操作,其原因是vector 內(nèi)部的實現(xiàn)是按照順序表的原理。
(5) 只能在vector 的最后進行push 和pop ,不能在vector 的頭進行push 和pop 。
(6) 當(dāng)動態(tài)添加的數(shù)據(jù)超過vector 默認(rèn)分配的大小時要進行內(nèi)存的重新分配、拷貝與釋放,這個操作非常消耗性能。 所以要vector 達到最優(yōu)的性能,最好在創(chuàng)建vector 時就指定其空間大小。
Vectors 包含著一系列連續(xù)存儲的元素,其行為和數(shù)組類似。訪問Vector中的任意元素或從末尾添加元素都可以在常量級時間復(fù)雜度內(nèi)完成,而查找特定值的元素所處的位置或是在Vector中插入元素則是線性時間復(fù)雜度。
1.Constructors 構(gòu)造函數(shù)
vector<int> v1; //構(gòu)造一個空的vector
vector<int> v1( 5, 42 ); //構(gòu)造了一個包含5個值為42的元素的Vector
2.Operators 對vector進行賦值或比較
C++ Vectors能夠使用標(biāo)準(zhǔn)運算符: ==, !=, <=, >=, <, 和 >.
要訪問vector中的某特定位置的元素可以使用 [] 操作符.
兩個vectors被認(rèn)為是相等的,如果:
1.它們具有相同的容量
2.所有相同位置的元素相等.
vectors之間大小的比較是按照詞典規(guī)則.
3.assign() 對Vector中的元素賦值
語法:
void assign( input_iterator start, input_iterator end );
// 將區(qū)間[start, end)的元素賦到當(dāng)前vector
void assign( size_type num, const TYPE &val );
// 賦num個值為val的元素到vector中,這個函數(shù)將會清除掉為vector賦值以前的內(nèi)容。
4.at() 返回指定位置的元素
語法:
TYPE at( size_type loc );//差不多等同v[i];但比v[i]安全;
5.back() 返回最末一個元素
6.begin() 返回第一個元素的迭代器
7.capacity() 返回vector所能容納的元素數(shù)量(在不重新分配內(nèi)存的情況下)
8.clear() 清空所有元素
9.empty() 判斷Vector是否為空(返回true時為空)
10.end() 返回最末元素的迭代器(譯注:實指向最末元素的下一個位置)
11.erase() 刪除指定元素
語法:
iterator erase( iterator loc );//刪除loc處的元素
iterator erase( iterator start, iterator end );//刪除start和end之間的元素
12.front() 返回第一個元素的引用
13.get_allocator() 返回vector的內(nèi)存分配器
14.insert() 插入元素到Vector中
語法:
iterator insert( iterator loc, const TYPE &val );
//在指定位置loc前插入值為val的元素,返回指向這個元素的迭代器,
void insert( iterator loc, size_type num, const TYPE &val );
//在指定位置loc前插入num個值為val的元素
void insert( iterator loc, input_iterator start, input_iterator end );
//在指定位置loc前插入?yún)^(qū)間[start, end)的所有元素
15.max_size() 返回Vector所能容納元素的最大數(shù)量(上限)
16.pop_back() 移除最后一個元素
17.push_back() 在Vector最后添加一個元素
18.rbegin() 返回Vector尾部的逆迭代器
19.rend() 返回Vector起始的逆迭代器
20.reserve() 設(shè)置Vector最小的元素容納數(shù)量
//為當(dāng)前vector預(yù)留至少共容納size個元素的空間
21.resize() 改變Vector元素數(shù)量的大小
語法:
void resize( size_type size, TYPE val );
//改變當(dāng)前vector的大小為size,且對新創(chuàng)建的元素賦值val
22.size() 返回Vector元素數(shù)量的大小
23.swap() 交換兩個Vector
語法:
void swap( vector &from );
Vector用法 :
1.聲明:
一個vector類似于一個動態(tài)的一維數(shù)組。
vector<int> a; //聲明一個元素為int類型的vector a
vectot<MyType> a; //聲明一個元素為MyType類型的vector a
這里的聲明的a包含0個元素,既a.size()的值為0,但它是動態(tài)的,其大小會隨著數(shù)據(jù)的插入和刪除改變而改變。
vector<int> a(100, 0); //這里聲明的是一個已經(jīng)存放了100個0的整數(shù)vector
你可以用以下的幾種方法聲明一個 vector 對象:
vector<float> v(5, 3.25); //初始化有5 個元素,其值都是3.25
vector<float> v_new1(v);
vector<float> v_new2 = v;
vector<float> v_new3(v.begin(), v.end());
這四個vector 對象是相等的,可以用operator==來判斷。
2.向量操作
常用函數(shù):
size_t size(); // 返回vector的大小,即包含的元素個數(shù)
void pop_back(); // 刪除vector末尾的元素,vector大小相應(yīng)減一
void push_back(); //用于在vector的末尾添加元素
T back(); // 返回vector末尾的元素
void clear(); // 將vector清空,vector大小變?yōu)?
其他訪問方式:
cout<<a[5]<<endl;
cout<<a.at(5)<<endl;
以上區(qū)別在于后者在訪問越界時會拋出異常,而前者不會。
3.遍歷
(1). for(vector<datatype>::iterator it=a.begin(); it!=a.end();it++)
cout<<*it<<endl;
(2). for(int i=0;i<a.size;i++)
cout<<a[i]<<endl;
現(xiàn)在想得到容器中能保存的最大元素數(shù)量就可以用 vector 類的成員函數(shù)max_size():
vector<shape>::size_type max_size = my_shapes.max_size();
當(dāng)前容器的實際尺寸 --- 已有的元素個數(shù)用size():
vector<shape>::size_type size = my_shapes.size();
就像size_type 描述了vector 尺寸的類型,value_type 說明了其中保存的對象的類型:
cout << “value type: “ << typeid(vector<float>::value_type).name();
輸出:
value type: float
可以用capacity()來取得vector 中已分配內(nèi)存的元素個數(shù):
vector<int> v;
vector<int>::size_type capacity = v.capacity();
vector 類似于數(shù)組,可以使用下標(biāo)[]訪問:
vector<int> v(10);
v[0] = 101;
注意到這里預(yù)先給10 個元素分配了空間。你也可以使用vector 提供的插入函數(shù)來動態(tài)的擴
展容器。成員函數(shù)push_back()就在vector 的尾部添加了一個元素:
v.push_back(3);
也可以用insert()函數(shù)完成同樣的工作:
v.insert(v.end(), 3);
這里insert()成員函數(shù)需要兩個參數(shù):一個指向容器中指定位置的迭代器(iterator),一個待插
入的元素。insert()將元素插入到迭代器指定元素之前。
現(xiàn)在對迭代器(Iterator)做點解釋。Iterator 是指針(pointer)的泛化,iterator 要求定義
operator*,它返回指定類型的值。Iterator 常常和容器聯(lián)系在一起。例子:
vector<int> v(3);
v[0] = 5;
v[1] = 2;
v[2] = 7;
vector<int>::iterator first = v.begin();
vector<int>::iterator last = v.end();
while (first != last)
cout << *first++ << “ “;
上面代碼的輸出是:
5 2 7
begin()返回的是vector 中第一個元素的iterator,而end()返回的并不是最后一個元素的
iterator,而是past the last element。在STL 中叫past-the-end iterator。
組合查找
vector<int>::iterator result = find( v.begin( ), v.end( ), 2 ); //查找2
if ( result == v.end( ) ) //沒找到
cout << "No" << endl;
else //找到
cout << "Yes" << endl;