STL应用总结
C++ STL基本容器的使用
C++中有兩種類型的容器:順序容器和關聯容器。順序容器主要有vector、list、deque等。其中vector表示一段連續的內存,基于數組實現,list表示非連續的內存,基于鏈表實現,deque與vector類似,但
是對首元素提供插入和刪除的雙向支持。關聯容器主要有map和set。map是key-value形式,set是單值。
map和set只能存放唯一的key,multimap和multiset可以存放多個相同的key。
容器類自動申請和釋放內存,因此無需new和delete操作。
一、vector
vector基于模板實現,需包含頭文件vector。
1.定義和初始化
//1.定義和初始化vector<int> vec1; //默認初始化,vec1為空vector<int> vec2(vec1); //使用vec1初始化vec2vector<int> vec3(vec1.begin(),vec1.end());//使用vec1初始化vec2vector<int> vec4(10); //10個值為的元素vector<int> vec5(10,4); //10個值為的元素//2.常用操作方法vec1.push_back(100); //添加元素int size = vec1.size(); //元素個數bool isEmpty = vec1.empty(); //判斷是否為空cout<<vec1[0]<<endl; //取得第一個元素vec1.insert(vec1.end(),5,3); //從vec1.back位置插入個值為的元素//vec1.pop_back(); //刪除末尾元素//vec1.erase(vec1.begin(),vec1.end());//刪除之間的元素,其他元素前移cout<<(vec1==vec2)?true:false; //判斷是否相等==、!=、>=、<=...vector<int>::iterator iter = vec1.begin(); //獲取迭代器首地址vector<int>::const_iterator c_iter = vec1.begin(); //獲取const類型迭代器//vec1.clear(); //清空元素//3.遍歷//下標法int length = vec1.size();for(int i=0;i<length;i++){cout<<vec1[i];}cout<<endl<<endl;//迭代器法vector<int>::const_iterator iterator = vec1.begin();for(;iterator != vec1.end();iterator++){cout<<*iterator;}二、list
List是stl實現的雙向鏈表,與 向量(vectors)相比, 它允許快速的插入和刪除,但是隨機訪問卻比較慢。需要添加頭文件list
//1.定義和初始化list<int> lst1; //創建空listlist<int> lst2(3); //創建含有三個元素的listlist<int> lst3(3,2); //創建含有三個元素的listlist<int> lst4(lst2); //使用lst2初始化lst4list<int> lst5(lst2.begin(),lst2.end()); //同lst4//2.常用操作方法lst1.assign(lst2.begin(),lst2.end()); //分配值lst1.push_back(10); //添加值lst1.pop_back(); //刪除末尾值lst1.begin(); //返回首值的迭代器lst1.end(); //返回尾值的迭代器lst1.clear(); //清空值bool isEmpty1 = lst1.empty(); //判斷為空lst1.erase(lst1.begin(),lst1.end()); //刪除元素lst1.front(); //返回第一個元素的引用lst1.back(); //返回最后一個元素的引用lst1.insert(lst1.begin(),3,2); //從指定位置插入個lst1.rbegin(); //返回第一個元素的前向指針lst1.remove(2); //相同的元素全部刪除lst1.reverse(); //反轉lst1.size(); //含有元素個數lst1.sort(); //排序lst1.unique(); //刪除相鄰重復元素//3.遍歷//迭代器法for(list<int>::const_iterator iter = lst1.begin();iter != lst1.end();iter++){cout<<*iter;}cout<<endl;三、deque
deque容器類與vector類似,支持隨機訪問和快速插入刪除,它在容器中某一位置上的操作所花費的是線性時間。與vector不同的是,deque還支持從開始端插入數據:push_front()。其余類似vector操作方法
的使用。
四、map
C++中map容器提供一個鍵值對(key/value)容器,map與multimap差別僅僅在于multiple允許一個鍵對
應多個值。需要包含頭文件map。對于迭代器來說,可以修改實值,而不能修改key。Map會根據key自動
排序。
//1.定義和初始化map<int,string> map1; //空map//2.常用操作方法map1[3] = "Saniya"; //添加元素map1.insert(map<int,string>::value_type(2,"Diyabi"));//插入元素//map1.insert(pair<int,string>(1,"Siqinsini"));map1.insert(make_pair<int,string>(4,"V5"));string str = map1[3]; //根據key取得value,key不能修改map<int,string>::iterator iter_map = map1.begin();//取得迭代器首地址int key = iter_map->first; //取得ekystring value = iter_map->second; //取得valuemap1.erase(iter_map); //刪除迭代器數據map1.erase(3); //根據key刪除valuemap1.size(); //元素個數map1.empty(); //判斷空map1.clear(); //清空所有元素//3.遍歷for(map<int,string>::iterator iter = map1.begin();iter!=map1.end();iter++){int keyk = iter->first;string valuev = iter->second;}五、set
set的含義是集合,它是一個有序的容器,里面的元素都是排序好的,支持插入,刪除,查找等操作,就
像一個集合一樣。所有的操作的都是嚴格在logn時間之內完成,效率非常高。set和multiset的區別是:
set插入的元素不能相同,但是multiset可以相同。Set默認自動排序。使用方法類似list。
六、各種容器總結(轉自:http://hi.baidu.com/ewook/item/514fc22ecde5940e73863e65)
(1) vector
內部數據結構:數組。
隨機訪問每個元素,所需要的時間為常量。
在末尾增加或刪除元素所需時間與元素數目無關,在中間或開頭增加或刪除元素所需時間隨元素數目呈
線性變化。
可動態增加或減少元素,內存管理自動完成,但程序員可以使用reserve()成員函數來管理內存。
vector的迭代器在內存重新分配時將失效(它所指向的元素在該操作的前后不再相同)。當把超過
capacity()-size()個元素插入vector中時,內存會重新分配,所有的迭代器都將失效;否則,指向當前
元素以后的任何元素的迭代器都將失效。當刪除元素時,指向被刪除元素以后的任何元素的迭代器都將
失效。
(2)deque
內部數據結構:數組。
隨機訪問每個元素,所需要的時間為常量。
在開頭和末尾增加元素所需時間與元素數目無關,在中間增加或刪除元素所需時間隨元素數目呈線性變
化。
可動態增加或減少元素,內存管理自動完成,不提供用于內存管理的成員函數。
增加任何元素都將使deque的迭代器失效。在deque的中間刪除元素將使迭代器失效。在deque的頭或尾刪
除元素時,只有指向該元素的迭代器失效。
(3)list
內部數據結構:雙向環狀鏈表。
不能隨機訪問一個元素。
可雙向遍歷。
在開頭、末尾和中間任何地方增加或刪除元素所需時間都為常量。
可動態增加或減少元素,內存管理自動完成。
增加任何元素都不會使迭代器失效。刪除元素時,除了指向當前被刪除元素的迭代器外,其它迭代器都
不會失效。
(4)slist
內部數據結構:單向鏈表。
不可雙向遍歷,只能從前到后地遍歷。
其它的特性同list相似。
(5)stack
適配器,它可以將任意類型的序列容器轉換為一個堆棧,一般使用deque作為支持的序列容器。
元素只能后進先出(LIFO)。
不能遍歷整個stack。
(6)queue
適配器,它可以將任意類型的序列容器轉換為一個隊列,一般使用deque作為支持的序列容器。
元素只能先進先出(FIFO)。
不能遍歷整個queue。
(7)priority_queue
適配器,它可以將任意類型的序列容器轉換為一個優先級隊列,一般使用vector作為底層存儲方式。
只能訪問第一個元素,不能遍歷整個priority_queue。
第一個元素始終是優先級最高的一個元素。
(8)set
鍵和值相等。
鍵唯一。
元素默認按升序排列。
如果迭代器所指向的元素被刪除,則該迭代器失效。其它任何增加、刪除元素的操作都不會使迭代器失
效。
(9)multiset
鍵可以不唯一。
其它特點與set相同。
(10)hash_set
與set相比較,它里面的元素不一定是經過排序的,而是按照所用的hash函數分派的,它能提供更快的搜
索速度(當然跟hash函數有關)。
其它特點與set相同。
(11)hash_multiset
鍵可以不唯一。
其它特點與hash_set相同。
(12)map
鍵唯一。
元素默認按鍵的升序排列。
如果迭代器所指向的元素被刪除,則該迭代器失效。其它任何增加、刪除元素的操作都不會使迭代器失
效。
(13)multimap
鍵可以不唯一。
其它特點與map相同。
(14)hash_map
與map相比較,它里面的元素不一定是按鍵值排序的,而是按照所用的hash函數分派的,它能提供更快的
搜索速度(當然也跟hash函數有關)。
其它特點與map相同。
(15)hash_multimap
鍵可以不唯一。
其它特點與hash_map相同。
========
C++ STL 一般總結
以下內容來源網上 經過整合而成一、一般介紹
? ? ? STL(Standard Template Library),即標準模板庫,是一個具有工業強度的,高效的C++程序庫
。它被容納于C++標準程序庫(C++ Standard Library)中,是ANSI/ISO C++標準中最新的也是極具革命
性的一部分。該庫包含了諸多在計算機科學領域里所常用的基本數據結構和基本算法。為廣大C++程序員
們提供了一個可擴展的應用框架,高度體現了軟件的可復用性。
? ? ? 從邏輯層次來看,在STL中體現了泛型化程序設計的思想(generic programming),引入了諸多
新的名詞,比如像需求(requirements),概念(concept),模型(model),容器(container),算
法(algorithmn),迭代子(iterator)等。與OOP(object-oriented programming)中的多態
(polymorphism)一樣,泛型也是一種軟件的復用技術;
? ? ? ?從實現層次看,整個STL是以一種類型參數化(type parameterized)的方式實現的,這種方式
基于一個在早先C++標準中沒有出現的語言特性--模板(template)。如果查閱任何一個版本的STL源代
碼,你就會發現,模板作為構成整個STL的基石是一件千真萬確的事情。除此之外,還有許多C++的新特
性為STL的實現提供了方便;
二、STL的六大組件
容器(Container),是一種數據結構,如list,vector,和deques ,以模板類的方法提供。為了訪問
容器中的數據,可以使用由容器類輸出的迭代器;
迭代器(Iterator),提供了訪問容器中對象的方法。例如,可以使用一對迭代器指定list或vector中
的一定范圍的對象。迭代器就如同一個指針。事實上,C++的指針也是一種迭代器。但是,迭代器也可以
是那些定義了operator*()以及其他類似于指針的操作符地方法的類對象;
算法(Algorithm),是用來操作容器中的數據的模板函數。例如,STL用sort()來對一個vector中的數
據進行排序,用find()來搜索一個list中的對象,函數本身與他們操作的數據的結構和類型無關,因此
他們可以在從簡單數組到高度復雜容器的任何數據結構上使用;
仿函數(Function object,仿函數(functor)又稱之為函數對象(function object),其實就是重載了
()操作符的struct,沒有什么特別的地方
迭代適配器(Adaptor)
空間配制器(allocator)其中主要工作包括兩部分1.對象的創建與銷毀 ? ?2.內存的獲取與釋放
以下主要討論:容器,迭代器,算法,適配器。如欲詳加了解 參見C++ Primer?
1.STL容器
1)序列式容器(Sequence containers),每個元素都有固定位置--取決于插入時機和地點,和元素
值無關,vector、deque、list;
? ?Vectors:將元素置于一個動態數組中加以管理,可以隨機存取元素(用索引直接存取),數組尾部
添加或移除元素非常快速。但是在中部或頭部安插元素比較費時;
? ?Deques:是“double-ended queue”的縮寫,可以隨機存取元素(用索引直接存取),數組頭部和尾
部添加或移除元素都非常快速。但是在中部或頭部安插元素比較費時;
? ?Lists:雙向鏈表,不提供隨機存取(按順序走到需存取的元素,O(n)),在任何位置上執行插入或
刪除動作都非常迅速,內部只需調整一下指針;
2)關聯式容器(Associated containers),元素位置取決于特定的排序準則,和插入順序無關,set、
multiset、map、multimap;
? ?Sets/Multisets:內部的元素依據其值自動排序,Set內的相同數值的元素只能出現一次,Multisets
內可包含多個數值相同的元素,內部由二叉樹實現(實際上基于紅黑樹(RB-tree)實現),便于查找;
? ?Maps/Multimaps:Map的元素是成對的鍵值/實值,內部的元素依據其值自動排序,Map內的相同數值
的元素只能出現一次,Multimaps內可包含多個數值相同的元素,內部由二叉樹實現(實際上基于紅黑樹
(RB-tree)實現),便于查找;
另外有其他容器hash_map,hash_set,hash_multiset,hash_multimap。
? 容器的比較:
? Vector Deque List Set MultiSet Map MultiMap
內部結構 dynamic array array of arrays double linked list binary tree
binary tree binary tree binary tree
隨機存取 Yes Yes No No No Yes(key) No
搜索速度 慢 慢 很慢 快 快 快 快
快速插入移除 尾部 首尾 任何位置 -- -- -- --
?
2.STL迭代器?
Iterator(迭代器)模式又稱Cursor(游標)模式,用于提供一種方法順序訪問一個聚合對象中各個元
素,?
而又不需暴露該對象的內部表示。或者這樣說可能更容易理解:Iterator模式是運用于聚合對象的一種
模式,通過運用該模式,使得我們可以在不知道對象內部表示的情況下,按照一定順序(由iterator提
供的方法)訪問聚合對象中的各個元素。
迭代器的作用:能夠讓迭代器與算法不干擾的相互發展,最后又能無間隙的粘合起來,重載了*,++,
==,!=,=運算符。用以操作復雜的數據結構,容器提供迭代器,算法使用迭代器;
常見的一些迭代器類型:iterator、const_iterator、reverse_iterator和const_reverse_iterator
迭代器一般聲明使用示例
vector<T>::iterator it;
list<T>::iterator it;
deque<T>::iterator it;
? ? ? ? ? ? input ? ? ? ? output
? ? ? ? ? ? ? \ ? ? ? ? ? ?/ ?
? ? ? ? ? ? ? ? forward
? ? ? ? ? ? ? ? ? ? ?|
? ? ? ? ? ? ? ? bidirectional
? ? ? ? ? ? ? ? ? ? ?|
? ? ? ? ? ? ? ?random access ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??
?
?
要注意,上面這圖表并不是表明它們之間的繼承關系:而只是描述了迭代器的種類和接口。處于圖表下
層的迭代器都是相對于處于圖表上層迭代器的擴張集。例如:forward迭代器不但擁有input和output迭
代器的所有功能,還擁有更多的功能。
各個迭代器的功能如下:
迭代器類別
說明
輸入
從容器中讀取元素。輸入迭代器只能一次讀入一個元素向前移動,輸入迭代器只支持一遍算法,同一個
輸入迭代器不能兩遍遍歷一個序列
輸出
向容器中寫入元素。輸出迭代器只能一次一個元素向前移動。輸出迭代器只支持一遍算法,統一輸出迭
代器不能兩次遍歷一個序列
正向
組合輸入迭代器和輸出迭代器的功能,并保留在容器中的位置
雙向
組合正向迭代器和逆向迭代器的功能,支持多遍算法
隨機訪問
組合雙向迭代器的功能與直接訪問容器中任何元素的功能,即可向前向后跳過任意個元素
迭代器的操作:
每種迭代器均可進行包括表中前一種迭代器可進行的操作。
迭代器操作
說明
所有迭代器
p++
后置自增迭代器
++p
前置自增迭代器
輸入迭代器
*p
復引用迭代器,作為右值
p=p1
將一個迭代器賦給另一個迭代器
p==p1
比較迭代器的相等性
p!=p1
比較迭代器的不等性
輸出迭代器
*p
復引用迭代器,作為左值
p=p1
將一個迭代器賦給另一個迭代器
正向迭代器
提供輸入輸出迭代器的所有功能
雙向迭代器
--p
前置自減迭代器
p--
后置自減迭代器
隨機迭代器
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的前面或同一位置時返回true,否則返回false
p>p1
如果迭代器p的位置在p1后,返回true,否則返回false
p>=p1
p的位置在p1的后面或同一位置時返回true,否則返回false
只有順序容器和關聯容器支持迭代器遍歷,各容器支持的迭代器的類別如下:
容器
支持的迭代器類別
說明
vector
隨機訪問
一種隨機訪問的數組類型,提供了對數組元素進行快速隨機訪問以及在序列尾部進行快速的插入和刪除
操作的功能。可以再需要的時候修改其自身的大小
deque
隨機訪問
一種隨機訪問的數組類型,提供了序列兩端快速進行插入和刪除操作的功能。可以再需要的時候修改其
自身的大小
list
雙向
一種不支持隨機訪問的數組類型,插入和刪除所花費的時間是固定的,與位置無關。
set
雙向
一種隨機存取的容器,其關鍵字和數據元素是同一個值。所有元素都必須具有惟一值。
multiset
雙向
一種隨機存取的容器,其關鍵字和數據元素是同一個值。可以包含重復的元素。
map
雙向
一種包含成對數值的容器,一個值是實際數據值,另一個是用來尋找數據的關鍵字。一個特定的關鍵字
只能與一個元素關聯。
multimap
雙向
一種包含成對數值的容器,一個值是實際數據值,另一個是用來尋找數據的關鍵字。一個關鍵字可以與
多個數據元素關聯。
stack
不支持
適配器容器類型,用vector,deque或list對象創建了一個先進后出容器
queue
不支持
適配器容器類型,用deque或list對象創建了一個先進先出容器
priority_queue
不支持
適配器容器類型,用vector或deque對象創建了一個排序隊列
?
?3.STL算法
STL算法部分主要由頭文件<algorithm>,<numeric>,<functional>組成。要使用 STL中的算法函數必須包
含頭文件<algorithm>,對于數值算法須包含<numeric>,<functional>中則定義了一些模板類,用來聲
明函數對象。
STL中算法大致分為四類:
1)、非可變序列算法:指不直接修改其所操作的容器內容的算法。
2)、可變序列算法:指可以修改它們所操作的容器內容的算法。
3)、排序算法:包括對序列進行排序和合并的算法、搜索算法以及有序序列上的集合操作。
4)、數值算法:對容器內容進行數值計算。
?
以下對所有算法進行細致分類并標明功能:
? ? <一>查找算法(13個):判斷容器中是否包含某個值
? ? adjacent_find: ? ? ? ? ? ?在iterator對標識元素范圍內,查找一對相鄰重復元素,找到則返回
指向這對元素的第一個元素的ForwardIterator。否則返回last。重載版本使用輸入的二元操作符代替相
等的判斷。
? ? binary_search: ? ? ? ? ? ?在有序序列中查找value,找到返回true。重載的版本實用指定的比較
函數對象或函數指針來判斷相等。
? ? count: ? ? ? ? ? ? ? ? ? ?利用等于操作符,把標志范圍內的元素與輸入值比較,返回相等元素
個數。
? ? count_if: ? ? ? ? ? ? ? ? 利用輸入的操作符,對標志范圍內的元素進行操作,返回結果為true
的個數。
? ? equal_range: ? ? ? ? ? ? ?功能類似equal,返回一對iterator,第一個表示lower_bound,第二
個表示upper_bound。
? ? find: ? ? ? ? ? ? ? ? ? ? 利用底層元素的等于操作符,對指定范圍內的元素與輸入值進行比較
。當匹配時,結束搜索,返回該元素的一個InputIterator。
? ? find_end: ? ? ? ? ? ? ? ? 在指定范圍內查找"由輸入的另外一對iterator標志的第二個序列"的
最后一次出現。找到則返回最后一對的第一個ForwardIterator,否則返回輸入的"另外一對"的第一個
ForwardIterator。重載版本使用用戶輸入的操作符代替等于操作。
? ? find_first_of: ? ? ? ? ? ?在指定范圍內查找"由輸入的另外一對iterator標志的第二個序列"中
任意一個元素的第一次出現。重載版本中使用了用戶自定義操作符。
? ? find_if: ? ? ? ? ? ? ? ? ?使用輸入的函數代替等于操作符執行find。
? ? lower_bound: ? ? ? ? ? ? ?返回一個ForwardIterator,指向在有序序列范圍內的可以插入指定值
而不破壞容器順序的第一個位置。重載函數使用自定義比較操作。
? ? upper_bound: ? ? ? ? ? ? ?返回一個ForwardIterator,指向在有序序列范圍內插入value而不破
壞容器順序的最后一個位置,該位置標志一個大于value的值。重載函數使用自定義比較操作。
? ? search: ? ? ? ? ? ? ? ? ? 給出兩個范圍,返回一個ForwardIterator,查找成功指向第一個范圍
內第一次出現子序列(第二個范圍)的位置,查找失敗指向last1。重載版本使用自定義的比較操作。
? ? search_n: ? ? ? ? ? ? ? ? 在指定范圍內查找val出現n次的子序列。重載版本使用自定義的比較
操作。
?
? ? <二>排序和通用算法(14個):提供元素排序策略
? ? inplace_merge: ? ? ? ? ? ?合并兩個有序序列,結果序列覆蓋兩端范圍。重載版本使用輸入的操
作進行排序。
? ? merge: ? ? ? ? ? ? ? ? ? ?合并兩個有序序列,存放到另一個序列。重載版本使用自定義的比較
。
? ? nth_element: ? ? ? ? ? ? ?將范圍內的序列重新排序,使所有小于第n個元素的元素都出現在它前
面,而大于它的都出現在后面。重載版本使用自定義的比較操作。
? ? partial_sort: ? ? ? ? ? ? 對序列做部分排序,被排序元素個數正好可以被放到范圍內。重載版
本使用自定義的比較操作。
? ? partial_sort_copy: ? ? ? ?與partial_sort類似,不過將經過排序的序列復制到另一個容器。
? ? partition: ? ? ? ? ? ? ? ?對指定范圍內元素重新排序,使用輸入的函數,把結果為true的元素
放在結果為false的元素之前。
? ? random_shuffle: ? ? ? ? ? 對指定范圍內的元素隨機調整次序。重載版本輸入一個隨機數產生操
作。
? ? reverse: ? ? ? ? ? ? ? ? ?將指定范圍內元素重新反序排序。
? ? reverse_copy: ? ? ? ? ? ? 與reverse類似,不過將結果寫入另一個容器。
? ? rotate: ? ? ? ? ? ? ? ? ? 將指定范圍內元素移到容器末尾,由middle指向的元素成為容器第一
個元素。
? ? rotate_copy: ? ? ? ? ? ? ?與rotate類似,不過將結果寫入另一個容器。
? ? sort: ? ? ? ? ? ? ? ? ? ? 以升序重新排列指定范圍內的元素。重載版本使用自定義的比較操作
。
? ? stable_sort: ? ? ? ? ? ? ?與sort類似,不過保留相等元素之間的順序關系。
? ? stable_partition: ? ? ? ? 與partition類似,不過不保證保留容器中的相對順序。
?
? ? <三>刪除和替換算法(15個)
? ? copy: ? ? ? ? ? ? ? ? ? ? 復制序列
? ? copy_backward: ? ? ? ? ? ?與copy相同,不過元素是以相反順序被拷貝。
? ? iter_swap: ? ? ? ? ? ? ? ?交換兩個ForwardIterator的值。
? ? remove: ? ? ? ? ? ? ? ? ? 刪除指定范圍內所有等于指定元素的元素。注意,該函數不是真正刪
除函數。內置函數不適合使用remove和remove_if函數。
? ? remove_copy: ? ? ? ? ? ? ?將所有不匹配元素復制到一個制定容器,返回OutputIterator指向被
拷貝的末元素的下一個位置。
? ? remove_if: ? ? ? ? ? ? ? ?刪除指定范圍內輸入操作結果為true的所有元素。
? ? remove_copy_if: ? ? ? ? ? 將所有不匹配元素拷貝到一個指定容器。
? ? replace: ? ? ? ? ? ? ? ? ?將指定范圍內所有等于vold的元素都用vnew代替。
? ? replace_copy: ? ? ? ? ? ? 與replace類似,不過將結果寫入另一個容器。
? ? replace_if: ? ? ? ? ? ? ? 將指定范圍內所有操作結果為true的元素用新值代替。
? ? replace_copy_if: ? ? ? ? ?與replace_if,不過將結果寫入另一個容器。
? ? swap: ? ? ? ? ? ? ? ? ? ? 交換存儲在兩個對象中的值。
? ? swap_range: ? ? ? ? ? ? ? 將指定范圍內的元素與另一個序列元素值進行交換。
? ? unique: ? ? ? ? ? ? ? ? ? 清除序列中重復元素,和remove類似,它也不能真正刪除元素。重載
版本使用自定義比較操作。
? ? unique_copy: ? ? ? ? ? ? ?與unique類似,不過把結果輸出到另一個容器。
?
? ? <四>排列組合算法(2個):提供計算給定集合按一定順序的所有可能排列組合
? ? next_permutation: ? ? ? ? 取出當前范圍內的排列,并重新排序為下一個排列。重載版本使用自
定義的比較操作。
? ? prev_permutation: ? ? ? ? 取出指定范圍內的序列并將它重新排序為上一個序列。如果不存在上
一個序列則返回false。重載版本使用自定義的比較操作。
?
? ? <五>算術算法(4個)
? ? accumulate: ? ? ? ? ? ? ? iterator對標識的序列段元素之和,加到一個由val指定的初始值上。
重載版本不再做加法,而是傳進來的二元操作符被應用到元素上。
? ? partial_sum: ? ? ? ? ? ? ?創建一個新序列,其中每個元素值代表指定范圍內該位置前所有元素
之和。重載版本使用自定義操作代替加法。
? ? inner_product: ? ? ? ? ? ?對兩個序列做內積(對應元素相乘,再求和)并將內積加到一個輸入的
初始值上。重載版本使用用戶定義的操作。
? ? adjacent_difference: ? ? ?創建一個新序列,新序列中每個新值代表當前元素與上一個元素的差
。重載版本用指定二元操作計算相鄰元素的差。
?
? ? <六>生成和異變算法(6個)
? ? fill: ? ? ? ? ? ? ? ? ? ? 將輸入值賦給標志范圍內的所有元素。
? ? fill_n: ? ? ? ? ? ? ? ? ? 將輸入值賦給first到first+n范圍內的所有元素。
? ? for_each: ? ? ? ? ? ? ? ? 用指定函數依次對指定范圍內所有元素進行迭代訪問,返回所指定的
函數類型。該函數不得修改序列中的元素。
? ? generate: ? ? ? ? ? ? ? ? 連續調用輸入的函數來填充指定的范圍。
? ? generate_n: ? ? ? ? ? ? ? 與generate函數類似,填充從指定iterator開始的n個元素。
? ? transform: ? ? ? ? ? ? ? ?將輸入的操作作用與指定范圍內的每個元素,并產生一個新的序列。
重載版本將操作作用在一對元素上,另外一個元素來自輸入的另外一個序列。結果輸出到指定容器。
?
? ? <七>關系算法(8個)
? ? equal: ? ? ? ? ? ? ? ? ? ?如果兩個序列在標志范圍內元素都相等,返回true。重載版本使用輸
入的操作符代替默認的等于操作符。
? ? includes: ? ? ? ? ? ? ? ? 判斷第一個指定范圍內的所有元素是否都被第二個范圍包含,使用底
層元素的<操作符,成功返回true。重載版本使用用戶輸入的函數。
? ? lexicographical_compare: ?比較兩個序列。重載版本使用用戶自定義比較操作。
? ? max: ? ? ? ? ? ? ? ? ? ? ?返回兩個元素中較大一個。重載版本使用自定義比較操作。
? ? max_element: ? ? ? ? ? ? ?返回一個ForwardIterator,指出序列中最大的元素。重載版本使用自
定義比較操作。
? ? min: ? ? ? ? ? ? ? ? ? ? ?返回兩個元素中較小一個。重載版本使用自定義比較操作。
? ? min_element: ? ? ? ? ? ? ?返回一個ForwardIterator,指出序列中最小的元素。重載版本使用自
定義比較操作。
? ? mismatch: ? ? ? ? ? ? ? ? 并行比較兩個序列,指出第一個不匹配的位置,返回一對iterator,
標志第一個不匹配元素位置。如果都匹配,返回每個容器的last。重載版本使用自定義的比較操作。
?
? ? <八>集合算法(4個)
? ? set_union: ? ? ? ? ? ? ? ?構造一個有序序列,包含兩個序列中所有的不重復元素。重載版本使
用自定義的比較操作。
? ? set_intersection: ? ? ? ? 構造一個有序序列,其中元素在兩個序列中都存在。重載版本使用自
定義的比較操作。
? ? set_difference: ? ? ? ? ? 構造一個有序序列,該序列僅保留第一個序列中存在的而第二個中不
存在的元素。重載版本使用自定義的比較操作。
? ? set_symmetric_difference: 構造一個有序序列,該序列取兩個序列的對稱差集(并集-交集)。
?
? ?<九>堆算法(4個)
? ? make_heap: ? ? ? ? ? ? ? ?把指定范圍內的元素生成一個堆。重載版本使用自定義比較操作。
? ? pop_heap: ? ? ? ? ? ? ? ? 并不真正把最大元素從堆中彈出,而是重新排序堆。它把first和
last-1交換,然后重新生成一個堆。可使用容器的back來訪問被"彈出"的元素或者使用pop_back進行真
正的刪除。重載版本使用自定義的比較操作。
? ? push_heap: ? ? ? ? ? ? ? ?假設first到last-1是一個有效堆,要被加入到堆的元素存放在位置
last-1,重新生成堆。在指向該函數前,必須先把元素插入容器后。重載版本使用指定的比較操作。
? ? sort_heap: ? ? ? ? ? ? ? ?對指定范圍內的序列重新排序,它假設該序列是個有序堆。重載版本
使用自定義比較操作。
?
4.適配器
STL提供了三個容器適配器:queue、priority_queue、stack。這些適配器都是包裝了vector、list、
deque中某個順序容器的包裝器。注意:適配器沒有提供迭代器,也不能同時插入或刪除多個元素。下面
對各個適配器進行概括總結。
(1)stack用法
#include <stack>
template < typename T, typename Container=deque > class stack;
可以使用三個標準順序容器vecotr、deque(默認)、list中的任何一個作為stack的底層模型。
bool stack<T>::empty() ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //判斷堆棧是否為空
void stack<T>::pop() ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? //彈出棧頂數據
stack<T>::push(T x) ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?//壓入一個數據
stack<T>::size_type stack<T>::size() ? ? ? ? ? ? ? ? //返回堆棧長度
T stack<T>::top() ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?//得到棧頂數據
?代碼示例:
stack<int> intDequeStack; ?
stack<int,vector<int>> intVectorStack; ?
stack<int,list<int>> intListStack;?
?
(2)queue用法
#include <queue>
template<typename T, typename Container = deque<T> > class ?queue;
第一個參數指定要在queue中存儲的類型,第二個參數規定queue適配的底層容器,可供選擇的容器只有
dequeue和list。對大多數用途使用默認的dequeue。
queue<T>::push(T x)
void queue<T>::pop()
T queue<T>::back()
T queue<T>::front()
queue<T>::size_type?
queue<T>::size()
bool queue<T>::empty()
代碼示例:
queue<int> intDequeQueue; ? ?
queue<int,list<int>> intListQueue;
?
(3)priority_queue用法
#include <queue>
template <typename T, typename Container = vector<T>, typename Compare = less<T> > class?
priority_queue;
priority_queue也是一個隊列,其元素按有序順序排列。其不采用嚴格的FIFO順序,給定時刻位于隊頭
的元素正是有最高優先級的元素。如果兩個元素有相同的優先級,那么它們在隊列中的順序就遵循FIFO
語義。默認適配的底層容器是vector,也可以使用deque,list不能用,因為priority_queue要求能對元
素隨機訪問以便進行排序。
priority_queue<T>::push(T x)
void priority_queue<T>::pop()
T priority_queue<T>::top()
priority_queue<T>::size_type?
priority_queue<T>::size()
bool priority_queue<T>::empty()
代碼示例:
priority_queue< int, vector<int>, greater<int> >
priority_queue< int, list<int>, greater<int> >
?
標準庫默認使用元素類型的<操作符來確定它們之間的優先級關系,用法有三:(下文轉自
http://www.cnblogs.com/vvilp/articles/1504436.html)
優先隊列第一種用法,通過默認使用的<操作符可知在整數中元素大的優先級高。
priority_queue<int> qi;?
示例中輸出結果為:9 6 5 3 2
優先隊列第二種用法,建立priority_queue時傳入一個比較函數,使用functional.h函數對象作為比較
函數。
priority_queue<int, vector<int>, greater<int> >qi2;
示例2中輸出結果為:2 3 5 6 9
優先隊列第三種用法,是自定義優先級。
struct node?
{
? ? ?friend bool operator< (node n1, node n2)
? ? ?{
? ? ? ? ?return n1.priority < n2.priority;
? ? ?}?
? ? ?int priority;
? ? ?int value;?
};?
priority_queue<node> qn;?
在示例3中輸出結果為:
優先級 ?值
9 ? ? ? ? ?5
8 ? ? ? ? ?2
6 ? ? ? ? ?1
2 ? ? ? ? ?3
1 ? ? ? ? ?4
在該結構中,value為值,priority為優先級。通過自定義operator<操作符來比較元素中的優先級。注
意:必須是自定義<操作符才行,把上述的結構中的<操作符改成>編譯不通過。
========
STL應用實例
一、vector的簡單應用
#include <iostream> ?
#include <vector> ?
??
int main() ?
{ ?
? ? std::vector<char> charVector; ?
??
? ? int x; ?
? ? for (x=0; x<10; ++x) ?
? ? ? ? charVector.push_back(65 + x); ?
??
? ? int size = charVector.size(); ?
? ? for (x=0; x<size; ++x) ?
? ? { ?
? ? ? ? std::vector<char>::iterator start = ?
? ? ? ? ? ? charVector.begin(); ?
? ? ? ? charVector.erase(start); ?
? ? ? ? std::vector<char>::iterator iter; ?
? ? ? ? for (iter = charVector.begin(); ??
? ? ? ? ? ? ? ? iter != charVector.end(); iter++) ?
? ? ? ? { ?
? ? ? ? ? ? std::cout << *iter; ?
? ? ? ? } ?
? ? ? ? std::cout << std::endl; ?
? ? } ?
??
? ? return 0; ?
} ?
二、deque的簡單應用
#include <iostream> ?
#include <deque> ?
??
int main() ?
{ ?
? ? std::deque<char> charDeque; ?
? ? int x; ?
? ? for (x=0; x<10; ++x) ?
? ? ? ? charDeque.push_front(65 + x); ?
??
? ? int size = charDeque.size(); ?
? ? for (x=0; x<size; ++x) ?
? ? { ?
? ? ? ? std::deque<char>::iterator start = ?
? ? ? ? ? ? charDeque.begin(); ?
? ? ? ? charDeque.erase(start); ?
? ? ? ? std::deque<char>::iterator iter; ?
? ? ? ? for (iter = charDeque.begin(); ??
? ? ? ? ? ? ? ? iter != charDeque.end(); iter++) ?
? ? ? ? { ?
? ? ? ? ? ? std::cout << *iter; ?
? ? ? ? } ?
? ? ? ? std::cout << std::endl; ?
? ? } ?
??
? ? return 0; ?
} ?
三、list的簡單應用
#include <iostream> ?
#include <list> ?
??
int main() ?
{ ?
? ? // Create and populate the list. ?
? ? int x; ?
? ? std::list<char> charList; ?
? ? for (x=0; x<10; ++x) ?
? ? ? ? charList.push_front(65 + x); ?
??
? ? // Display contents of list. ?
? ? std::cout << "Original list: "; ?
? ? std::list<char>::iterator iter; ?
? ? for (iter = charList.begin(); ??
? ? ? ? ? ? iter != charList.end(); iter++) ?
? ? { ?
? ? ? ? std::cout << *iter; ?
? ? ? ? //char ch = *iter; ?
? ? ? ? //std::cout << ch; ?
? ? } ?
? ? std::cout << std::endl; ?
? ? ??
? ? // Insert five Xs into the list. ?
? ? std::list<char>::iterator start = charList.begin(); ?
? ? charList.insert(++start, 5, 'X'); ?
??
? ? // Display the result. ?
? ? std::cout << "Resultant list: "; ?
? ? for (iter = charList.begin(); ??
? ? iter != charList.end(); iter++) ?
? ? { ?
? ? ? ? std::cout << *iter; ?
? ? ? ? //char ch = *iter; ?
? ? ? ? //std::cout << ch; ?
? ? } ?
? ? ??
? ? return 0; ?
} ?
四、set的簡單應用
#include <iostream> ?
#include <set> ?
??
int main() ?
{ ?
? ? // Create the set object. ?
? ? std::set<char> charSet; ?
??
? ? // Populate the set with values. ?
? ? charSet.insert('E'); ?
? ? charSet.insert('D'); ?
? ? charSet.insert('C'); ?
? ? charSet.insert('B'); ?
? ? charSet.insert('A'); ?
??
? ? // Display the contents of the set. ?
? ? std::cout << "Contents of set: " << std::endl; ?
? ? std::set<char>::iterator iter; ?
? ? for (iter = charSet.begin(); iter != charSet.end(); iter++) ?
? ? ? ? std::cout << *iter << std::endl; ?
? ? std::cout << std::endl; ?
??
? ? // Find the D. ?
? ? iter = charSet.find('D'); ?
? ? if (iter == charSet.end()) ?
? ? ? ? std::cout << "Element not found."; ?
? ? else ?
? ? ? ? std::cout << "Element found: " << *iter; ?
??
? ? return 0; ?
} ?
五、multiset的簡單應用
#include <iostream> ?
#include <set> ?
??
int main() ?
{ ?
? ? // Create the first set object. ?
? ? std::multiset<char> charMultiset1; ?
??
? ? // Populate the multiset with values. ?
? ? charMultiset1.insert('E'); ?
? ? charMultiset1.insert('D'); ?
? ? charMultiset1.insert('C'); ?
? ? charMultiset1.insert('B'); ?
? ? charMultiset1.insert('A'); ?
? ? charMultiset1.insert('B'); ?
? ? charMultiset1.insert('D'); ?
??
? ? // Display the contents of the first multiset. ?
? ? std::cout << "Contents of first multiset: " << std::endl; ?
? ? std::multiset<char>::iterator iter; ?
? ? for (iter = charMultiset1.begin(); ?
? ? ? ? ? ? iter != charMultiset1.end(); iter++) ?
? ? ? ? std::cout << *iter << std::endl; ?
? ? std::cout << std::endl; ?
??
? ? // Create the second multiset object. ?
? ? std::multiset<char> charMultiset2; ?
??
? ? // Populate the multiset with values. ?
? ? charMultiset2.insert('J'); ?
? ? charMultiset2.insert('I'); ?
? ? charMultiset2.insert('H'); ?
? ? charMultiset2.insert('G'); ?
? ? charMultiset2.insert('F'); ?
? ? charMultiset2.insert('G'); ?
? ? charMultiset2.insert('I'); ?
? ? ??
? ? // Display the contents of the second multiset. ?
? ? std::cout << "Contents of second multiset: " ?
? ? ? ? << std::endl; ?
? ? for (iter = charMultiset2.begin(); ?
? ? iter != charMultiset2.end(); iter++) ?
? ? ? ? std::cout << *iter << std::endl; ?
? ? std::cout << std::endl; ?
? ? ??
? ? // Compare the sets. ?
? ? if (charMultiset1 == charMultiset2) ?
? ? ? ? std::cout << "set1 == set2"; ?
? ? else if (charMultiset1 < charMultiset2) ?
? ? ? ? std::cout << "set1 < set2"; ?
? ? else if (charMultiset1 > charMultiset2) ?
? ? ? ? std::cout << "set1 > set2"; ?
? ? ??
? ? return 0; ?
} ?
六、map的簡單應用
#include <iostream> ?
#include <map> ?
??
typedef std::map<int, char> MYMAP; ?
??
int main() ?
{ ?
? ? // Create the first map object. ?
? ? MYMAP charMap1; ?
??
? ? // Populate the first map with values. ?
? ? charMap1[1] = 'A'; ?
? ? charMap1[4] = 'D'; ?
? ? charMap1[2] = 'B'; ?
? ? charMap1[5] = 'E'; ?
? ? charMap1[3] = 'C'; ?
??
? ? // Display the contents of the first map. ?
? ? std::cout << "Contents of first map: " << std::endl; ?
? ? MYMAP::iterator iter; ?
? ? for (iter = charMap1.begin(); ?
? ? ? ? ? ? iter != charMap1.end(); iter++) ?
? ? { ?
? ? ? ? std::cout << (*iter).first << " --> "; ?
? ? ? ? std::cout << (*iter).second << std::endl; ?
? ? } ?
? ? std::cout << std::endl; ?
??
? ? // Create the second map object. ?
? ? MYMAP charMap2; ?
??
? ? // Populate the first map with values. ?
? ? charMap2[1] = 'F'; ?
? ? charMap2[4] = 'I'; ?
? ? charMap2[2] = 'G'; ?
? ? charMap2[5] = 'J'; ?
? ? charMap2[3] = 'H'; ?
??
? ? // Display the contents of the second map. ?
? ? std::cout << "Contents of second map: " << std::endl; ?
? ? for (iter = charMap2.begin(); ?
? ? ? ? ? ? iter != charMap2.end(); iter++) ?
? ? { ?
? ? ? ? std::cout << (*iter).first << " --> "; ?
? ? ? ? std::cout << (*iter).second << std::endl; ?
? ? } ?
? ? std::cout << std::endl; ?
??
? ? // Compare the maps. ?
? ? if (charMap1 == charMap2) ?
? ? ? ? std::cout << "map1 == map2"; ?
? ? else if (charMap1 < charMap2) ?
? ? ? ? std::cout << "map1 < map2"; ?
? ? else if (charMap1 > charMap2) ?
? ? ? ? std::cout << "map1 > map2"; ?
? ? ??
? ? return 0; ?
} ?
七、multimap的簡單應用
#include <iostream> ?
#include <map> ?
??
typedef std::multimap<int, char> MYMAP; ?
??
int main() ?
{ ?
? ? // Create the first multimap object. ?
? ? MYMAP charMultimap; ?
??
? ? // Populate the multimap with values. ?
? ? charMultimap.insert(MYMAP::value_type(1,'A')); ?
? ? charMultimap.insert(MYMAP::value_type(4,'C')); ?
? ? charMultimap.insert(MYMAP::value_type(2,'B')); ?
? ? charMultimap.insert(MYMAP::value_type(7,'E')); ?
? ? charMultimap.insert(MYMAP::value_type(5,'D')); ?
? ? charMultimap.insert(MYMAP::value_type(3,'B')); ?
? ? charMultimap.insert(MYMAP::value_type(6,'D')); ?
??
? ? // Display the contents of the first multimap. ?
? ? std::cout << "Contents of first multimap: " << std::endl; ?
? ? MYMAP::iterator iter; ?
? ? for (iter = charMultimap.begin(); ?
? ? ? ? ? ? iter != charMultimap.end(); iter++) ?
? ? { ?
? ? ? ? std::cout << (*iter).first << " --> "; ?
? ? ? ? std::cout << (*iter).second << std::endl; ?
? ? } ?
? ? std::cout << std::endl; ?
??
? ? // Create the second multimap object. ?
? ? MYMAP charMultimap2; ?
??
? ? // Populate the second multimap with values. ?
? ? charMultimap2.insert(MYMAP::value_type(1,'C')); ?
? ? charMultimap2.insert(MYMAP::value_type(4,'F')); ?
? ? charMultimap2.insert(MYMAP::value_type(2,'D')); ?
? ? charMultimap2.insert(MYMAP::value_type(7,'E')); ?
? ? charMultimap2.insert(MYMAP::value_type(5,'F')); ?
? ? charMultimap2.insert(MYMAP::value_type(3,'E')); ?
? ? charMultimap2.insert(MYMAP::value_type(6,'G')); ?
??
? ? // Display the contents of the second multimap. ?
? ? std::cout << "Contents of second multimap: " << std::endl; ?
? ? for (iter = charMultimap2.begin(); ?
? ? ? ? ? ? iter != charMultimap2.end(); iter++) ?
? ? { ?
? ? ? ? std::cout << (*iter).first << " --> "; ?
? ? ? ? std::cout << (*iter).second << std::endl; ?
? ? } ?
? ? std::cout << std::endl; ?
??
? ? // Compare the multimaps. ?
? ? if (charMultimap == charMultimap2) ?
? ? ? ? std::cout << "multimap1 == multimap2"; ?
? ? else if (charMultimap < charMultimap2) ?
? ? ? ? std::cout << "multimap1 < multimap2"; ?
? ? else if (charMultimap > charMultimap2) ?
? ? ? ? std::cout << "multimap1 > multimap2"; ?
? ? ??
? ? return 0; ?
}
========
C++STL標準庫中隊列的運用
卡片游戲桌上有一疊牌,從第一張牌開始從上往下依次編號1~n。當至少還剩兩張牌時進行如下操作:把第一張牌扔掉,然后把新的第一張牌放到整疊牌的最后。輸入n,輸出每次扔掉的牌,以及最后剩下的牌。
樣例輸入:7
樣例輸出:1 3 5 7 4 2 6
代碼如下:
#include<iostream> #include<queue> using namespace std; queue<int> q; //聲明隊列 int main() {int n;cin>>n;for(int i=0;i<n;i++) q.push(i+1);while(!q.empty()){cout<<q.front()<<" ";q.pop();if(!q.empty()) //此處需要判斷此時隊列是否為空{q.push(q.front());q.pop();}}cout<<endl;return 0; }
========
應用C++ STL以最小堆方法解決Top K 問題
問題的來源我想不必多言了,很多的面試題中,以及<編程之美>中都有對問題的描述,以及相關的解法,寫本文的目的是以C++ STL的方式用最小堆解法解決這個問題。
那么什么是最小堆呢?
其實最小堆是一顆特殊二叉樹,其父節點的key小于其孩子節點,對!最小堆不是堆,是二叉樹!
最小堆解法其實可以將問題的時間復雜度縮減到nlgK, 但是本文由于沒有在C++ STL 中找到合適的函數保持最小堆(如果用自己寫代碼可以做到lgk),所以必須每次重建最小堆(如果您有更好的建議,歡迎指點),因此,時間復雜度為nk, 另外本文假設k<<n.
#include <iostream>
#include <algorithm>
#include <vector>
#include <functional>
?
using namespace std;
?
void TopKAlgorithm(int inputArray[], int nInputLength, int nOutputLength )
{
?
? ? ? ?//construct the minimum heap the size is K
? ? ? ?vector<int> vec(inputArray,inputArray+nOutputLength);
? ? ? ?make_heap (vec.begin(),vec.end(), greater<int>());
?
? ? ? ?for(int i=nOutputLength; i<10; i++)
? ? ? ?{
? ? ? ? ? ? ? if(inputArray[i] >= vec[0])
? ? ? ? ? ? ? {
? ? ? ? ? ? ? ? ? ? ?vec[0] = inputArray[i];
//此處其實只需要保持堆的性質即可,并不需要重建堆
? ? ? ? ? ? ? ? ? ? ?make_heap (vec.begin(),vec.end(), greater<int>());
? ? ? ? ? ? ? }
? ? ? ?}
?
? ? ? ?for(int i=0; i<nOutputLength; i++)
? ? ? ?{
? ? ? ? ? ? ? inputArray[i]=vec[i];
? ? ? ?}?
}
?
int main ()
{
?
?int InputValues[] = {10,200,30,5,15,110,2,42,6,36};
?
?
?TopKAlgorithm(InputValues, 10, 3);
?
?cout << "The top K Values are:";
?for (unsigned i=0; i<3; i++)
?{
? ? ? ? cout << " " << InputValues[i];
?}
?cout << endl;
?
?return 0;
}
總結
本文以最小堆解法解決了TOP K 問題,完全采用C++的STL原生函數加以實現,其中沒有手動加入任何操作最小堆的代碼,另外,本文的一個遺憾是第二次建堆的時候其實不是完全的必要,因為我們只需要保持對的性質就可以,
========
鏈接
http://stlchina.huhoo.net/twiki/bin/view.pl/Main/STLChina
stl中文站
總結
- 上一篇: eclipse调试一个struts2例子
- 下一篇: 一些常用黑客工具的初步使用