疯子的算法总结(三) STL Ⅱ迭代器(iterator) + 容器
一、迭代器(Iterator)
背景:指針可以用來(lái)遍歷存儲(chǔ)空間連續(xù)的數(shù)據(jù)結(jié)構(gòu),但是對(duì)于存儲(chǔ)空間費(fèi)連續(xù)的,就需要尋找一個(gè)行為類似指針的類,來(lái)對(duì)非數(shù)組的數(shù)據(jù)結(jié)構(gòu)進(jìn)行遍歷。
定義:迭代器是一種檢查容器內(nèi)元素并遍歷元素的數(shù)據(jù)類型。
迭代器提供對(duì)一個(gè)容器中的對(duì)象的訪問(wèn)方法,并且定義了容器中對(duì)象的范圍。
迭代器(Iterator)是指針(pointer)的泛化,它允許程序員用相同的方式處理不同的數(shù)據(jù)結(jié)構(gòu)(容器)。
(1)迭代器類似于C語(yǔ)言里面的指針類型,它提供了對(duì)對(duì)象的間接訪問(wèn)。
(2)指針是C語(yǔ)言中的知識(shí)點(diǎn),迭代器是C++中的知識(shí)點(diǎn)。指針較靈活,迭代器功能較豐富。
(3)迭代器提供一個(gè)對(duì)容器對(duì)象或者string對(duì)象的訪問(wèn)方法,并定義了容器范圍。
迭代器和指針的區(qū)別:
容器和string有迭代器類型同時(shí)擁有返回迭代器的成員。如:容器有成員begin和end,其中begin成員復(fù)制返回指向第一個(gè)元素的迭代器,而end成員返回指向容器尾元素的下一個(gè)位置的迭代器,也就是說(shuō)end指示的是第一個(gè)不合法地址,所以end返回的是尾后迭代器。
容器迭代器的使用
每種容器類型都定義了自己的迭代器類型,如vector:vector< int>:: iterator iter;//定義一個(gè)名為iter的變量,數(shù)據(jù)類型是由vector< int>定義的iterator 類型。簡(jiǎn)單說(shuō)就是容器類定義了自己的iterator類型,用于訪問(wèn)容器內(nèi)的元素。每個(gè)容器定義了一種名為iterator的類型,這種類型支持迭代器的各種行為。
我么們先講一下各種迭代器的類型,在講容器所用的迭代器類型,就可以明白怎么操作。
常見(jiàn)迭代器類型如下:
| p++ | 后置自增迭代器 |
| ++p | 前置自增迭代器 |
| 輸入迭代器 | 操作介紹 |
| *p | 復(fù)引用迭代器,作為右值 |
| p=p1 | 將一個(gè)迭代器賦給另一個(gè)迭代器(迭代器指向地址值) |
| p==p1 | 比較迭代器的相等性(比較地址) |
| p!=p1 | 比較迭代器的不等性 |
| 輸出迭代器 | 操作 |
| *p | 復(fù)引用迭代器,作為左值 |
| p=p1 | 將一個(gè)迭代器賦給另一個(gè)迭代器 |
| 正向迭代器 | 提供輸入輸出迭代器的所有功能 |
| 雙向迭代器 | 操作 |
| –p | 前置自減迭代器 |
| p– | 后置自減迭代器 |
| 隨機(jī)迭代器 | |
| p+=i | 將迭代器遞增i位 |
| p-=i | 將迭代器遞減i位 |
| p+i | 在p位加i位后的迭代器 |
| p-i | 在p位減i位后的迭代器 |
| p[i] | 返回p位元素偏離i位的元素引用 |
| p<p1 | 如果迭代器p的位置在p1前,返回true,否則返回false |
| p<=p1 | p的位置在p1的前面或同一位置時(shí)返回true,否則返回false |
| p>p1 | 如果迭代器p的位置在p1后,返回true,否則返回false |
| p>=p1 | p的位置在p1的后面或同一位置時(shí)返回true,否則返回false |
只有順序容器和關(guān)聯(lián)容器支持迭代器遍歷,各容器支持的迭代器的類別如下:
| vector | 隨機(jī)訪問(wèn) | 一種隨機(jī)訪問(wèn)的數(shù)組類型,提供了對(duì)數(shù)組元素進(jìn)行快速隨機(jī)訪問(wèn)以及在序列尾部進(jìn)行快速的插入和刪除操作的功能。可以再需要的時(shí)候修改其自身的大小 |
| deque | 隨機(jī)訪問(wèn) | 一種隨機(jī)訪問(wèn)的數(shù)組類型,提供了序列兩端快速進(jìn)行插入和刪除操作的功能。可以再需要的時(shí)候修改其自身的大小 |
| list | 雙向 | 一種不支持隨機(jī)訪問(wèn)的數(shù)組類型,插入和刪除所花費(fèi)的時(shí)間是固定的,與位置無(wú)關(guān)。 |
| set | 雙向 | 一種隨機(jī)存取的容器,其關(guān)鍵字和數(shù)據(jù)元素是同一個(gè)值。所有元素都必須具有惟一值。 |
| multiset | 雙向 | 一種隨機(jī)存取的容器,其關(guān)鍵字和數(shù)據(jù)元素是同一個(gè)值。可以包含重復(fù)的元素。 |
| map | 雙向 | 一種包含成對(duì)數(shù)值的容器,一個(gè)值是實(shí)際數(shù)據(jù)值,另一個(gè)是用來(lái)尋找數(shù)據(jù)的關(guān)鍵字。一個(gè)特定的關(guān)鍵字只能與一個(gè)元素關(guān)聯(lián)。 |
| multimap | 雙向 | 一種包含成對(duì)數(shù)值的容器,一個(gè)值是實(shí)際數(shù)據(jù)值,另一個(gè)是用來(lái)尋找數(shù)據(jù)的關(guān)鍵字。一個(gè)關(guān)鍵字可以與多個(gè)數(shù)據(jù)元素關(guān)聯(lián)。 |
| stack | 不支持 | 適配器容器類型,用vector,deque或list對(duì)象創(chuàng)建了一個(gè)先進(jìn)后出容器 |
| queue | 不支持 | 適配器容器類型,用deque或list對(duì)象創(chuàng)建了一個(gè)先進(jìn)先出容器 |
| priority_queue | 不支持 | 適配器容器類型,用vector或deque對(duì)象創(chuàng)建了一個(gè)排序隊(duì)列 |
二、容器
所有容器都支持自定義數(shù)據(jù)類型,就是結(jié)構(gòu)體。
(一) vector
使用此容器需在程序前加上頭文件#include< vector >。
vector可理解為變長(zhǎng)數(shù)組,基于倍增思想。當(dāng)以已申請(qǐng)vector長(zhǎng)度為m時(shí),若實(shí)際長(zhǎng)度n=m,則申請(qǐng)長(zhǎng)度為2m的數(shù)組,將內(nèi)容轉(zhuǎn)移至新地址上,并釋放舊空間;刪除元素時(shí),若n<=m/4,則釋放一半空間。
vector容器能像數(shù)組一樣隨機(jī)訪問(wèn)第i個(gè)數(shù)a[i],但不支持隨機(jī)插入.
具體操作如下:
a.size() //返回實(shí)際長(zhǎng)度(元素個(gè)數(shù)),O(1)復(fù)雜度a.empty() //容器為空返回1,否則返回0,O(1)復(fù)雜度a.clear() //把vector清空a.begin() //返回指向第一個(gè)元素的迭代器,*a.begin()與a[0]作用相同a.end() //越界訪問(wèn),指向vector尾部,指向第n個(gè)元素再往后的邊界a.front() //返回第一個(gè)元素的值,等價(jià)于*a.begin和a[0]a.back() //返回最后一個(gè)元素的值,等價(jià)于*--a.end()和a[size()-1]a.push_back(x) //把元素x插入vector尾部a.pop_back() //刪除vector中最后一個(gè)元素迭代器使用與指針類似,可如下遍歷整個(gè)容器
for ( vector<int>::iterator it=a.begin() ; it!=a.end() ; it++ )queue
循環(huán)隊(duì)列queue需使用頭文件< queue >
priority_queue
優(yōu)先隊(duì)列priority_queue可理解為一個(gè)大根二叉堆,必須定義“小于號(hào)”,而int,string本身就能比較。同樣需要頭文件< queue >。
其定義方式與queue相似。
可通過(guò)插入元素的相反數(shù)取出時(shí)再取反,或重載“小于號(hào)”的方式實(shí)現(xiàn)小根堆,通過(guò)懶惰刪除法實(shí)現(xiàn)隨機(jī)刪除操作。
deque
雙端隊(duì)列,是一個(gè)支持在兩端高效插入或刪除元素的連續(xù)線性存儲(chǔ)空間,可像數(shù)組一樣隨機(jī)訪問(wèn),使用前加頭文件< deque >。
定義方式
deque<類型> 名稱ps:clear復(fù)雜度為O(n),其余為O(1)。
set/multiset
兩容器相似,但set為有序集合,元素不能重復(fù),multiset為有序多重集合,可包含若干相等的元素,內(nèi)部通過(guò)紅黑樹(shù)實(shí)現(xiàn),支持的函數(shù)基本相同,同樣必須定義“小于號(hào)”運(yùn)算符,頭文件為< set >。
其迭代器不支持隨機(jī)訪問(wèn),支持星號(hào)(*)結(jié)束引用,僅支持 ++ 、-- 兩個(gè)與算術(shù)有關(guān)的操作。迭代器it++,則指向從小到大排序的結(jié)果中排在it下一名的元素,兩操作時(shí)間復(fù)雜度均為O(log n)。
定義方式
set<int> demo 定義一個(gè)類型為int的set容器 struct rec {int a,b,c;bool operator<(const rec&w){if(a==w.a) return b==w.b?c<w.c:b<w.b;return a<w.a;} };set<rec> ob; 一樣所有排序的容器不重載就出錯(cuò)map/multimap
map/multimap映射容器的元素?cái)?shù)據(jù)是由一個(gè)Key和一個(gè)Value成的,key與映照value之間具有一一映照的關(guān)系。
map/multimap容器的數(shù)據(jù)結(jié)構(gòu)也采用紅黑樹(shù)來(lái)實(shí)現(xiàn)的,map插入元素的鍵值不允許重復(fù),類似multiset,multimap的key可以重復(fù)。比較函數(shù)只對(duì)元素的key進(jìn)行比較,元素的各項(xiàng)數(shù)據(jù)只能通過(guò)key檢索出來(lái)。雖然map與set采用的都是紅黑樹(shù)的結(jié)構(gòu),但跟set的區(qū)別主要是set的一個(gè)鍵值和一個(gè)映射數(shù)據(jù)相等,Key=Value。
map<first,second> a; //map,會(huì)按照f(shuō)irst(鍵值)排序(查找也是);map/multimap用法
頭文件
map成員函數(shù)
begin() //返回指向 map 頭部的迭代器 clear() // 刪除所有元素 count() //返回指定元素出現(xiàn)的次數(shù) empty() // 如果 map 為空則返回 true end() //返回指向 map 末尾的迭代器 erase() // 刪除一個(gè)元素 find() // 查找一個(gè)元素 insert() //插入元素 key_comp() //返回比較元素 key 的函數(shù) lower_bound() //返回鍵值>=給定元素的第一個(gè)位置 max_size() //返回可以容納的最大元素個(gè)數(shù) rbegin() //返回一個(gè)指向 map 尾部的逆向迭代器 rend() //返回一個(gè)指向 map 頭部的逆向迭代器 size() //返回 map 中元素的個(gè)數(shù) swap() //交換兩個(gè) map創(chuàng)建map對(duì)象
#include<iostream> #include<map> using namespace std; map<int,char>mp;//定義map容器創(chuàng)建結(jié)構(gòu)體map對(duì)象
struct student{ int birth; string name; }; int id; typedef map<int,student> Student;// 這里相當(dāng)于給map<int,student> 起了個(gè)別名Student,后續(xù)代碼均可以用student代替map<int,student> 使用。插入結(jié)構(gòu)體對(duì)象
接上文代碼
棧(stack)
1.定義:
棧是一種只能在某一端插入和刪除數(shù)據(jù)的特殊線性表。他按照先進(jìn)先出的原則存儲(chǔ)數(shù)據(jù),先進(jìn)的數(shù)據(jù)被壓入棧底,最后進(jìn)入的數(shù)據(jù)在棧頂,需要讀數(shù)據(jù)的時(shí)候從棧頂開(kāi)始彈出數(shù)據(jù)(最后被壓入棧的,最先彈出)。因此棧也稱先進(jìn)后出表。
允許進(jìn)行插入刪除操作的一端稱為棧頂,另一端稱為棧底。棧底固定,棧頂浮動(dòng)。插入元素稱為進(jìn)棧,刪除一個(gè)元素稱為進(jìn)棧,棧內(nèi)元素為零稱為空棧。
2.stack成員函數(shù)
List
定義:List類表示可通過(guò)索引訪問(wèn)的對(duì)象的強(qiáng)類型列表,提供用于對(duì)列表進(jìn)行搜索、排序和操作的方法。
作用:
泛型最常見(jiàn)的用途是泛型集合
我們?cè)趧?chuàng)建列表類時(shí),列表項(xiàng)的數(shù)據(jù)類型可能是int,string或其它類型,如果對(duì)列表類的處理方法相同,
就沒(méi)有必要事先指定數(shù)據(jù)類型,留待列表類實(shí)例化時(shí)再指定。相當(dāng)于把數(shù)據(jù)類型當(dāng)成參數(shù),這樣可以最
大限度地重用代碼,保護(hù)類型的安全以及提高性能。
定義 list<類型> 名稱
成員函數(shù)
bitset
bitset可看作一個(gè)多位二進(jìn)制數(shù),每8位占用1個(gè)字節(jié),相當(dāng)于采用了狀態(tài)壓縮的二進(jìn)制數(shù)組,并支持基本的位運(yùn)算。一般以32位整數(shù)的運(yùn)算次數(shù)為基準(zhǔn)估算運(yùn)行時(shí)間,n位bitset執(zhí)行一次的位運(yùn)算復(fù)雜度可視為n/32,效率較高。頭文件< bitset >。
同樣具有~,&,|,^,<<,>>操作符,==,!=可比較二進(jìn)制數(shù)是否相等
總結(jié)
以上是生活随笔為你收集整理的疯子的算法总结(三) STL Ⅱ迭代器(iterator) + 容器的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Python中index是什么(老猿Py
- 下一篇: [USACO1.5]回文质数 Prime