STL學習筆記之算法

迭代器

標準STL容器提供了四種不同的迭代器:
iterator门坷、const_iterator暗赶、reverse_iterator和const_reverse_iterator

條款26:盡量用iterator代替const_iterator,reverse_iterator和const_reverse_iterator

每個標準容器類都提供四種迭代器類型。對于container<T>而言淤翔,iterator的作用相當于T*,而const_iterator則相當于const T*佩谷;
增加一個iterator或者const_iterator可以在一個從容器開頭趨向尾部的遍歷中讓你移動到容器的下一個元素旁壮。reverse_iterator與const_reverse_iterator同樣相當于對應的T*和
const T*,所不同的是谐檀,增加reverse_iterator或者const_reverse_iterator會在從尾到頭的遍歷中讓你移動到容器的下一個元素抡谐。
迭代器使用的一個重要指導方針是:盡量使用iterator代替其他三種迭代器,原因有:

  • insert和erase的一些版本要求iterator桐猬。如果你需要調(diào)用這些函數(shù)麦撵,你就必須產(chǎn)生iterator,而不能用const或reverse iterators溃肪。
  • 不可能把const_iterator隱式轉換成iterator免胃。

條款27:用distance和advance把const_iterator轉化成iterator

如果你只有一個const_iterator,而你要在它所指向的容器位置上插入新元素呢惫撰?也就是如何把const_iterator轉化為iterator呢羔沙?前面提到:并不存在從const_iterator到iterator之間的隱式轉換,也就是說下面操作是不可以的:

typedef deque<int> IntDeque;
// 方便的typedef
typedef IntDeque::iterator Iter;
typedef IntDeque::const_iterator ConstIter;
ConstIter ci;
// ci是const_iterator
...
Iter i(ci);// 錯誤厨钻!沒有從const_iterator 到iterator隱式轉換的途徑
Iter i( const_cast<Iter>(ci)); // 仍是個錯誤扼雏!不能從const_iterator映射為iterator坚嗜!

正確方法如下:

typedef deque<int> IntDeque;
typedef IntDeque::iterator Iter;
typedef IntDeque::const_iterator ConstIter; 
IntDeque d; 
ConstIter ci;
...
// 讓ci指向d
Iter i(d.begin());
// 初始化i為d.begin()
advance(i, distance <ConstIter> (i, ci));
// 把i移到指向ci位置

注:distance返回兩個指向同一個容器的iterator之間的距離;advance則用于將一個iterator移動指定的距離呢蛤。如果i和ci指向同一個容器惶傻,那么表達式advance(i, distance(i, ci))會將i移動到與ci相同的位置上棍郎。

5其障、算法

條款30:確保目標區(qū)間足夠大

目標區(qū)間不會進行內(nèi)存檢查,也不會動態(tài)擴充內(nèi)存涂佃,所以要提前估算目標區(qū)間的內(nèi)存大小励翼,也可以使用插入迭代器。


條款31:了解你的排序選擇

(1) 如果你需要在vector辜荠、string汽抚、deque或數(shù)組上進行完全排序,你可以使用sort或stable_sort伯病。
(2) 如果你有一個vector造烁、string、deque或數(shù)組午笛,你只需要排序前n個元素惭蟋,應該用partial_sort。
(3) 如果你有一個vector药磺、string告组、deque或數(shù)組,你需要鑒別出第n個元素或你需要鑒別出最前的n個元素癌佩,而不用知道它們的順序木缝,nth_element是你應該注意和調(diào)用的。
(4) 如果你需要把標準序列容器的元素或數(shù)組分隔為滿足和不滿足某個標準围辙,你大概就要找partition或stable_partition我碟。
(5) 如果你的數(shù)據(jù)是在list中,你可以直接使用partition和stable_partition姚建,你可以使用list的sort來代替sort和stable_sort矫俺。如果你需要partial_sort或nth_element提供的效果,你就必須間接完成這個任務


條款32:如果你真的想刪除東西的話就在類似remove的算法后接上erase

先看一個錯誤的實例:

// 建立一個vector<int> 用1-10填充它
vector<int> v;
v.reserve(10);
for(int i = 1; i <= 10; ++i) {
    v.push_back(i);
 }
 
cout << v.size();
// 打印10 
v[3] = v[5] = v[9] = 99;
// 設置3個元素為99
remove (v.begin(), v.end(), 99);
// 刪除所有等于99的元素
cout << v.size();
// 仍然是10桥胞!

正確的刪除元素的方法是:

vector< int> v;
// 正如從前
 v.erase( remove (v.begin(), v.end(), 99), v.end());
// 真的刪除所有等于99的元素
cout << v.size();
// 現(xiàn)在返回7

需要注意的是remove和erase是親密聯(lián)盟恳守,這兩個整合到list成員函數(shù)remove中。這是STL中唯一名叫remove又能從容器中除去元素的函數(shù):

list<int> li;
// 建立一個list 
// 放一些值進去
li.remove(99);
// 除去所有等于99的元素:真的刪除元素贩虾,所以它的大小可能改變了

remove_if 催烘,unique和remove
類似,都需要跟erase連用才可以真正刪除數(shù)據(jù)缎罢,同樣伊群,對于list是個特殊考杉。


條款33:提防在指針的容器上使用類似remove的算法

該條款是對條款32的補充,采用remove/erase方式刪除指針容器中的數(shù)據(jù)會造成內(nèi)存泄漏舰始, 正確的方法有兩種:
(1)在應用erase-remove慣用法之前先刪除指針并設置它們?yōu)榭粘缣模缓蟪ト萜髦械乃锌罩羔槪?br> (2)采用智能指針,如boost庫中的shared_ptr和scoped_ptr


條款34:注意哪個算法需要有序區(qū)間

STL中只能操作有序數(shù)據(jù)(升序)的算法有:
(1) binary_search:二分查找
(2) lower_bound:下界
(3) upper_bound:上界
(4) equal_range:所有等于某個值的元素
(5) set_union:集合并集
(6) set_intersection:集合交集
(7) set_difference :集合差集
(8) set_symmetric_difference:包含在第一個集合但是不包含在第二個集合中的元素丸卷,包含在第2個集合但是不包含在第1個集合中的元素
(9) merge:合并兩個有序表
(10) inplace_merge:合并兩個有序表
(11) includes:檢測一個區(qū)間的所有對象是否在另一個區(qū)間中
另外枕稀,下面的算法一般用于有序區(qū)間,雖然它們不要求:
(12) unique:去重谜嫉,相同的元素必須緊挨著萎坷,排序是個特例
(13) unique_copy:同上

原創(chuàng)文章,轉載請注明: 轉載自董的博客
本文鏈接地址: http://dongxicheng.org/cpp/effective-stl-part3/

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末沐兰,一起剝皮案震驚了整個濱河市哆档,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌住闯,老刑警劉巖瓜浸,帶你破解...
    沈念sama閱讀 206,013評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場離奇詭異比原,居然都是意外死亡插佛,警方通過查閱死者的電腦和手機,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,205評論 2 382
  • 文/潘曉璐 我一進店門春寿,熙熙樓的掌柜王于貴愁眉苦臉地迎上來朗涩,“玉大人,你說我怎么就攤上這事绑改⌒淮玻” “怎么了?”我有些...
    開封第一講書人閱讀 152,370評論 0 342
  • 文/不壞的土叔 我叫張陵厘线,是天一觀的道長识腿。 經(jīng)常有香客問我,道長造壮,這世上最難降的妖魔是什么渡讼? 我笑而不...
    開封第一講書人閱讀 55,168評論 1 278
  • 正文 為了忘掉前任,我火速辦了婚禮耳璧,結果婚禮上成箫,老公的妹妹穿的比我還像新娘。我一直安慰自己旨枯,他們只是感情好蹬昌,可當我...
    茶點故事閱讀 64,153評論 5 371
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著攀隔,像睡著了一般皂贩。 火紅的嫁衣襯著肌膚如雪栖榨。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 48,954評論 1 283
  • 那天明刷,我揣著相機與錄音婴栽,去河邊找鬼。 笑死辈末,一個胖子當著我的面吹牛愚争,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播本冲,決...
    沈念sama閱讀 38,271評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼准脂,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了檬洞?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 36,916評論 0 259
  • 序言:老撾萬榮一對情侶失蹤沟饥,失蹤者是張志新(化名)和其女友劉穎添怔,沒想到半個月后,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體贤旷,經(jīng)...
    沈念sama閱讀 43,382評論 1 300
  • 正文 獨居荒郊野嶺守林人離奇死亡广料,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,877評論 2 323
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發(fā)現(xiàn)自己被綠了幼驶。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片艾杏。...
    茶點故事閱讀 37,989評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖盅藻,靈堂內(nèi)的尸體忽然破棺而出购桑,到底是詐尸還是另有隱情,我是刑警寧澤氏淑,帶...
    沈念sama閱讀 33,624評論 4 322
  • 正文 年R本政府宣布勃蜘,位于F島的核電站,受9級特大地震影響假残,放射性物質(zhì)發(fā)生泄漏缭贡。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 39,209評論 3 307
  • 文/蒙蒙 一辉懒、第九天 我趴在偏房一處隱蔽的房頂上張望阳惹。 院中可真熱鬧,春花似錦眶俩、人聲如沸莹汤。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,199評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽体啰。三九已至攒巍,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間荒勇,已是汗流浹背柒莉。 一陣腳步聲響...
    開封第一講書人閱讀 31,418評論 1 260
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留沽翔,地道東北人兢孝。 一個月前我還...
    沈念sama閱讀 45,401評論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像仅偎,于是被迫代替她去往敵國和親跨蟹。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 42,700評論 2 345

推薦閱讀更多精彩內(nèi)容