演算法學習之路|用C++刷演算法會用到的STL(一)——vector
STL是Standard Template Library的簡稱,中文名標準模板庫。
從根本上說,STL是一些“容器”的集合,這些“容器”有list,vector,set,map等,STL也是演算法和其他一些元件的集合。STL現在是C++的一部分,因此不用安裝額外的庫檔案。
在C++標準中,STL被組織為下面的17個標頭檔案:
<algorithm>、<deque>、<functional>、<iterator>、<array>、<vector>、<list>、<forward_list>、<map>、<unordered_map>、<memory>、<numeric>、<queue>、<set>、<unordered_set>、<stack>和<utility>。
一、vector
1. vector的自我介紹
- vector是向量的意思,可以理解為“可變長度的陣列”。
- 就像陣列一樣,vector也採用的連續儲存空間來儲存元素。也就是意味著可以採用下標對vector的元素進行訪問,和陣列一樣高效。但是又不像陣列,它的大小是可以動態改變的,而且它的大小會被容器自動處理。
- 相當於一個動態陣列,在你不知道需要的陣列有多大時可以使用它來節省很多空間。在ACM中常常會出現記憶體溢位(out of memory)的問題導致WA(wrong answer),而使用vector就能節省很多記憶體。
- 使用vector要在程式開頭加上#include<vector>來包含需要的標頭檔案,還有加上“using namespace std;”,這樣就可以在程式碼中使用vector了。
2.vector的定義
- 定義一個vector:
vector<typename> vectorname;
- 這個定義相當於定義了一個一維的陣列vectorname[SIZE],只不過這個SIZE的長度是可以改變的,隨著你“加入”進去數的個數而改變。所謂“可變長度的陣列”。
- 和一維的陣列一樣,這裡的typename可以是任何的型別,如int,double,char,string,long long ,也可以是結構體,甚至是STL的容器如vector,set,queue,stack等。注意!如果typename也是一個容器的話,比如vector<vector<int> > vectorname,要在兩個`<`符號之間加上一個空格,否則編譯時會誤以為是位移操作。
3.vector的建立
vector<double> vec1; // 建立一個空的double向量
vector<int> vec(66); // 建立一個初始大小為66的int向量
vector<double> vec2(vec1); // 建立一個double型的vec2,並用vec1去初始化vec2
vector<char> vec(10,`k`); // 建立一個含有10個char型資料的vector,並全部初始化為`k`
vector<int> vec(10,1);//建立一個初始大小為10的並且值都是1的vector
vector<int> vec2(vec1.begin(),vec1.begin()+3);//用向量vec1的第0個到第2個值初始化vec2
int arr[5] = {1, 2, 3, 4, 5};
vector<int> vec(arr, arr + 5); //將arr陣列的元素用於初始化vec向量,末尾指標指向結束元素
//的下一個
vector<int> vec(&arr[1], &arr[4]); //將arr[1]~arr[4]範圍內的元素作為vec的初始值,不包含arr[4],
//原因如上
4.特別的,元素為vector的vector陣列
- (其實就是vector的二維陣列)和vector陣列! 如果typename是vector,那麼就這麼定義vector<vector<int> > vectorname; 注意在相鄰的`>`之間要加空格。 這個就像二維陣列的定義,其中一維是一個元素是vector的vector陣列。可以把vector陣列 當作兩個維長度都可變的二維陣列理解。vector陣列的定義vector<typename> Arrayname[arraySize]; 比如,vector<int> vec[66]; 這樣Arrayname[0]~Arrayname[arraySize-1]中每一個都是vector容器。 而vector<vector<int> > vectorname不同的地方時,前者的第一維長度已經固定為arraySize了, 後者卻是兩個維度都可變長的陣列。哈哈哈,用你的大腦,發揮空間想象能力,出現了什麼圖形? 很神奇是不是!
5.vector容器內元素的訪問形式
- vector一般有兩種訪問形式:通過下標訪問或者是通過迭代器訪問。
(1)通過下標訪問
和訪問普通陣列是一樣的,一個已經定義的vector<typename> vec的vector容器,直接訪問vec[index]就可以了(比如 vec[0],vec[1])。需要注意的一點是,首先這個vec得有size!!!橋黑板!什麼意思呢?就是如果一開始你定義了 比如vector<int> vec1;直接使用vec[0]是不對的!因為裡面還沒有長度啊!開始用的時候我就經常犯這個錯誤(尷尬) 。所以可以通過下標訪問的範圍是從0~vec.size()-1.
(2)通過迭代器訪問
- 啥叫迭代器啊?好可怕~就理解為指標吧,不去考慮細節,兩者是一樣的(包括在java中最近遇見的引用,這簡直是三胞胎!)。 定義如下: vector<typename>::iterator it;(it就是變數名,一般預設都寫成it) 這樣it就是一個vector<typename>::iterator 型的變數了(hhh,這個名字好長啊),其中,typename就是定義vector時 寫的型別。比如: vector<double>::iterator it; vector<int> vec; vector<int>::iterator it2; it2=vec.begin();(或者合成一條:vector<int>::iterator it2=vec.begin(); ) 這樣就得到了迭代器it(or it2),並且可以通過*it來訪問vector裡的元素。
vector<int> vec;
vector<int>::iterator it;
for (it = vec.begin(); it != vec.end(); it++)//vector的迭代器不支援it<vec.end()寫法,因此迴圈中只能用it!=end()
cout << *it << endl;
//或者
vector<int>::iterator it=vec.begin();
for(int i=0;i<vec.size();i++){
printf("%d ",*(it+i));//橋黑板!!在STL容器中,只有vector和string這兩個好基友,才允許使用vev.begin()+3這種迭代器加上整
//數的寫法,只有這倆。
//從這裡可以看出,vec[i]和*(vec.begin()+i)是等價的
}
//或者
for (size_t i = 0; i < vec.size(); i++) {
cout << vec.at(i) << endl;//見下文分解
}
好了,終於說完訪問形式了,可以介紹基本操作啦!
6.vector的基本操作
(1)對容量的操作
- 得到向量的大小: vec.size();
- 得到向量最大可以是多大: vec.max_size();
- 重新設定容器size的大小: vec.resize(num);
- 重新設定容器capacity的大小: vec.reserve(num);
- 向量真實大小: vec.capacity();
- 判斷向量是否為空: vec.empty();
注:關於resize()和reverse(),我覺得記住一點就行了,容器呼叫resize()函式後, 所有的空間都已經初始化了,所以可以直接訪問。比如: vector<int> vet; vec.resize(100); vec[0]=1;//合法語句! 而reserve()函式預分配出的空間沒有被初始化,所以不可訪問。 推薦一個關於resize()和reserve()寫的不錯的部落格vector中resize()和reserve()區別
(2)修改元素
- 多個元素賦值: vec.assign(); //類似於初始化時用陣列進行賦值
- 末尾新增元素: vec.push_back(i)//在末尾新增元素i
- 末尾刪除元素: vec.pop_back();
- 任意位置插入元素: vec.insert(it,x);
- 用來向vector的任意迭代器(見上文)it處插入一個元素x,時間複雜度O(N);
- 任意位置刪除元素: vec.erase();
- erease(it)即刪除迭代器為it處的元素;
- erase(first,last)即刪除[first,last)內的所有元素;(老美的左閉右開,你懂的)
- 交換兩個向量的元素: vec.swap();//不多講,用的真的很少。同樣,推薦部落格vector利用swap()函式進行記憶體的釋放
(3)驚現迭代器
開始指標:vec.begin();
末尾指標:vec.end(); //指向最後一個元素的下一個位置
指向常量的開始指標: vec.cbegin(); //意思就是不能通過這個指標來修改所指的內容,但還是可以通過其他方式修改的,而且指標也是可以移動的。(用的很少,不妨先忽略吧)
指向常量的末尾指標: vec.cend();(同上,不多說)
(4)元素的訪問
下標訪問: vec[1]; //橋黑板!!並不會檢查是否越界
at方法訪問: vec.at(1); //以上兩者的區別就是at會檢查是否越界,是則丟擲out of range異常
訪問第一個元素: vec.front();
訪問最後一個元素: vec.back();
返回一個指標: int* p = vec.data(); //可行的原因在於vector在記憶體中就是一個連續儲存的陣列,所以可以返回一個指標指向這個陣列。這是是C++11的特性。(可忽略)
(5)一些演算法
- 遍歷元素
Cvector<int>::iterator it;
for (it = vec.begin();it != vec.end(); it++)
cout << *it << endl;
//或者
for (size_t i = 0; i < vec.size(); i++) {
cout << vec.at(i) << endl;
}
- 元素翻轉
C#include <algorithm>
reverse(vec.begin(), vec.end());
- 元素排序
C#include <algorithm>
sort(vec.begin(), vec.end()); //採用的是從小到大的排序
//如果想從大到小排序,可以採用上面反轉函式,也可以採用下面方法:
bool Comp(const int& a, const int& b) {//固定套路,要加上const,意思是不能修改引用
return a > b;
}
sort(vec.begin(), vec.end(), Comp);
7.vector的用武之地
(1)儲存資料
- vector本身可以作為陣列使用,而且在一些元素個數不確定的場合可以很好的節省空間。
- 有些場合需要根據一些條件把部分資料輸出在同一行,資料中間用空格隔開。由於輸出的資料個數是不確定的,為了跟方便的處理最後一個滿足條件的資料後面不輸出額外的空格,可以先用vector記錄所有需要輸出的資料,然後一次性輸出。
- 有強大的方法可以呼叫(媽呀,java學多了,請不要噴我,暫且就叫方法吧,介紹如上vector的基本操作(1)~(4))
( 2 )用鄰接表儲存圖
- 使用vector實現鄰接表可以有效避免指標,而且更容易把握。
哈哈哈,終於結束啦(喝口水)。
好了,說了這麼多,當然廢話也不少~~
來幾道題目吧!
PAT A1039. Course List for Student (25)
PAT A1047. Student List for Course (25)
參考:C++ STL之vector用法總結
《演算法筆記》(胡凡,曽磊)
相關文章
- C++ STL -- vectorC++
- C++ 學習筆記(1):STL、Vector 與 SetC++筆記
- 【演算法學習】STL庫 大小根堆的用法演算法
- 強化學習之路一 QLearning 演算法強化學習演算法
- 學習java一定會用到的應用軟體Java
- 最詳細STL(一)vector
- STL容器---Vector
- 跟我學C++中級篇——STL的學習C++
- C++進階:STL演算法9--邊界C++演算法
- STL---vector(向量)
- STL使用篇__vector
- C++ 學習筆記之——STL 庫 queueC++筆記
- 初探STL容器之Vector
- STL:vector用法總結
- C++STL之Vector向量詳解,用法和例子 一起學習 一起加油C++
- 小白機器學習基礎演算法學習必經之路(下)機器學習演算法
- C++學習筆記 — STL標準模板庫C++筆記
- 學習Pytho爬蟲常常會用到的一些庫!爬蟲
- STL學習
- STL原始碼剖析——vector容器原始碼
- STL-Vector容量問題:
- STL----vector注意事項
- 你是否 STL 不會用一點?
- 一個演算法工程師的學習演算法工程師
- 演算法學習筆記1語法 (C++組)演算法筆記C++
- 機器學習 - 競賽網站,演算法刷題網站機器學習網站演算法
- 美顏sdk趣味拍攝功能會用到哪些演算法?演算法
- C++ vector 的一些操作C++
- 太極1:STL:vector和string
- 演算法學習演算法
- 機器學習演算法一覽機器學習演算法
- 刷演算法中途複習基礎知識演算法
- 開始刷演算法演算法
- 拿下史丹佛和劍橋雙offer,00後的演算法學習之路演算法
- BFS洛谷P1135 奇怪的電梯(我的演算法學習之路)演算法
- 演算法學習?挑戰高薪的必經之路!讓面試官滿意的排序演算法(圖文解析)演算法高薪面試排序
- C++的vector容器C++
- 演算法學習筆記:Kosaraju演算法演算法筆記
- 演算法學習 - 基礎排序演算法演算法排序