[LeetCode刷題筆記] C++ vector常用操作

在[1]對常用的STL容器進行了概覽,筆者在刷題過程中經常需要查詢一些STL容器的函數,實爲不便,因此在此對STL容器中常用的操作進行筆記。


std::vector是一種線性數組,每個元素的數據類型都相同,不過和一般的靜態的數組不同的是,其允許通過插入元素,刪除元素實現所謂的動態數組,是常用的數據結構,類似於python中的列表list

其涉及到的常用操作有幾大類:

  1. 初始化操作,涉及到初始化數組時候的一些操作。
  2. 檢索index,對指定位置的元素進行讀取或者修改。
  3. 插入元素,在某個指定位置或者某個位置區間插入特定的元素。
  4. 刪除元素,在某個特定的位置或者區間刪除元素。
  5. 遍歷元素,屬於檢索元素的一種,不過其操作具有一般性,因此特地拿出來討論。
  6. 其他操作,包括對元素進行排序sort,檢查是否有特定元素等。

接下來進行概覽和舉例說明。
PS: vector.begin()指向vector的第一個元素的位置,vector.end()指向vector的最後一個元素的後一個位置。


1. 初始化操作

vector的構造函數爲:

template < class T, class Alloc = allocator<T> > class vector; // generic template

可以用vector<data_type> 選擇元素的數據類型。一般有如下幾種常用的初始化方式:

vector<int> first; // 空的vector,只是一個列表的頭,裏面沒有元素
vector<int> second (4, 100); // 初始化一個具有4個元素的vector,每個元素的值都是100
vector<int> third (second.begin(), second.end()); // 通過其他vector的迭代器的方式,進行拷貝複製初始化
vector<int> fourth (third); // 直接對其他vector的拷貝複製

int myints[] = {16, 2, 77};
vector<int> fifth (myints, myints+sizeof(myints) / sizeof(int)); // 將數組轉化成vector,需要提供的是數組的首地址和地址偏移。

vector<int> sixth = {1,5,4,6}; // 指定內容進行構造,內容爲1,5,4,6的vector

在作爲函數返回或者傳參數時,可以進行匿名的構造,也就是不需要給予變量名字,如:

return vector<int>(); // 此時返回的就是空的vector
return vector<int>{1,4,5}; // 此時返回的是{1,4,5}
foo(vector<int>{1,4,5})

也可以實現多重vector

vector< vector<int> > vars;
// 二維vector的初始化
int size = 10;
vector<vector<int>> vars(size, vector<int>(size, 0)); // (size,size)的矩陣,元素全部是0

2. 索引元素

索引其元素和索引一般的數組元素相似

vector<int> first = {1,3,4,5,6};
first[1]; // 直接索引
first[1] = 0; //直接可以修改
first.at(1) = 0; // 也可以通過函數索引
*(first.begin()+3); // 也可以通過對迭代器取值得到,而且可以提供偏移比如+3.
first.back(); // 獲取vector的最後一個元素

3. 遍歷元素

遍歷元素可以通過以下方式進行:

  1. 採用迭代器
vector<int> vars = {1,3,5,6,7,8};
for (vector<int>::iterator it = vars.begin(); it != vars.end(); ++it){
	*it = 10; // 遍歷每一個元素
}

通過對迭代器進行加減可以實現遍歷某一區間的元素:

vector<int> vars = {1,3,5,6,7,8};
for (vector<int>::iterator it = vars.begin()+1; it != vars.end()-1; ++it){
	*it = 10; // 遍歷每一個元素
}

當然如果你用auto關鍵字,你也可以這樣:

vector<int> vars = {1,3,5,6,7,8};
for (auto it = vars.begin(); it != vars.end(); ++it){
	*it = 10; // 遍歷每一個元素
}
vector<int> vars = {1,3,5,6,7,8};
for (auto &v:vars)
	cout << v << endl;

這種方法對於遍歷所有元素很方便

  1. 用索引的方式遍歷,這種方式是最直接的
vector<int> vars = {1,3,5,6,7,8};
int vsize = vars.size();
for (int i = 0; i < vsize: ++i){
	vars[i];
}

4. 插入元素操作

對於線性的vector來說,如果是在最後一個位置添加一個元素,類似於python中的list.append(),那麼可以:

vector<int> vars ;
vars.push_back(10);

如果是需要在中間的某個位置插入元素,用insert():

vector<int> vars = {1,2,3,4,5};
vars.insert(vars.begin(), 100); // 插入單個元素,在vars的第0元素位置插入100,位置用迭代器表示
vars.insert(vars.begin(), 2, 100); // 插入多個相同的元素,此處插入2個100

vector<int> cop = {6,7,8};
vars.insert(vars.end(), cop.begin(), cop.end()); // 也可以進行vector之間的拼接

5. 刪除元素

vector<int> vars = {1,2,3,4,5,6};
vars.pop_back(); // 彈出最後一個元素,注意只是彈出,不返回其值,用vector.back()返回其值
vars.clear(); // 清空vector
auto iter = vars.erase(vars.begin()+1); 
// 刪除單個元素,指定迭代器,刪除後vector的大小減1,但是容量不變。
// 其返回一個迭代器,指向被刪除元素後的第一個元素。
auto iter = vars.erase(vars.begin(), vars.begin()+2); // 刪除一個範圍內的值,指定開頭,結尾的迭代器即可。

其中在algorithm頭文件中提供了remove操作,其本質是對vector中的值進行匹配,如果匹配到了,則移到vector的末端。
例如

std::vector<std::string> words { "one", "none","some", "all”, "none", "most","many"};
auto iter = std::remove(std::begin(words), std::end(words), "none");

此處第二句將會匹配words中的字符串none,並且檢查其後一個元素,如果是不符合none的,則把它前移,覆蓋掉前一個的none,就結果而言,vector中的最後的若干個元素都變成了none,因此這裏的remove並不是實質上的移除,而是移到了末尾的位置,並且將其設爲了空字符串。如果此時用vector.size()我們會發現其大小並沒有改變。
在這裏插入圖片描述
爲了釋放最後的無用的空間,我們結合erase,有:

words.erase(iter, words.end()); // 此處的iter是由remove返回的迭代器

6. 其他操作

其他常見的操作有sort排序,max_element求最大值, min_element求最小值, find查找值,swap交換值,distance查找值的位置等函數,這些函數在頭文件<algorithm>中。

  1. sort排序
vector<int> vars = {2,4,1,6,7,3,9};
sort(vars.begin(), vars.end()); // 默認是升序排列,輸出如 1,2,3,4,6,7,9
// 也可以指定特定的排序函數,取代默認的升序排序,甚至可以對非數值類型的數據結構進行排序。
bool sortFunc(const int &num1, const int &num2) {
	return num1 > num2 ; // 降序排序
	// return num1 < num2; 升序排序
	// 返回爲true的將會放置於之前,false的元素爲之後
}
sort(vars.begin(), vars.end(), sortFunc);
  1. max_element, min_element
vector<int> vars = {2,4,1,6,7,3,9};
auto iter = max_element(vars.begin(), vars.end()); // 返回的是迭代器,指向的是最大值的位置,需要取值的話加*取值。
int max_value = *iter;
auto iter = min_element(vars.begin(), vars.end()); // 返回的是迭代器,指向的是最小值的位置,需要取值的話加*取值。
int min_value = *iter;

通過指定特定比較函數,可以實現不同數據結構的比較,如:

struct node {
    int x, y;
};
bool cmp1(node a, node b) {
    return a.x > b.x;
}
vector<node> v1(3);
node max_node = *max_element(v1.begin(), v1.end(), cmp1);
  1. find查找值的位置
    此函數返回第一個匹配指定值的數據的位置。
vector<int> vars = {1,2,3,4,5,6};
int myints[] = {1,2,3,4,5,6};

int *p = find(myints, myints+6, 5); // 查找數值5的位置,如果找到了返回其位置的指針,否則將指向最後一個元素的下一個元素的位置,如
if (p != myints+6)
	cout << "found in myints at location :" << p-myints << endl;
else
	cout << "element not found in the arrays" << endl;
	
// 同樣的,對於vector也是適用的
vector<int>::iterator iter = find(vars.begin(), vars.end(), 5);
if (iter != iter.end())
	cout << "found in myints at location :" << iter-vars.begin() << endl;
else
	cout << "element not found in the arrays" << endl;
  1. distance求距離
    求指定的迭代器之間的元素距離,類似於指針地址詳見,該函數在頭文件<iterator>,如:
vector<int> vars = {1,2,3,4,5,6};
vector<int>::iterator iter = find(vars.begin(), vars.end(), 5);
cout << distance(vars.begin(), iter) << endl; // 類似於 iter-vars.begin()

Reference

[1]. https://blog.csdn.net/LoseInVain/article/details/104189784

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章