技術(shù)交流QQ群:1027579432锹淌,歡迎你的加入辞色!
1.Cpp中的迭代器
- 要訪問順序容器和關(guān)聯(lián)容器中的元素鸽嫂,需要通過迭代器(iterator)進(jìn)行。迭代器是一個(gè)變量髓窜,相當(dāng)于容器和操縱容器的算法之間的中介扇苞。迭代器可以指向容器中的某個(gè)元素,通過迭代器就可以讀寫它指向的元素,從這一點(diǎn)上看,迭代器和指針類似杨拐。
- 迭代器按照定義方式分成以下四種:
- 正向迭代器祈餐,定義方法如下:
容器類名::iterator 迭代器名;
- 常量正向迭代器擂啥,定義方法如下:
容器類名::const__iterator 迭代器名;
- 反向迭代器哄陶,定義方法如下:
容器類名::reverse_iterator 迭代器名;
- 常量反向迭代器,定義方法如下:
容器類名::const_reverse_iterator 迭代器名;
- 正向迭代器祈餐,定義方法如下:
2.迭代器用法示例
-
通過迭代器可以讀取它指向的元素哺壶,*迭代器名就表示迭代器指向的元素,通過非常量迭代器還能修改其指向的元素**屋吨。迭代器都可以進(jìn)行++操作。反向迭代器和正向迭代器的區(qū)別在于:
- 對正向迭代器進(jìn)行++操作時(shí)山宾,迭代器會(huì)指向容器中的后一個(gè)元素至扰;
- 對反向迭代器進(jìn)行++操作時(shí),迭代器會(huì)指向容器中的前一個(gè)元素资锰。
- 實(shí)例如下:
#include "iostream" #include "vector" using namespace std; int main(){ // 迭代器用法實(shí)例 vector<int> v; // v中存放int類型變量的可變長的數(shù)組敢课,開始時(shí)沒有元素 for(int n=0; n < 5; n++) v.push_back(n); // push_back()成員函數(shù)在vector容器尾部添加一個(gè)元素 vector<int>::iterator i; // 定義正向迭代器 cout << "正向迭代器遍歷容器: "; for(i = v.begin(); i!=v.end();++i){ // 用正向迭代器從前往后遍歷容器,使用前置++,不使用后置++,因?yàn)檫@將會(huì)降低運(yùn)算時(shí)間,原因是++運(yùn)算符的重載绷杜!后置++會(huì)多生成一個(gè)局部對象temp! cout << *i << " "; // *n就是迭代器n指向的元素 *i *= 2; // 每個(gè)元素變?yōu)樵瓉淼?倍 } cout << endl; // 用反向迭代器遍歷容器 cout << "反向迭代器遍歷容器: "; vector<int>::reverse_iterator j; for(j=v.rbegin(); j != v.rend();++j) // 用反向迭代器從后往前遍歷容器 cout << *j << " "; cout << "-------------------------------------\n"; return 0; }
3.迭代器的功能分類
- 不同容器的迭代器直秆,其功能強(qiáng)弱有所不同。容器的迭代器的功能強(qiáng)弱鞭盟,決定了該容器是否支持STL中的某種算法圾结。例如,排序算法需要通過隨機(jī)訪問迭代器來訪問容器中的元素齿诉,因此有的容器就不支持排序算法筝野。常用的迭代器按功能強(qiáng)弱分為輸入、輸出粤剧、正向歇竟、雙向、隨機(jī)訪問五種抵恋,這里只介紹常用的三種焕议。
- 正向迭代器: 假設(shè)p是一個(gè)正向迭代器,則p支持以下操作:++p馋记,p++号坡,*p。此外梯醒,兩個(gè)正向迭代器可以互相賦值宽堆,還可以用==和!=運(yùn)算符進(jìn)行比較。
- 雙向迭代器: 雙向迭代器具有正向迭代器的全部功能茸习。除此之外畜隶,若p是一個(gè)雙向迭代器,則--p和p--都是有定義的。--p使得p朝著和++p相反的方向移動(dòng)籽慢。
- 隨機(jī)訪問迭代器: 隨機(jī)訪問迭代器具有雙向迭代器的全部功能浸遗。若p是一個(gè)隨機(jī)訪問迭代器,i是一個(gè)整型變量或常量箱亿,則p還支持以下操作:
- p+=i:使得p往后移動(dòng)i個(gè)元素
- p-=i:使得p往前移動(dòng)i個(gè)元素
- p+i:返回p后面第i個(gè)元素的迭代器
- p-i:返回p前面第i個(gè)元素的迭代器
- p[i]:返回p后面第i個(gè)元素的引用
- 此外跛锌,兩個(gè)隨機(jī)訪問迭代器p1、p2 還可以用 <届惋、>髓帽、<=、>= 運(yùn)算符進(jìn)行比較脑豹。p1 < p2的含義是:p1經(jīng)過若干次(至少一次)++操作后郑藏,就會(huì)等于p2,其他比較方式的含義與此類似。對于兩個(gè)隨機(jī)訪問迭代器p1瘩欺、p2必盖,表達(dá)式p2-p1也是有定義的,其返回值是p2所指向元素和p1所指向元素的序號之差(也可以說是p2和p1之間的元素個(gè)數(shù)減一)俱饿。
不同容器的迭代器的功能.png
- 實(shí)例如下:
// 迭代器的功能分類 vector<int> v1(10); // v1初始化成有10個(gè)元素 for(int i = 0; i < v.size(); ++i) // size()返回元素的個(gè)數(shù) cout << "v1[" << i << "] = " << v1[i] << " "; cout << endl; vector<int>::iterator i1; for(i1 = v1.begin(); i1 != v1.end(); ++i1) // 用 != 比較兩個(gè)迭代器 cout << *i1; cout << endl; for(i1 = v1.begin(); i1 < v1.end(); ++i1) // 用 < 比較兩個(gè)迭代器 cout << *i1; cout << endl; i1 = v.begin(); while(i1 < v.end()){ // 間隔一個(gè)輸出 cout << *i1; i1 += 2; // 隨機(jī)訪問迭代器支持 "+= 整數(shù)" 的操作 } cout << endl;
- list容器的迭代器是雙向迭代器歌粥。假設(shè)v和i的定義如下:
list<int> l; list<int>::const_iterator i
- 則以下代碼是合法的:
for(i = l.begin(); i != l.end(); ++i) cout << *l << " ";
- 因?yàn)殡p向迭代器不支持用“<”進(jìn)行比較,list不支持隨機(jī)訪問迭代器的容器,也不支持用下標(biāo)隨機(jī)訪問其元素稍途。以下代碼則不合法:
for(i = l.begin(); i < l.size(); ++i) cout << l[i]; for(i = l.begin(); i < l.end(); ++i) cout << *l << endl;
- 在C++中阁吝,數(shù)組也是容器。數(shù)組的迭代器就是指針械拍,而且是隨機(jī)訪問迭代器突勇。例如,對于數(shù)組int a[10]坷虑,int * 類型的指針就是其迭代器甲馋。則a、a+1迄损、a+2都是a的迭代器定躏。
4.迭代器的輔助函數(shù)
- STL中有用于操作迭代器的三個(gè)函數(shù)模板,它們是:
- advance(p, n):使迭代器p向前或向后移動(dòng)n個(gè)元素
- distance(p, q):計(jì)算兩個(gè)迭代器之間的距離芹敌,即迭代器p經(jīng)過多少次++操作后和迭代器q相等痊远。如果調(diào)用時(shí)p已經(jīng)指向q的后面,則這個(gè)函數(shù)會(huì)陷入死循環(huán)氏捞。
- iter_swap(p, q):用于交換兩個(gè)迭代器p碧聪、q指向的值
-
要使用上述模板,需要包含頭文件algorithm液茎。下面的程序演示了這三個(gè)函數(shù)模板的用法:
#include "iostream" #include "vector" #include "list" #include "algorithm" // 要使用操作迭代器的函數(shù)模板逞姿,需要包含此文件!! using namespace std; int main(){ // 迭代器的輔助函數(shù) int a[5] = {6, 66, 666, 6666, 0}; list<int> lst(a, a+5); list<int>::iterator p = lst.begin(); // 迭代器p辞嗡,類似于一個(gè)指針 advance(p, 2); // p向后移動(dòng)兩個(gè)元素,指向666 cout << *p << endl; // 輸出666 advance(p, -1); // p向前移動(dòng)一個(gè)元素滞造,指向66 cout << *p << endl; // 輸出66 list<int>::iterator q = lst.end(); q--; // q指向5 cout << distance(p, q) << endl; // 輸出3 iter_swap(p, q); // 序號從1開始续室,交換2號和5號元素 for(p = lst.begin(); p != lst.end(); ++p) cout << *p << " "; return 0; }