C++ STL STL是Standard Template Library 是一种泛型编程 STL从广义上分为 容器(container) 算法(algorithm) 迭代器(iterator) 目前广泛认为STL有六大组件
容器 可以说容器就是将一些常用的数据结构用模版实现出来 容器中包括的常用数据结构有: 字符串(string)
定长数组(array)
动态数组(vector)
链表(list)
栈(stack)
队列(queue)
双端队列(deque)
树(tree)
集合(set)
映射(map)
根据数据在容器中的排列特性 这些数据分为序列式容器和关联式容器两种 序列式容器强调值的排序 序列式容器中的每个元素均有固定的位置 除非用删除或插入的操作改变这个位置 Vector容器 Deque容器 List容器等 关联式容器是非线性的树结构 更准确的说是二叉树结构 各元素之间没有严格的物理上的顺序关系 也就是说元素在容器中并没有保存元素置入容器时的逻辑顺序 关联式容器另一个显著特点是:在值中选择一个值作为关键字key 这个关键字对值起到索引的作用 方便查找 Set/multiset容器 Map/multimap容器
string string构造函数 1 2 3 4 5 6 7 8 9 10 11 12 string ();string (const string &str);string (const char *s);string (int n,char c);string s1; string s2 ("syh" ) ;string s3="syh02" ; string s4 (10 ,'k' ) ;string s5=s2;
string重载运算符的基本赋值操作 1 2 3 4 5 6 7 8 9 10 11 string &operator =(const char *s); string &operator =(const string &s); string &operator =(char c); string& assign (const char *s) ;string& assign (const char *s, int n) ;string& assign (const string &s) ;string& assign (int n, char c) ;string& assign (const string &s, int start, int n) ;
string获取相应位数的字符操作 1 2 3 4 char &operator [](int n);char &at (int n) ;
string字符串的拼接(在结尾处添加) 1 2 3 4 5 6 7 8 string &operator +=(const string &str); string &operator +=(const char *str); string &operator +=(const char c); string &append (const char *s) ;string &append (const char *s,int n) ;string s1;s1.append ("syh" ,2 );#把"syh" 的前2 位拼接在s1后面string& append (const string &s) ;string& append (int n, char c) ;string& append (const string &s, int pos, int n) ;
string查找和替换 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 int find (const string& str, int pos = 0 ) const ; int find (const char * s, int pos = 0 ) const ; int find (const char * s, int pos, int n) const ; int find (const char c, int pos = 0 ) const ; int rfind (const string& str, int pos = npos) const ;int rfind (const char * s, int pos = npos) const ;int rfind (const char * s, int pos, int n) const ;int rfind (const char c, int pos = 0 ) const ;eg:s1="abcdefgabcdfe" ; int i=s1.rfind ("a" ,12 ); #i=7 string &replace (int pos,int n,const string &str) ;string &replace (int pos,int n,const string *s) ;
string比较大小 1 2 3 4 int compare (const string &str) ;int compare (const char *s) ;
string子串 1 2 string substr (int pos=0 ,int n=npos) const ;
string插入和删除 1 2 3 4 5 6 7 string &insert (int pos,const char *s) ;string &insert (int pos,const string &str) ;string &insert (int pos,int n,char c) ;string &erase (int pos,int n=npos) ;
c++ string和C-type字符串互相转化 1 2 3 4 5 6 7 8 string str="it" ; const char *cstr=str.c_str ();char *s="it" ;string str (s) ;
vector vector起到了动态数组的作用 加入新元素内部会自动扩容 vector支持随机存取 所以vector提供的是随机访问迭代器(Random Access Iterators)
vector常用方法 1 2 3 4 #include <vector> vector<int > v; v.push_back (i); v.capacity ();
因为vector采取的是线性连续空间 它以两个迭代器_Myfirst和_Mylast分别指向配置得来的连续空间中目前已被使用的范围 并以迭代器_Myend指向整块连续内存空间的尾端 意思就是_Myfirst指向数组的头部 _Mylast指向数组的尾部 _Myend指向数组大小空间真正的最后一块
vector构造函数 1 2 3 4 5 vector<T> v; vector v1 (n,elem) ;vector<T> v1 (v.begin(),v.end()) ;vector<T> v1 (v) ;vector<T> v={1 ,2 ,3 };
vector赋值 1 2 3 4 5 6 7 8 assign (begin,end);assign (n,elem);vector &operator =(const vector &vec); swap (&vec); vector<int > v1={1 ,3 ,5 ,7 ,9 };vector<int > v2={2 ,4 ,6 ,8 ,10 }; v1.swap (v2); v1与v2数组的内容互换了 v1是246810 v2是13579
vector长度空间操作 1 2 3 4 5 6 7 size ();empty (); resize (int n);resize (int n,elem);v.capacity (); reserve (int len);
vector容器如果空间不足 将会重新申请一块更大的空间然后将元素都复制过去 再释放旧有的空间
用swap缩短内存空间 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 #include <iostream> #include <vector> vector<int > v; for (int i=0 ;i<100000 ;i++){ v.push_back (i); } cout << "capacity:" << v.capacity () << endl; cout << "size:" << v.size () << endl; v.resize (100 ); cout << "capacity:" << v.capacity () << endl; cout << "size:" << v.size () << endl; vector <int > (v).swap (v); cout << "capacity:" << v.capacity () << endl; cout << "size:" << v.size () << endl;
vector取数据 1 2 3 4 at (int n);operator [](int n);front ();back ();
vector插入删除 1 2 3 4 5 6 push_back (ele);pop_back ();insert (const_iterator pos, int count,ele);erase (const_iterator start, const_iterator end);erase (const_iterator pos);clear ();
vector在尾部插入数据 也可以在头部插入数据 但是效率很低很低 因此引入deque容器概念
deque deque可以高效率的对头端进行元素的插入和删除 并且没有容量的概念 因为deque逻辑上是由动态的以分段连续空间组合而成 随时可以增加一段新空间连接起来 实际上deque是由一段一段的定量的连续空间构成 一旦有必要在deque前端或者尾端增加新的空间 便配置一段连续定量的空间 串接在deque的头端或者尾端 Deque最大的工作就是维护这些分段连续的内存空间的整体性的假象 并提供随机存取的接口 避开了重新配置空间 复制 释放的轮回 代价就是复杂的迭代器架构 deque的迭代器非常复杂 所以除非有必要 应该尽可能的先使用vector 对deque的排序操作 可以通过先将deque的元素复制到vector中 排序后再复制回deque中来提高效率
deque采取了一块连续的内存空间作为主控 其中每一个元素都是一个指针 指向另一段连续的存储空间(缓冲区) 这些存储空间存储了deque的元素
deque构造函数 1 2 3 4 deque<T> D; deque<T> D (D1.begin(),D1.end()) ;deque<T> D (n,elem) ;deque (const deque &deq);
deque赋值 1 2 3 4 assign (begin (),end ());assign (n,elem);deque &operator =(const deque &deq); swap (deq);
deque长度空间操作 1 2 3 4 size ();empty ();resize (int n);resize (int n,elem);
deque双端插入删除 1 2 3 4 5 6 7 8 9 10 push_back (elem);push_front (elem);pop_back ();pop_front ();insert (const_iterator pos, int count,ele);erase (const_iterator start, const_iterator end);erase (const_iterator pos);clear ();
deque取数据 1 2 3 4 at (int n);operator [](int n);front ();back ();
stack stack栈是一个先进后出的数据结构 stack容器允许新增/移除元素 取栈顶元素 stack容器不允许遍历元素 stack没有迭代器
stack构造函数 1 2 stack<T> stk; stack (const stack &stk);
stack赋值 1 stack& operator =(const stack &stk);
stack存取 1 2 3 push (elem);pop ();top ();
stack空间
queue 队列是一种先进先出的数据结构 队头出 队头进
queue构造函数 1 2 3 #include <queue> queue<T> q; queue (const queue &q);
queue赋值 1 queue &operator =(const queue &q);
queue存取 1 2 3 4 push (elem);pop ();back ();front ();
queue空间
list list容器是一个循环的双向链表 list对元素的插入和删除效率都非常高 list容器不能像vector一样用普通的指针作为迭代器 因为它的节点不能保证在同一块连续的内存空间上 list容器提供的迭代器是Bidirectional Iterators
list构造函数 1 2 3 4 list<T> l; list (l.begin (),l.end ());list (n,elem)list (const list &l);
list赋值 1 2 3 4 assign (begin,end);assign (n,elem);list &operator =(const list &l); swap (l);
list空间 1 2 3 4 size ();empty ()resize (int n);resize (int n,elem);
list存取数据
list插入删除 1 2 3 4 5 6 7 8 9 10 11 12 13 push_back (elem);pop_back ();push_front (elem);pop_front ();insert (const_iterator pos, int count,ele);insert (pos,begin (),end ());insert (pos,elem);erase (begin,end);erase (pos);clean ();remove (elem);
list排序
set/multiset set是一个关联容器 不需要做内存拷贝和内存移动 set用来存储同一数据类型的容器 在set容器中 每个元素的值都是唯一的 并且系统根据元素的值进行自动排序 multiset特性与用法和set完全相同 唯一的区别是multiset允许元素的值重复 C++ STL中标准关联容器set
multiset
map
multimap
内部采用的就是一种非常高效的平衡检索二叉树:红黑树 也称为RB树(Red-Black Tree) RB树的统计性能要好于一般平衡二叉树 set中元素的值不能被直接改变 因为set元素值就是它的key值 关系到set元素的排序规则 简言之set容器的迭代器是const_iterator
set构造函数 1 2 set<T> st; set (const set &st);
set赋值 1 2 set &operator =(const set &s); swap (s);
set查找操作 1 2 3 4 5 find (key);count (key);lower_bound (keyElem);upper_bound (keyElem);equal_range (keyElem);
set插入删除 1 2 3 4 5 6 insert (elem);clear ()erase (pos);erase (begin,end);erase (elem);
用迭代器遍历输出set内数据 1 2 3 4 5 6 7 8 9 10 #include <set> set<int > s; s.insert (5 ); s.insert (2 ); s.insert (3 ); set<int >::iterator x; for (x=s.begin ();x!=s.end ();++x){ cout<<*x<<" " ; }
pair pair容器的类型定义需要引入头文件#include<utility>
pair存有两个值 这一对值可以有不同的数据类型 两个值分别可以用first和second访问
pair构造函数 1 2 3 4 pair<T1,T2> p1; pair<T1,T2> p1 (v1,v2) ;pair<T1,T2> p1= make_pair (v1,v2); pair<T1,T2> p1=p2;
map/multimap map容器中存放的元素都是pair类型的 这一对值中第一个被视为键(key) 第二个被视为值(value) map不允许两个元素有相同的key map有助于处理一对一映射数据 map容器中所有元素会根据元素的key自动排序 不能通过map的迭代器改变map的值 因为map的key关系到map元素的排列规则 若想要修改map的value是可以的 与set容器相同 multimap的键值可以重复
map构造函数 1 2 3 map<T1,T2> mapt; map (const map &mapt);map (iterator begin,iterator end);
map赋值 1 2 map &operator =(const map &mapt); swap (mp);
map空间操作 1 2 3 size ();empty ();max_size ();
map插入删除 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 #include <map> map<int ,string> student; student.insert (map<int ,string>::value_type (100 ,"syh" )); student.insert (pair <int ,string>(200 ,"sc" )); student.insert (make_pair (300 ,"abc" )); student[3 ]="test" ; map<int ,string>::iterator iter; for (iter=student.begin ();iter!=student.end ();++iter){ cout<<iter->first<<" " <<iter->second<<endl; }
程序输出结果为: 3 test 100 syh 200 sc 300 abc
map查找 1 2 3 4 5 6 7 find (key);count (key);lower_bound (keyElem);upper_bound (keyElem);equal_range (keyElem);
map删除数据 1 2 3 erase (map<T1,T2>::iterator iter);erase (key);erase (map<T1,T2>::iterator iter1,map<T1,T2>::iterator iter2);
STL容器表格对比 ||vector|deque|list|set|multiset|map|multimap| |:——:|:——:|:——:|:——:|:——:|:——:|:——:|:——:|:——:|:——:| |数据结构|单端数组|双向队列|循环双向链表|二叉树|二叉树|二叉树|二叉树| |随机存取|是|是|否|否|否|key(否)|key(否)| |元素寻找|慢|慢|非常慢|快|快|key(快)|key(快)| |元素增减|尾端|头/尾|任何位置|-|-|-|-|
算法 STL收录了大量常用的算法例如排序sort() 查找find()等等 特定的算法搭配特定的数据结构 算法分为质变算法和非质变算法 质变算法是指运算过程中会改变元素的内容 例如拷贝替换删除等 非质变算法是指运算过程中不会改变元素的内容 例如查找遍历寻找极值等等
迭代器 迭代器(iterator)是一种抽象的设计概念 《设计模式》一书中囊括了共23种设计模式的完整描述 其中关于迭代器的定义为:提供一种方法 使之能够依照次序寻访某个容器中的各个元素 并且还可以不暴露容器的内部表示方式 综上 迭代器就是在某一容器中进行某种算法的操作 可谓是容器和算法的粘合剂 容器和算法分开独立设计 再由迭代器粘合在一起 这也是STL的中心思想 迭代器的种类分为: 输入迭代器 输出迭代器 前向迭代器 双向迭代器 随机访问迭代器