C++ vector的初始化、添加、遍历、插入、删除、查找、排序、释放操作
C++的vector本質上是一個動態數組,數據量不大的情況下,非常方便存儲和訪問操作,當然,不好的情況是數據量大的情況下,查找效率低,刪除操作還會導致大量的數組移動操作。
雖然這樣,vector還是一個很有用的東西,可以滿足很多開發需求。
?
1.??vector的初始化
Vector是向量模板,C++ STL之一。前面說過vector是一個動態生長的數組,一開始vector為空時,會給一個初始化的容量(就是允許的添加個數),并申請好內存了,當往vector里面添加的元素超過現在的容量(capacity)時,就會重新更大申請內存,并把之前的所有元素,拷貝到新內存中。
?
因此,我們最好用到vector時,最好給他一個初始化大小,避免更多的內存申請動作和移動操作。
?
?
初始化vector元素的個數例子:
???typedef std::vector < ?Type > ?VectorT;
???VectorT ?a(10);
Type是類型,可以是結構體、整型、指針,類對象,指針函數等。
VectorT ?a(10);定義了一個初始化大小10,類型為Type的vector向量。定義后a有10個初始值為0的元素,因此要調用a.clear()把這些元素清空,清空后STL并不會銷毀10個元素的內存。
?
其實初始化方法:
(1)初始化一個空的vector:
?VectorT ?a;
(2)初始化n個值為value的vector
?VectorT ??a( n , value);
?
2.添加元素(添加到末尾)
?
調用push_back()函數
void push_back (const value_type& val);
?a是vector向量
?a.push_back( val);
如果vector的容器已滿,在末尾添加元素時會alloc申請更大的內存,并拷貝之前的元素到新內存,再把元素添加到vector容器末尾。
?
3.查找
調用find方法(需要include<algorithm>)
template <class InputIterator, class T>
???InputIterator find (InputIterator first, InputIterator last, const T& val)
?
如查找元素為value,找到則返回迭代器的位置,否則迭代器將指向end()
std::vector < ?Type >:: iterator ??iVector;
iVector = std::find(a.begin(), a.end() , value);
?
If( ?iVector ?!= ?a.end())
{
找到了
}
Else
{
沒找到。
}
?
4.遍歷
利用迭代器,一開始迭代器iVector指向begin,只要不等于end,就繼續遍歷下去
typedef std::vector < ?Type > ?VectorT;
VectorT a;
VectorT::iterator iVector = a.begin(); ?
while(iVector != a.end())
{ ??
?std::cout<<" dump "<< (*iVector)<<std::endl;
?++iVector; ?
} ?
?
?
5.刪除末尾元素或者刪除全部元素。
(1)刪除一個末尾元素
a.pop_back();
?
//刪除操作避免大量移動的方法,如果元素有申請堆棧的內存,需要換另外一種方法刪除,因為需要先獲取元素,釋放元素指向的申請內存后,才能做刪除操作,不然會造成內存泄漏。
(2)刪除全部元素
while(pVector->size() != 0)
{
//pop_back方法無返回值
pVector->pop_back();
//刪除操作避免大量移動的方法,如果元素有申請堆棧的內存,不可用此方法
}
?
(3)調用clear函數刪除全部元素
a.clear()
?
(3)另外一種刪除全部元素的方法
這種方法針對元素有另外申請內存的情況下比較有用,比如元素是一個結構體或者對象,有成員p申請了堆內存,刪除元素前要釋放內存。
VectorT::iterator iVector = a.begin();
while(iVector != a.end())
{
delete (*iVector)->p;
iVector = a.erase(iVector);
//執行erase后,iVector將指向刪除的元素的下一個元素
}
?
?
6.刪除一個不一定是末尾的元素
先執行find查找value的值,在vector容器里面就刪除
?
VectorType::iterator iVector = std::find(a.begin(), ?a.end(), value);
?
if(iVector != a.end())
{
a.erase(iVector); //參數只能是迭代器
//std::cout<<" erase success "<< m<<std::endl;
}
7.插入一個元素
?
single element (1)
iterator insert (iterator position, const value_type& val);
fill (2)
????void insert (iterator position, size_type n, const value_type& val);
range (3)
template <class InputIterator>_x000D_ ???void insert (iterator position, InputIterator first, InputIterator last);
?
Vector向量的元素插入有三種方法。
(1)?insert (iterator position, const value_type& val)傳入的參數是迭代器的位置和需要插入的元素val。
Position可以是a.begin(),也可以是a.end(),或者這兩者中間的一個迭代器位置
?
?(2)void insert (iterator position, size_type n, const value_type& val);
在position位置開始,插入n個值為val的元素
?
(3)void insert (iterator position, InputIterator first, InputIterator last);
在position位置插入first(比如數組首地址)到last(比如數組首地址+n)之間的元素。
?
最常用的是insert (iterator position, const value_type& val);
?
8.capacity()和size()
容器對象調用size()可以知道當前容器里面有多少個元素,對vector向量對象來說,就是當前存放的元素的個數。
容器對象調用capacity()函數,可以知道容器的大小,也就是當前容器對象可用容納的元素個數。Capacity隨著向量的元素的增加而增加,當size() ==capacity()時,容器會自動重新alloc內存,增加一倍的內存。
?
9.排序
?
default (1)
template <class RandomAccessIterator>??void sort (RandomAccessIterator first, RandomAccessIterator last);
custom (2)
template <class RandomAccessIterator, class Compare>??void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp);
?
?
?std::sort( a.begin() , a.end() );
也可以是
?
?std::sort( a.begin() , a.begin + 4 );
?
反正就是傳入排序的位置范圍。
默認是升序
另外可以實現自己的排序函數Compare comp
?void sort (RandomAccessIterator first, RandomAccessIterator last, Compare comp);
10.釋放vector容器自身的內存
通過調用erase函數刪除元素或者調用clear函數,雖然清楚了vector容器里面的元素,但是并沒有釋放調容器本身的內存,就好像一個裝滿了腰果的瓶子,把里面的腰果倒掉了,瓶子并沒有被銷毀。
?
釋放方法:
比如定義有對象a,有10個元素在里面。
?typedef std::vector < ?Type > ?VectorT;
???VectorT ?a(10);
?
std::vector < Type >().swap( ?a ?);
代碼實例:
#include <iostream> #include <vector> #include <algorithm> typedef unsigned long U32;typedef std::vector < U32 > VectorType;int add(VectorType *pVector ,U32 m) {if(NULL == pVector){return -1;}pVector->push_back(m); //添加元素到末尾//無返回值return 0; }int remove(VectorType *pVector ,U32 m) {if(NULL == pVector){return -1;}VectorType::iterator iVector = std::find(pVector->begin(), pVector->end(), m); if(iVector != pVector->end()){pVector->erase(iVector); //參數只能是迭代器std::cout<<" erase success "<< m<<std::endl;}else{std::cout<<" not find in pVector"<< m<<std::endl;}return 0; }int remove_last_one(VectorType *pVector ) {if(NULL == pVector){std::cout<<"pVector is NULL,(remove_last_one)"<<std::endl;return -1;}if(pVector->empty()){std::cout<<"pVector is empty , remove_last_one"<<std::endl;return -1;}pVector->pop_back(); //刪除最后一個元素return 0; }int remove_all(VectorType *pVector ) {if(NULL == pVector){std::cout<<"pVector is NULL,(remove_all)"<<std::endl;return -1;}#if 0VectorType::iterator iVector = pVector->begin();//;std::find(pVector->begin(), pVector->end(), m); while(iVector != pVector->end()){std::cout<<" remove_all a "<< (*iVector)<<std::endl;iVector = pVector->erase(iVector);std::cout<<" remove_all b "<< (*iVector)<<std::endl;}#endif //這種做法導致大量的移動操作,但好處是如果元素是指針,我們可以先把內存//釋放了再刪除//erase的返回值是指向刪除元素的下一個元素的迭代器指針#if 1while(pVector->size() != 0){//pop_back方法無返回值pVector->pop_back();//刪除操作避免大量移動的方法,如果元素有申請堆棧的內存,不可用此方法} #endif #if 0//以下方法不可行VectorType::iterator iVector = pVector->end();//;std::find(pVector->begin(), pVector->end(), m); while(iVector != pVector->begin()){std::cout<<" remove_all a "<< (*iVector)<<std::endl;iVector = pVector->erase(iVector);std::cout<<" remove_all b "<< (*iVector)<<std::endl;} #endifreturn 0; }void dump(VectorType *pVector) {if(NULL == pVector){std::cout<<"pVector is NULL"<<std::endl;return ;}if(pVector->empty()) //判斷是否為空{std::cout<<"pVector is empty"<<std::endl;return ;}VectorType::iterator iVector = pVector->begin(); while(iVector != pVector->end()) { std::cout<<" dump "<< (*iVector)<<std::endl;++iVector; } return ; }int find(VectorType *pVector ,U32 m,int *pnFlag) {if(NULL == pVector || NULL == pnFlag){return -1;}*pnFlag = 0;VectorType::iterator iVector = std::find(pVector->begin(), pVector->end(), m); if(iVector != pVector->end()){std::cout<<" find success "<< m<<std::endl;*pnFlag = 1;return 0;}else{std::cout<<" not find in pVector"<< m<<std::endl;return -1;} }int insert_one(VectorType *pVector ,U32 val, int iPlace) {int i = 0;if(NULL == pVector || iPlace < 0){std::cout<<"insert_one param error"<<std::endl;return -1;}VectorType::iterator iVector = pVector->begin(); while(iVector != pVector->end()) { //std::cout<<" dump "<< (*iVector)<<std::endl;if(i == iPlace){iVector = pVector->insert(iVector , val); //此時insert的返回值是迭代器,插入成功后iVector指向插入的位置std::cout<<" insert_one after iVector point "<< (*iVector)<<std::endl;return 0;}i++;++iVector; } iVector = pVector->insert(pVector->end() , val); return 0; }int print_size(VectorType *pVector) {if(NULL == pVector){std::cout<<"pVector is NULL"<<std::endl;return -1;}if(pVector->empty()) //判斷是否為空{std::cout<<"pVector is empty (get_size)"<<std::endl;}std::cout<<"pVector capacity: "<< pVector->capacity() << " size:"<<pVector->size()<<std::endl;return 0; }int main() {VectorType vArray(20);//初始化20個元素的容器int nFlag =0;vArray.clear();//把容器的里的元素全部清掉//添加元素add(&vArray,5);add(&vArray,4);add(&vArray,3);add(&vArray,2);add(&vArray,1);add(&vArray,0);//插入一個元素 值為6U32 val = 6;int place = 2;insert_one(&vArray, val, place);//打印capatity sizeprint_size(&vArray);dump(&vArray);//刪除末尾元素remove_last_one(&vArray);print_size(&vArray);U32 element = 1;find(&vArray ,element,&nFlag);remove(&vArray ,element);find(&vArray ,element,&nFlag);element = 8;//移除元素elementremove(&vArray ,element);//查找elementfind(&vArray ,element,&nFlag);//移除所有元素remove_all(&vArray);dump(&vArray);print_size(&vArray);std::vector < U32 >().swap(vArray);//銷毀向量的做法print_size(&vArray);}
?
?
總結
以上是生活随笔為你收集整理的C++ vector的初始化、添加、遍历、插入、删除、查找、排序、释放操作的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: list插入/删除元素
- 下一篇: emplace与insert