For efficiency reasons, STL is not object-oriented:html
STL是c++的精華,開始前先在此提一下。linux
有助於整體理解的連接:[C++ STL] 各容器簡單介紹ios
The Standard Template Library (STL) is a part of the C++ standard library, Some others are:c++
分類一:算法
分類二:數組
Containers: vector, list, stack, ...
Algorithms: find, sort, copy, ...
Iterators are the glue between the two!安全
(1) 數據流中的數據按照必定的格式<T>提取 -------> 放在vector中。數據結構
(2) 注意 vector.begin(), vector.front()的區別。"front"是返回當前vector容器中起始元素的引用。less
(3) accumulate()求sum。(與valarrary貌似有一拼,孰優孰劣?---- 可能後者效率更高)ide
accumulate(ivec.begin() , ivec.end() , 0);
(4) multiplies<int>() c++ --> reference --> <functional> --> multiplies: 與accumulate配合使用構成了連乘的計算。
#include<math.h> #include<iostream> #include<fstream> #include<algorithm> #include<functional> #include<numeric> #include<vector> #include<iterator>
int main() { std::vector<int> v; std::ifstream in("numbers.txt");
std::copy(std::istream_iterator<int>(in), std::istream_iterator<int>(), std::back_inserter(v)); for (unsigned int i = 0; i < v.size(); i++) { std::cout << v[i] << std::endl; }
std::sort(v.begin(), v.end());
std::cout << "min/max: " << v.front() << " " << v.back() << std::endl; std::cout << "median: " << *(v.begin() + (v.size()/2)) << std::endl;
std::cout << "average: " << accumulate(v.begin(), v.end(), 0.0) / v.size() << std::endl; std::cout << "geomean: " << std::pow( accumulate(v.begin(), v.end(), 1.0, std::multiplies<double>()), 1.0/v.size() ) << std::endl; }
(5) copy()做爲輸入的技巧,以及map的使用。
int test02(void) { using namespace std; std::vector<string> v;
std::map<string, int> m; std::ifstream in("words.txt"); std::copy(std::istream_iterator<string>(in), std::istream_iterator<string>(), std::back_inserter(v)); // The number of times it occurs in a file.
for (auto vi = v.begin(); vi != v.end(); ++vi) ++m[*vi]; for (auto mi = m.begin(); mi != m.end(); ++mi) std::cout << mi->first << ": " << mi->second << std::endl; return 0; }
(6) copy()做爲輸出的技巧:拷貝到ostream。
int test03(void) { std::vector<int> v = {1, 3, 5, 4, 3, 2}; std::string s("string"); std::sort(v.begin(), v.end()); std::copy(v.begin(), v.end(), std::ostream_iterator<int>(std::cout, ",")); std::cout << std::endl; std::sort(s.begin(), s.end()); std::copy(s.begin(), s.end(), std::ostream_iterator<char>(std::cout, " ")); std::cout << std::endl; return 0; }
In reality, not all operations are supported in all containers,
http://www.cplusplus.com/reference/stl/
須要逐個實踐下,爲下一節作準備
Ref: 關於vector的resize()的理解
resize()的做用是改變vector中元素的數目。
若是n比當前的vector元素數目要小,vector的容量要縮減到resize的第一個參數大小,既n。並移除那些超出n的元素同時銷燬他們。
若是n比當前vector元素數目要大,在vector的末尾擴展須要的元素數目,若是第二個參數val指定了,擴展的新元素初始化爲val的副本,不然按類型默認初始化。
注意:若是n大於當前的vector的容量(是容量,並不是vector的size),將會引發自動內存分配。因此現有的pointer, references, iterators將會失效。
int func_vector_insert(void) { cout << "== vector insert() show ==" << endl; std::vector<int> myvector (3,100); std::vector<int>::iterator it; it = myvector.begin(); it = myvector.insert ( it , 200 ); //某位置插入一個數字 for (auto p = myvector.begin(); p != myvector.end(); p++) { std::cout << (*p) << ", "; } std::cout << std::endl; myvector.insert (it,2,300); //某位置插入若干數字 for (auto p = myvector.begin(); p != myvector.end(); p++) { std::cout << (*p) << ", "; } std::cout << std::endl; // "it" no longer valid, get a new one: it = myvector.begin(); std::vector<int> anothervector (2,400); myvector.insert (it+2, anothervector.begin(), anothervector.end()); //某位置插入一段動態同類的數字 for (auto p = myvector.begin(); p != myvector.end(); p++) { std::cout << (*p) << ", "; } std::cout << std::endl; int myarray [] = { 501,502,503 }; myvector.insert (myvector.begin(), myarray, myarray+3); //某位置插入一段靜態同類的數字 std::cout << "myvector contains:"; for (it=myvector.begin(); it<myvector.end(); it++) std::cout << ' ' << *it; std::cout << '\n'; return 0; } //****************************************************************************** void func_vector(void) { // vector<int> vec= new vector(); vector<int> vec= {1, 2, 3, 4, 5}; cout << vec.at(0) << endl; cout << "size = " << vec.size() << endl; cout << "capacity = " << vec.capacity() << endl; cout << "resize(10)\n"; vec.resize(10); /* Jeff --> I don't like unsigned here. */ // for (unsigned int i = 0; i < vec.size(); i++) // { // cout << vec.at(i) << "\n"; // } for (auto p = vec.begin(); p != vec.end(); p++) { // Jeff --> endl == \n + flush cout << (*p) << ' '; } cout << endl; cout << "size = " << vec.size() << endl; cout << "capacity = " << vec.capacity() << endl; cout << "vec.clear()" << endl; vec.clear(); cout << "size = " << vec.size() << endl; cout << "capacity = " << vec.capacity() << endl; //----------------------------------------------------------------------------- for (int i = 1; i <= 10; i++) { vec.push_back(i); }
// Jeff --> vector<int>::iterator iter = vec.begin();
// 可以使用通用的iterator方式,畢竟list不能直接l.begin()+1這麼用! cout << "erase(0-2)" << endl; vec.erase(vec.begin(), vec.begin() + 3); for (auto p = vec.begin(); p != vec.end(); p++) { // Jeff --> endl == \n + flush cout << (*p) << ' '; } cout << endl; cout << "size = " << vec.size() << endl; cout << "capacity = " << vec.capacity() << endl; //----------------------------------------------------------------------------- func_vector_insert(); //----------------------------------------------------------------------------- cout << "vec.front() = " << vec.front() << endl; cout << "push_back(111)" << endl; vec.push_back(111); for (auto p = vec.begin(); p != vec.end(); p++) { // Jeff --> endl == \n + flush cout << (*p) << ' '; } cout << endl; cout << "size = " << vec.size() << endl; cout << "capacity = " << vec.capacity() << endl; }
void func_vector2(void) { vector<vector<int>> vector2; vector<int> v1 = {1, 2, 3, 4, 5}; vector<int> v2 = {1, 2, 3, 4, 5}; vector2.push_back(v1); vector2.push_back(v2); for (auto it_v = vector2.begin(); it_v != vector2.end(); it_v++) { for (auto it_sub_v = (*it_v).begin(); it_sub_v != (*it_v).end(); it_sub_v++) { cout << (*it_sub_v) << ' '; } cout << endl; } }
void func_catch(void) { vector<string> words = { "Hello", "World" }; for (unsigned int i = 0; i < words.size(); ++i) { cout << words[i] << endl; } try { cout << words.at(2) << endl; } catch(const std::out_of_range &e) { cout << e.what() << endl; } }
區別在於處理類時,若是有malloc就有有不一樣,會涉及到引用計數的問題。詳見:assign、retain和copy的區別
// vector assign
// 與 insert比較類似
#include <iostream> #include <vector> int main () { std::vector<int> first; std::vector<int> second; std::vector<int> third; first.assign (7, 100); // 分配 七個100
for (auto p = first.begin(); p != first.end(); p++) { std::cout << (*p) << std::endl; } std::cout << "============================" << std::endl; std::vector<int>::iterator it; it=first.begin()+1; second.assign (it, first.end()-1); // first上的一段數據 (動態數組)
for (auto p = second.begin(); p != second.end(); p++) { std::cout << (*p) << std::endl; } int myints[] = {1776, 7, 4}; third.assign (myints, myints+3); // myints上的一段數據 (靜態數組) std::cout << "Size of first: " << int (first.size()) << '\n'; std::cout << "Size of second: " << int (second.size()) << '\n'; std::cout << "Size of third: " << int (third.size()) << '\n'; return0; }
void func_assign() { vector<int> v1(10); // vector<float> v2 = v1; vector<float> v2; v2.assign(v1.begin(), v1.end()); // 可能的優點:v1轉化爲了v2類型 }
在鏈表上的指針位移操做。
void func_list(void) { list<int> l = {1, 2, 3, 4, 5}; list<int> l2(5, 8); list<int>::iterator iter = l.begin(); list<int>::iterator iter2 = l.begin();
// Jeff --> 不知能直接++, 就設計了這個函數 advance (iter2, 2); l.erase(iter, iter2); for(auto p = l.begin(); p != l.end(); p++) { cout << (*p) << ' '; } cout << endl; //Jeff --> notice: here will be a 野指針! // l2.insert(l2.begin(), iter, iter2);
l2.insert(l2.begin(), l.begin(), l.end()); for(auto p = l2.begin(); p != l2.end(); p++) { cout << (*p) << ' '; } cout << endl; }
// splicing lists #include <iostream> #include <list> int main () { std::list<int> mylist1, mylist2; std::list<int>::iterator it; // set some initial values:
for (int i=1; i<=4; ++i) mylist1.push_back(i); // mylist1: 1 2 3 4
for (int i=1; i<=3; ++i) mylist2.push_back(i*10); // mylist2: 10 20 30
it = mylist1.begin(); ++it; // points to 2 mylist1.splice (it, mylist2); // mylist1: 1 10 20 30 2 3 4 // mylist2 (empty) // "it" still points to 2 (the 5th element) mylist2.splice (mylist2.begin(),mylist1, it); // mylist1: 1 10 20 30 3 4 // mylist2: 2 // "it" is now invalid. it = mylist1.begin(); std::advance(it,3); // "it" points now to 30 mylist1.splice ( mylist1.begin(), mylist1, it, mylist1.end()); // mylist1: 30 3 4 1 10 20 std::cout << "mylist1 contains:"; for (it=mylist1.begin(); it!=mylist1.end(); ++it) std::cout << '' << *it; std::cout << '\n'; std::cout << "mylist2 contains:"; for (it=mylist2.begin(); it!=mylist2.end(); ++it) std::cout << '' << *it; std::cout << '\n'; return0; }
void func_splice(void) { list<string> words = {"hello", "world"}; list<string> words2 = {"lovely"}; words.splice(++words.begin(), words2); for (auto p = words.begin(); p != words.end(); p++) { cout << *p << endl; } cout << "=============================" << endl;
//-------------------------------------------------
// 單向鏈表
forward_list<int> myfl1 = {1, 2, 3}; forward_list<int> myfl2 = {4, 5, 6}; // Jeff --> iterator's next position. myfl1.splice_after(myfl1.begin(), myfl2); for (auto p = myfl1.begin(); p != myfl1.end(); p++) { cout << *p << endl; } }
在順序容器的基礎上再包裝一層,造成常見的數據結構。
容器適配器, more details: http://blog.csdn.net/thefutureisour/article/details/7751846
咱們已有的容器(好比vector、list、deque)支持的操做不少,好比插入,刪除,迭代器訪問等等。而咱們但願這個容器表現出來的是棧的樣子:先進後出,入棧出棧等等,此時,咱們沒有必要從新動手寫一個新的數據結構,而是把原來的容器從新封裝一下,改變它的接口,就能把它當作棧使用了。
C++中定義了三種容器適配器,它們讓容器提供的接口變成了咱們經常使用的的3種數據結構:棧(先進後出), 隊列(先進先出), 優先級隊列。
至於具體是怎麼變的,咱們能夠先了解一個大概:
固然,咱們也能夠指定本身的實現方式。可是因爲數據結構的關係,咱們也不能胡亂指定:
void func_stack(void)
{
std::stack<int> foo, bar; foo.push (10); foo.push(20); foo.push(30); bar.push (111); bar.push(222);
// 交換了兩個container的內容 foo.swap(bar); std::cout << foo.top() << std::endl; foo.pop(); std::cout << foo.top() << std::endl; foo.pop(); std::cout << "size of foo: " << foo.size() << '\n'; std::cout << "size of bar: " << bar.size() << '\n'; }
void func_queue(void) { queue<int> que; for (int i = 1; i <= 5; i++) { que.push(i); } cout << que.size() << endl; while(!que.empty()) {
// print & pop是兩碼事! cout << que.front() << ' '; que.pop(); } cout << endl; }
void func_priority_queue(void) { priority_queue<int, vector<int>, greater_equal<int>> mypq; mypq.push(rand()); mypq.push(rand()); mypq.push(rand()); mypq.push(rand()); mypq.push(rand()); while(!mypq.empty()) { cout << mypq.top() << endl; mypq.pop(); } //--------------------------------------------------------------------------
typedef struct { int a; int b; }Node; Node *myNode = new Node[10]; struct cmp { bool operator()(const Node &t1, const Node &t2) { // Jeff --> less return t1.b < t2.b; } }; for (int i = 0; i < 10; i++) { myNode[i].a = i; myNode[i].b = i+10; } priority_queue< Node, vector<Node>, cmp > Q(myNode, myNode+10); while(!Q.empty()) { cout << Q.top().b << endl; Q.pop(); } }
1.empty() 堆棧爲空則返回真 2.pop() 移除棧頂元素 3.push() 在棧頂增長元素 4.size() 返回棧中元素數目 5.top() 返回棧頂元素
1.back() 返回一個引用,指向最後一個元素 2.empty() 若是隊列空則返回真 3.front() 返回第一個元素 4.pop() 刪除第一個元素 5.push() 在末尾加入一個元素 6.size() 返回隊列中元素的個數
1.empty() 若是優先隊列爲空,則返回真 2.pop() 刪除第一個元素 3.push() 加入一個元素 4.size() 返回優先隊列中擁有的元素的個數 5.top() 返回優先隊列中有最高優先級的元素