C++ 容器1 vector
容器分類:
1.順序容器有以下三種:可變長動態數組 vector、雙端隊列 deque、雙向鏈表 list。
它們之所以被稱為順序容器,是因為元素在容器中的位置同元素的值無關,即容器不是排序的。將元素插入容器時,指定在什么位置(尾部、頭部或中間某處)插入,元素就會位于什么位置。
2.關聯容器有以下四種:set、multiset、map、multimap。關聯容器內的元素是排序的。插入元素時,容器會按一定的排序規則將元素放到適當的位置上,因此插入元素時不能指定位置。
默認情況下,關聯容器中的元素是從小到大排序(或按關鍵字從小到大排序)的,而且用<運算符比較元素或關鍵字大小。因為是排好序的,所以關聯容器在查找時具有非常好的性能。
3.除了以上兩類容器外,STL 還在兩類容器的基礎上屏蔽一部分功能,突出或增加另一部分功能,實現了三種容器適配器:棧 stack、隊列 queue、優先級隊列 priority_queue。
容器都是類模板。它們實例化后就成為容器類。用容器類定義的對象稱為容器對象。
例如,vector<int>是一個容器類的名字,vector<int> a;就定義了一個容器對象 a,a 代表一個長度可變的數組,數組中的每個元素都是 int 類型的變量;vector<double> b;定義了另一個容器對象 b,a 和 b 的類型是不同的。
- Vector<類型>標識符
- Vector<類型>標識符(最大容量)
- Vector<類型>標識符(最大容量,初始所有值)
- Int i[5]={1,2,3,4,5}
Vector<類型>vi(I,i+2);//得到i索引值為3以后的值 - Vector< vector< int> >v; 二維向量//這里最外的<>要有空格。否則在比較舊的編譯器下無法通過
任何兩個容器對象,只要它們的類型相同,就可以用 <、<=、>、>=、==、!= 進行詞典式的比較運算。假設 a、b 是兩個類型相同的容器對象,這些運算符的運算規則如下。
- a == b:若 a 和 b 中的元素個數相同,且對應元素均相等,則
a == b的值為 true,否則值為 false。元素是否相等是用==運算符進行判斷的。 - a<b:規則類似于詞典中兩個單詞比較大小,從頭到尾依次比較每個元素,如果發生 a 中的元素小于 b 中的元素的情況,則
a<b的值為 true;如果沒有發生 b 中的元素小于 a 中的元素的情況,且 a 中的元素個數比 b 少,a<b的值也為 true;其他情況下值為 false。元素比較大小是通過<運算符進行的。 - a != b:等價于 !(a == b)。
- a > b:等價于 b < a。
- a <= b:等價于 !(b < a)。
- a >= b:等價于 !(a < b)。
所有容器都有以下兩個成員函數:
- int size():返回容器對象中元素的個數。
- bool empty():判斷容器對象是否為空。
順序容器和關聯容器還有以下成員函數:
- begin():返回指向容器中第一個元素的迭代器。
- end():返回指向容器中最后一個元素后面的位置的迭代器。
- rbegin():返回指向容器中最后一個元素的反向迭代器。
- rend():返回指向容器中第一個元素前面的位置的反向迭代器。
- erase(...):從容器中刪除一個或幾個元素。該函數參數較復雜,此處省略。
- clear():從容器中刪除所有元素。
如果一個容器是空的,則 begin() 和 end() 的返回值相等,rbegin() 和 rend() 的返回值也相等。
順序容器還有以下常用成員函數:
- front():返回容器中第一個元素的引用。
- back():返回容器中最后一個元素的引用。
- push_back():在容器末尾增加新元素。
- pop_back():刪除容器末尾的元素。
- insert(...):插入一個或多個元素。該函數參數較復雜,此處省略。
--------vector 總結
vector是順序容器的一種。vector 是可變長的動態數組,支持隨機訪問迭代器,所有 STL 算法都能對 vector 進行操作。要使用 vector,需要包含頭文件 vector。
在 vector 容器中,根據下標隨機訪問某個元素的時間是常數,在尾部添加一個元素的時間大多數情況下也是常數,總體來說速度很快。
在中間插入或刪除元素時,因為要移動多個元素,因此速度較慢,平均花費的時間和容器中的元素個數成正比。
在 vector 容器中,用一個動態分配的數組來存放元素,因此根據下標訪問某個元素的時間是固定的,與元素個數無關。
vector 容器在實現時,動態分配的存儲空間一般都大于存放元素所需的空間。例如,哪怕容器中只有一個元素,也會分配 32 個元素的存儲空間。這樣做的好處是,在尾部添加一個新元素時不必重新分配空間,直接將新元素寫入適當位置即可。在這種情況下,添加新元素的時間也是常數。
但是,如果不斷添加新元素,多出來的空間就會用完,此時再添加新元素,就不得不重新分配內存空間,把原有內容復制過去后再添加新的元素。碰到這種情況,添加新元素所花的時間就不是常數,而是和數組中的元素個數成正比。
至于在中間插入或刪除元素,必然涉及元素的移動,因此時間不是固定的,而是和元素個數有關。
vector 有很多成員函數,常用的如下所示:
vector()//無參構造函數,將容器初始化為空
vector(int n)//將容器初始化為有 n 個元素
vector(int n, const T & val)//假定元素的類型是 T,此構造函數將容器初始化為有 n 個元素,每 個元素的值都是 val
vector(iterator first, iterator last)//first 和 last 可以是其他容器的迭代器。一般來說,本構造函數初始化的結果就是將 vector 容器的內容變成與其他容器上的區間 [first, last) —致
void clear()//刪除所有元素
bool empty()//判斷容器是否為空
void pop_back()//刪除容器末尾的元素
void push_back( const T & val)//將 val 添加到容器末尾
int size()//返回容器中元素的個數
T & front()//返回容器中第一個元素的引用
T & back()//返回容器中最后一個元素的引用
iterator insert(iterator i, const T & val)//將 val 插入迭代器 i 指向的位置,返回 i
iterator insert( iterator i, iterator first, iterator last)//將其他容器上的區間 [first, last) 中的元素插入迭代器 i 指向的位置
iterator erase(iterator i)//刪除迭代器 i 指向的元素,返回值是被刪元素后面的元素的迭代器
iterator erase(iterator first, iterator last)//刪除容器中的區間 [first, last)
void swap( vector <T> & v)//將容器自身的內容和另一個同類型的容器 v 互換
下面的程序演示了 vector 的基本用法。 (代碼涉及到模板內容,對模板的介紹參照如下鏈接:)
https://blog.csdn.net/m0_37957160/article/details/104715659
#include <iostream>
#include <vector> //使用vector需要包含此頭文件
using namespace std;
template <class T>
void PrintVector(const vector <T> & v)
{ //用于輸出vector容器的全部元素的函數模板typename vector <T>::const_iterator i;//typename 用來說明 vector <T>::const_iterator 是一個類型,在 Visual Studio 中不寫也可以for (i = v.begin(); i != v.end(); ++i)cout << *i << " ";cout << endl;
}
int main()
{int a[5] = { 1, 2, 3, 4, 5 };vector <int> v(a, a + 5); //將數組a的內容放入vcout << "1) " << v.end() - v.begin() << endl; //兩個隨機迭代器可以相減,輸出:1)5cout << "2)"; PrintVector(v); //輸出:2)1 2 3 4 5v.insert(v.begin() + 2, 13); //在 begin()+2 位置插人 13cout << "3)"; PrintVector(v); //輸出:3)1 2 13 3 4 5v.erase(v.begin() + 2); //刪除位于 begin()+2 位置的元素cout << "4)"; PrintVector(v); //輸出:4)1 2 3 4 5vector<int> v2(4, 100); //v2 有 4 個元素,都是 100v2.insert(v2.begin(), v.begin() + 1, v.begin() + 3); //將v的一段插入v2開頭cout << "5)v2:"; PrintVector(v2); //輸出:5)v2:2 3 100 100 100 100v.erase(v.begin() + 1, v.begin() + 3); //刪除 v 上的一個區間,即 [2,3)cout << "6)"; PrintVector(v); //輸出:6)1 4 5return 0;
}
程序中的 PrintVector 模板演示了將容器的引用作為函數參數的用法。
vector 還可以嵌套以形成可變長的二維數組。例如:
#include <iostream>
#include <vector>
using namespace std;
int main()
{ vector<vector<int> > v(3); //v有3個元素,每個元素都是vector<int> 容器for(int i = 0;i < v.size(); ++i)for(int j = 0; j < 4; ++j)v[i].push_back(j);for(int i = 0;i < v.size(); ++i) {for(int j = 0; j < v[i].size(); ++j)cout << v[i][j] << " ";cout << endl;}return 0;
}
程序的輸出結果是:
0 1 2 3
0 1 2 3
0 1 2 3vector< vector<int> > v(3);(在其他編譯器中,int后邊兩個> >要用空格隔開,否則有的編譯器會把他們當作>>運算符編譯出錯)定義了一個 vector 容器,該容器中的每個元素都是一個 vector <int> 容器。即可以認為,v 是一個二維數組,一共 3 行,每行都是一個可變長的一維數組。
(1)a.assign(b.begin(), b.begin()+3); //b為向量,將b的0~2個元素構成的向量賦給a
(2)a.assign(4,2); //是a只含4個元素,且每個元素為2
(3)a.back(); //返回a的最后一個元素
(4)a.front(); //返回a的第一個元素
(5)a[i]; //返回a的第i個元素,當且僅當a[i]存在2013-12-07
(6)a.clear(); //清空a中的元素
(7)a.empty(); //判斷a是否為空,空則返回ture,不空則返回false
(8)a.pop_back(); //刪除a向量的最后一個元素
(9)a.erase(a.begin()+1,a.begin()+3); //刪除a中第1個(從第0個算起)到第2個元素,也就是說刪除的元素從a.begin()+1算起(包括它)一直到a.begin()+ 3(不包括它)
(10)a.push_back(5); //在a的最后一個向量后插入一個元素,其值為5
(11)a.insert(a.begin()+1,5); //在a的第1個元素(從第0個算起)的位置插入數值5,如a為1,2,3,4,插入元素后為1,5,2,3,4
(12)a.insert(a.begin()+1,3,5); //在a的第1個元素(從第0個算起)的位置插入3個數,其值都為5
(13)a.insert(a.begin()+1,b+3,b+6); //b為數組,在a的第1個元素(從第0個算起)的位置插入b的第3個元素到第5個元素(不包括b+6),如b為1,2,3,4,5,9,8 ,插入元素后為1,4,5,9,2,3,4,5,9,8
(14)a.size(); //返回a中元素的個數;
(15)a.capacity(); //返回a在內存中總共可以容納的元素個數
(16)a.resize(10); //將a的現有元素個數調至10個,多則刪,少則補,其值隨機
(17)a.resize(10,2); //將a的現有元素個數調至10個,多則刪,少則補,其值為2
(18)a.reserve(100); //將a的容量(capacity)擴充至100,也就是說現在測試a.capacity();的時候返回值是100.這種操作只有在需要給a添加大量數據的時候才 顯得有意義,因為這將避免內存多次容量擴充操作(當a的容量不足時電腦會自動擴容,當然這必然降低性能)
(19)a.swap(b); //b為向量,將a中的元素和b中的元素進行整體性交換
(20)a==b; //b為向量,向量的比較操作還有!=,>=,<=,>,<
三、順序訪問vector的幾種方式,舉例說明如下:
(1)向向量a中添加元素
1、直接添加
vector<int> a;
for(int i=0;i<10;i++)
{a.push_back(i);
}
2、也可以從數組中選擇元素向向量中添加
int a[6]={1,2,3,4,5,6};
vector<int> b;
for(int i=1;i<=4;i++)
{ b.push_back(a[i]);
}
?
3、也可以從現有向量中選擇元素向向量中添加
int a[6]={1,2,3,4,5,6};
vector<int> b;
vector<int> c(a,a+4);
for(vector<int>::iterator it=c.begin();it<c.end();it++)
{b.push_back(*it);
}
4、也可以從文件中讀取元素向向量中添加
ifstream in("data.txt");
vector<int> a;
for(int i; in>>i)
{ a.push_back(i);
}
5、錯誤做法
vector<int> a;
for(int i=0;i<10;i++)
{a[i]=i;
}
//這種做法以及類似的做法都是錯誤的。剛開始我也犯過這種錯誤,后來發現,下標只能用于獲取已存在的元素,而現在的a[i]還是空的對象
(2)從向量中讀取元素
1、通過下標方式讀取
int a[6]={1,2,3,4,5,6};
vector<int> b(a,a+4);
for(int i=0;i<=b.size()-1;i++)
{cout<<b[i]<<" ";
}
2、通過遍歷器方式讀取
int a[6]={1,2,3,4,5,6};
vector<int> b(a,a+4);
for(vector<int>::iterator it=b.begin();it!=b.end();it++)
{cout<<*it<<" ";
}
四、幾種重要的算法,使用時需要包含頭文件:
#include<algorithm>
(1)sort(a.begin(),a.end()); //對a中的從a.begin()(包括它)到a.end()(不包括它)的元素進行從小到大排列
(2)reverse(a.begin(),a.end()); //對a中的從a.begin()(包括它)到a.end()(不包括它)的元素倒置,但不排列,如a中元素為1,3,2,4,倒置后為4,2,3,1
(3)copy(a.begin(),a.end(),b.begin()+1); //把a中的從a.begin()(包括它)到a.end()(不包括它)的元素復制到b中,從b.begin()+1的位置(包括它)開 始復制,覆蓋掉原有元素
(4)find(a.begin(),a.end(),10); //在a中的從a.begin()(包括它)到a.end()(不包括它)的元素中查找10,若存在返回其在向量中的位置
參考連接:https://blog.csdn.net/wkq0825/article/details/82255984
?
?
?
?
?
?
?
?
?
?
?
總結
以上是生活随笔為你收集整理的C++ 容器1 vector的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: C++:模板
- 下一篇: c++:文件操作1 文件的打开