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() 返回优先队列中有最高优先级的元素