c++中级 STL基础学习(二)
deque
和vector差不多,可以在前端后端插入,一般用deque取代vector,vector只能在后端插入push_back()。deque还可以push_front(),但是deque后端插入比vecto稍慢。
list:双向链表,不能使用下标,和数组vector deque不同。只能使用迭代器,来指示元素。push_front,push_back,insert(位置,值),位置一般用迭代器来指定位置,其中insert返回的是一个迭代器。例如lis.insert(a.begin, );返回的是一个迭代器。删除使用erase(位置);或者erase(重哪里a,到哪里b);其中a位置包括,而b位置是不包括的,位置一般都是用的迭代器。list反转和排序:lis.reverse(), lis.sort().
可以使用distance(a, b);计算a到b的距离。 迭代器和迭代器范围
iter.begin是指向第一个,iter.end是指向最后一个的下一个,实质end是不包括的最后一个的,所以()begin=end()的时候,容器是空的。iter+n只有vector和deque可以有这种操作。list不可以。迭代器是个指针,所以const_iterator是迭代器指向的值不会变。通常用常迭代器作为for循环的迭代,相当于for(int i=;)中的i。
堆栈(容器适配器)
stack,LIFO形式。可以使用deque(默认) vector list做堆栈,stack<int, deque<int>> s。有empty() size() pop() top() push(item);push和pop都是始终指向栈顶。p.pop是删除数据,不返回删除的值,p.top()查看并返回查看的值。 队列(容器适配器)(堆栈和队列都没有迭代器,因为不能再中间进行操作数据,只能在两头进行,所以不能修改中间的数据)
queue, FIFO形式, queue不能用vector做队列(因为要求必须在两边进行操作,先进先出)。例如queue<int, list<int>> q; 或者指定为deque<int>(默认为deque)。操作,q.empty();q.size();q.front();查看队首,q.back();查看队尾,q.pop();q.push(item);push是在队尾操作,pop是在队首操作。 优先级队列(容器适配器)
priority_queue 不能使用list(因为要求能够对数据进行随机操作,而list不行),有最大最小优先级队列。priority_queue<int, deque<int>> pq;或者可以使用deque,vector(默认为), 不能使用list。pq.push(item),始终按循序排序(最大值(默认),或者最小值排序)。pq.size();获取大小数据个数。pq.top();查看,pq.pop();删除,因为队列始终指向队首,所以每次删除都是最大的(最小值)。pq.empty();判断是否为空。使用最小值优先级队列priority_queue<int ,deque<int>, greater<int>> pq;关键字greater<int>指示为最小值优先级队列。 顺序容器和容器适配器
vector list deque;stack queue priority_queue(优先级队列)
初始化问题使用默认的构造函数,带参数的构造函数
不同容器之间赋值,可以使用迭代器实现。
vector<int> ivec(ivec0); 使用同一种类型的顺序容器ivec0初始化ivec,这里ivec0必须是vector<int>类型。
但是list<string>slist(svec.begin(), svec.end());可以使用迭代器方式,对不同的容器赋值,例如svec是vector<string>类型。svec.begin()返回的是迭代器。svec.begin()+svec.size()/ 是指向svec向量对应的中间的数据元素。
list<string> slist();初始化了64个空字符串。或者list<string> slist(, "hello");初始化为64个hello字符串。定义一个类Foo,然后使用vector<Foo> a();初始化10个Foo对象,
和vector<Foo> a;不一样,vector<Foo> a(10);调用默认的构造函数,所以如果Foo没有默认的构造函数,那就出错了。如果vector<Foo> a(10, 1);调用Foo的构造函数,对应的参数为1;后面的1为形参表。
另外还有array,表示固定大小的数组,不支持push_back insert,但是提供了其他的STL操作,begin(), end(),size()等。
valarray类模板,支持很多数值计算。可以实现数据直接数值操作。但是性能可能稍微损失。可以结合slice类,灵活使用里面的元素 slice(start, num, stride),例如varint[slice(0, 4, 3)] = 10; 表示赋值valarray变量varint的第0个开始,取4个,每次取的步长为3的对应的位置处的值为10.
initializer_list类,需要头文件initializer_list 头文件,一般用于将一系列数值传递给构造函数或者其他函数;例如 int sum(const std::initializer_list<int> &ril); 直接可以sum({2, 3, 4})。vector能够使用std::vector<int> vec = ({2, 3, 4})的原因,是vector构造函数使用initializer_list
作为构造函数参数。
顺序容器的操作()
vector list deque操作类似。容器定义的类型别名,vector<int>::size_type a1(常常替换for中的int a1); iterator const_iterator(const容器返回const迭代器) reverse_iterator(对应rbegin,rend) const_reverse_iterator difference_type value_type reference const_reference类型。
顺序容器的操作()
c.push_back(), c.push_front()(向量没有), c.insert(p, value),插在p所指元素的前面。 c.insert(p,num,value);在p的前面插入num个value。c.insert(p, beginp, endp);
顺序容器的操作()
关系运算,比较的容器必须具有相同的数据类型
顺序容易的操作()
size() 返回数据个数,max_size()返回最多保持多少数据,empty(), resize()等
顺序容器的操作()
访问元素(返回的是引用):c.back(),c.front(), c[n],c.at(n)后面两个只对vector和deque有效,对list没效果,并且使用at比用[]方式要好,特别是处理异常的时候。
而c.begin();返回的是迭代器,迭代器是指针。
vector<int>::reference a = ivec.front();
vector<int>::reference a = *ivec.begin();因为ivec.begin()返回的是迭代器,所以用指针。
顺序容易的操作()
删除元素 c.erase(p), c.erase(b, e), c.clear(),c.pop_back(),c.pop_front(). pop_front只适用于list和deque。
list<string>::iterator iter = find(b,e,"value"); e表示迭代器,删除中,不包括。s
顺序容器的操作()
赋值和交换c1=c2 c1.swap(c2)类型必须相同才能进行, c1.assign(b, t),类型兼容即可 vector容器的自增长
vector用数组做出来,但是有数组更多的优点。vecv.capacity()返回向量以供可以存放多少数据,但是这个容量是自增长的,每次 增加50%或者和使用的C++有关,不需要去控制,而vecv.size是数组里面存了多少数据。 reserve。 顺序容器的选用
vector deque(数组形式,所以插入删除操作会很慢,但是排序,查找很快) list是个链表,所以插入删除操作insert eraser很快,但是排序sort 查找binary_search很慢。 push_back对list很快。 构造string对象的方法
string s1(s2) s1(, 'a') s1="str" s1(s.begin(), s.end())等等 修改string对象的方法
s.intert s.assign string对象的比较
s.compare(s2)等等 map multimap也是容器,是红黑树结构
插入数据:map<int, string> a; a.insert(map<int, string>::value_type(, "one")); a.insert(make_pair(-, "two"));(最常用), a.insert(pair<int,string>(, "one hundred")); a[]="one thousand";给map 插入数据赋值,通过键值对的方式;a.size();获取a有多少个键值对。所有容器都有迭代器都有对应的迭代器。可以通过迭代器获得对应的键值:map<int, string>::const_iterator i; i = a.begin(); i->first; i->second;获得对应的值,这里是int和string值;multimap 和map一样,只是需要放重复的数据的时候,得使用multimap,并且可以使用count()获取含有100的个数,另外第四种数组的形式,即a[]="one thounsand"不能在multimap中使用。
查找(因为map是红黑树结构,数据搜索查找会很快):map<int, string>::const_iterator i = a.find(); if(i !=a.end()),{cout<<"no found the 100"}; 也可以直接映射,或者字典,或者关联数组。使用a[]和使用a.find()一样,返回结果会是“one hundrred”。
删除:a.erase() if(a.rease()>){cout<<"delete success"} a.erase(b, e); b和e分别是开始的迭代器和结束的迭代器。 set和multiset 是集和多集。也是一种容器,红黑树结构。set<int> a; 有操作insert, count find,erase。同样multiset也是可以允许重复,但是,set不允许重复。注意不能通过find进行修改,因为set和multiset每次插入数据,是自动进行了排序的。。 STL算法简介,100多种算法,函数对象,函数适配器,三个头文件#include <algorithm> <numeric> <functional>
函数对象简介
for_each(起始指针,结束指针,函数或者函数对象) ;例如for_each(ivec.begin(), ivec.end(), display()); greater<int>(), less<int>(),plus<int>() 等等,是一些预定义的函数对象。
将一个类作为函数对象,使用operator,函数对象的好处:一般比普通的函数要快,有自己的状态。
例如:以下是一个函数对象,调用的时候,可以直接PRINT();打印a的值,使用这个类,像使用函数一样
class PRINT{
public:
void operator()(int elem) const{ //调用的时候,自动调用里面的operator函数方法
cout<<elem<<'';
}
};
函数适配器 count_if(ivec.begin(). ivec.end(), bind2nd(greater<int>(), );其中bind2nd是预定义的函数适配器,表示大于4的数。 元素计算算法:
通用的count count_if 对所有的容器都可以用,速度相对慢些,例如count(ivec.begin(), ivec.end(), ),计算这个ivec里面有几个4, count_if(ivec.begin(). ivec.end(), 函数或者函数对象),计算ivec中满足函数或者函数对象的数。关联容器的元素计算算法,例如set.count, map.count, multiset.count, multimap.count这个比通用的计算容器快些。
最小最大值算法:
min_element(b, e); min_element(b, e, op) 同理max。其中op为函数或者函数对象。
查找算法()
find find_if 查找效率比较慢,如果是已序空间的算法,一般用关联容器适配器自带的算法那。string类型不能使用find和find_if,查找的结果是一个迭代器。find(b, e, ); 将找到的第一个4,返回对应的迭代器,指向相对应的值。
茶渣算法()
search_n(b, e, c, n)连续的大于n的数的起始位置。search_n(b, e, c, n,greaater<int>())连续c个大于n的数起始位置.
查找算法()
search() find_end(),是一对,search()重前面开始查找,find_end()从后面开始查找。search(l.begin(), l.end(), k.begin(),k.end());在l的开始到结束中,找k的开始到结束中的数据,例如从l( )找k( );返回在l中对应的起始位置。
查找算法()
find_first_of(b, e, sb, se); find_first_of(b, e, se, bp); 没有find_last_of(一般用逆向迭代器实现),在b,e之间找含有sb到se中的任意数,的起始位置,就可以了。所以存的是找到的在sb到se中第一个数据出现在b到e中的起始位置。
string查找函数和stl查找算法的比较,首先,这些方法都是string的成员函数,而stl中是对应的algorithm中的方法:string:find stl:find; string:rfind stl:find+逆向迭代器;string:find,stl:search;string:rfind, stl:find_end; string:find_first_of stl:find_first_of; string find_last_of,stl:find_first_of+逆向迭代器;逆向迭代器vector<int>::reverse_iter irve, irve.base();输出的是对应的正向的位置;string::npos,对应的string自定义的成员变量;
查找算法()
adjacent_find(b, e);查找连续两个相等的或者; adjacent_find(b, e, p);两个连续的复合谓词规则的两个;
查找算法要使用得当,例如,如果是已序区间,就用已序区间查找算法例如binary_search()等等。
查找算法()
已序区间查找,要求必须先排好序,这样查找就比较快,binary_search(b, e, v)二分法查找数字v,或者带有谓词p查找,binary_search(b, e, v, p); 区间查找:includes(b,e,sb,se)或者带有谓词includes(b,e,sb,se,p);,lower_bound(), upper_bound(), equal_range();
查找算法()(已序区间算法,都必须先排序)
lower_bound(b,e,v), upper_bound(b,e,v);lower找到值为v的第一个数的位置,这里返回的是index(从0开始),upper是找到值为v的最后一个位置,所以这两个算法主要用于查找到有序的数据中某个数据的位置后,方便插入运算。
equal_range()返回既包括lower_bound又包括upper_bound,返回的是一对迭代器,例如pair<list<int>::iterator, list<int::iterator>> range; range = equal_range(b, e, v);通过range.first()和range.second();
如果有关联式容器,那就不要用这些方法,因为关联式容器有对应的算法,性能更加; for_each()算法:
for_each(b,e,p);可以遍历数据,和函数对象修改数据,以及使用for_each的返回值。如果p是函数对象,则返回值也是函数对象,例如 MeanValue mv = for_each(ivec.begin(),ivec.end(), MeanValue()); 算法交换
swap_ranges(b,e,b2); 如果是全部数据交换,并且是相同数据类型交换,一把用容器的成员函数swap() 填充新值:(修改性算法)
fill(b,e,v),填充之后,原来的被替换掉了; fill_n(b,n,v) generate(b,e,p) generate_n(b,n,p)。v是值,p是函数对象。 替换算法:
replace(b,e,ov,nv); 把旧的值ov替换为新的值nv,replace_if(b,e,p,v) replace_copy(b1,e1,b2,ov,nv) replace_copy_if(b1,e1,b2,p,v) 删除算法():
remove(b,e,v) vemove_if(b,e,p) 这里是一种逻辑删除,不是真正的删除,这里返回的是删除的最后的一个元素的终点,因为,remove的删除操作仅仅是后面的复制到后面,来覆盖,没有移动的部分的值是不不变的。即list: ,remove(b,e,)之后,变为1 ;
最后的两个一般使用容器的删除成员函数来删除,erase(end, list.end())才是真正的删除后面的4 ;
删除算法():
remove_copy() remove_copy_if(),把一个容器的数据复制到另外一个容器中,复制的过程中使用remove逻辑删除。
删除算法():
unique(b,e)或者 unique(b,e,p) unique_copy(b,e,newb) unique_copy(b,e,,newb,p);删除连续的重复的数字的算法或者删除连续的数字满足p条件的第二个数字的算法,注意没有unique_if和 unique_copy_if 逆转和旋转:
reverse() reverse_copy() rotate() rotate_copy() 算法排列组合:使用前,数据一般都需要先排序
next_permutation(b,e)下一个排列组合,如果返回值为true,表示排列组合还没有结束,还有排列组合,否则,就没有下一个排列组合了。 prev_permutation(b,e)与next 重排分区算法:
randon_shuffer(b,e)随机重排,就像洗扑克牌,重新打乱。 partition(b,e,p)把符合规则p的数据放在前面,其他的放在后面进行分区,并且分区以后,每个区域也是打乱重排了的,算法返回值为一个迭代器,即分区的分界的位置。stable_partition(b,e,p),稳定的分区,
即符合规则p的在前面,不符合规则的在后面,但是在每个区的相对顺序是不变的。 排序算法:
sort(b,e)默认从小到大排序 sort(b,e,p) stable_sort(b,e) stable_sort(b,e,p),注意:这里的排序算法不适合随机存取容器,因此不适合list容器,因为list容器不能随机存取。
局部排序:
partial_sort(b,se,e) b到e之间的数据排序,如果排序的序列中排到了se的位置,则后面的都不排序了,所以到底有多少个进行了排序不知道。partial_sort(b,se,e,p) partial_sort_copy(sb,se,db,de) partial_sort_copy(sb,se,db,de,p)
根据第n个元素进行排序:
nth_element(b,n,e) b到e之间排序,拍到第n个结束,所以知道有n个元素进行了排序。nth_element(b,n,e,p) 对比partial()算法。
堆排序算法:
make_heap(b,e)将向量变成堆,即二叉树规则进行排序。 push_heap(b,e)将一个数据加到堆里,这里前提是先将要push的数据push到原数据的对尾,然后进行二叉树排序形成新的堆。
pop_heap(b,e)将最大的,也就是树顶的元素放到了最后,其他的数据重新生成堆,进行了二叉树进行排序了。 sort_heap 对堆进行排序,形成普通的排序, 二叉树排序,
c++中级 STL基础学习(二)的更多相关文章
- Python入门基础学习 二
Python入门基础学习 二 猜数字小游戏进阶版 修改建议: 猜错的时候程序可以给出提示,告诉用户猜测的数字偏大还是偏小: 没运行一次程序只能猜测一次,应该提供多次机会给用户猜测: 每次运行程序,答案 ...
- Python基础学习二
Python基础学习二 1.编码 utf-8编码:自动将英文保存为1个字符,中文3个字符.ASCll编码被囊括在内. unicode:将所有字符保存为2给字符,容纳了世界上所有的编码. 2.字符串内置 ...
- Go基础学习(二)
数组[array] 数组定义[定义后长度不可变] 12 symbol := [...]string{USD: "$", EUR: "€", GBP: " ...
- Django基础学习二
今天继续学习django的基础 学习用户提交url如何获得返回值 1.首先需要在工程的urls文件定义指定的urls要路由给哪个函数 在这个例子中,我们定义home的urls路由给views里的tes ...
- salesforce lightning零基础学习(二) lightning 知识简单介绍----lightning事件驱动模型
看此篇博客前或者后,看一下trailhead可以加深印象以及理解的更好:https://trailhead.salesforce.com/modules/lex_dev_lc_basics 做过cla ...
- CSS入门基础学习二
我们下午继续学习CSS的入门基础,搬上你的小板凳赶快进入吧! 一.背景(background) Background-color:背景颜色 background-image (背景图片) backgr ...
- WebService基础学习(二)—三要素
一.Java中WebService规范 JAVA 中共有三种WebService 规范,分别是JAX-WS.JAX-RS.JAXM&SAAJ(废弃). 1.JAX-WS规范 ...
- jQuery基础学习(二)—jQuery选择器
一.jQuery基本选择器 1.CSS选择器 在学习jQuery选择器之前,先介绍一下之前学过的CSS选择器. 选择器 语法 描述 示例 标签选择器 E { ...
- HTML基础学习(二)—CSS
一.CSS概述 CSS(Cascading Stytle Sheets)层叠样式表,用来定义网页的显示效果.可以解决HTNL代码对样式定义的重复,提高了后期样式代码的可维护性,并增强了网页的显 ...
随机推荐
- 测试工具之Charles视频教程(更新中。。。)
应群里小伙伴学习需求,录制新版 Charles V4 系列教程,后续内容抽空更新,测试工具系列带你上王者...(ノ°ο°)ノ前方高能预警 链接:http://pan.baidu.com/s/1c16P ...
- 也谈Oracle异常: ORA-06502: PL/SQL: 数字或值错误 : 字符串缓冲区太小
场景: .Net程序调用Oracle方法 command.ExecuteNonQuery()执行存储过程;弹出如标题异常信息. 存储过程有4个输入参数,一个输出参数.一旦执行到给输出参数赋值的时候就报 ...
- ios 开发小技巧一
对于UITableViewCell中的textField/textView,你肯定想让它编辑时可以把所在行滚动到键盘上方.如果你的VC是UITableViewController或者子类,那么只要在o ...
- 将框架的底层改掉,改成一个轻量级的ORM
公司底层的缺点 1.功能有限,只有增删查改 2.不支持异步 3.不支持懒加载 4.不支持泛型 5.不支持Linq 6.性能没做到最好,比如FirsttOrDefault()只能通过查找select * ...
- 62. Divide Two Integers
Divide Two Integers Divide two integers without using multiplication, division and mod operator. 思路: ...
- HEAP CORRUPTION 错误
一般是new一块内存过小, 在这个内存块上写入的内容过大, delete时出现的错误; 如: char* ptr = new char[2]; //申请了两个字节 *ptr = "1234 ...
- 使用jquery获取url以及jquery获取url参数的方法
使用jquery获取url以及使用jquery获取url参数是我们经常要用到的操作 1.jquery获取url很简单,代码如下 1.window.location.href; 其实只是用到了javas ...
- NUGET命令
主题 about_NuGet 简短说明 提供有关 NuGet 程序包管理器命令的信息. 详细说明 本主题介绍 NuGet 程序包管理器命令.NuGet 是一种集成的程序包 管理工具,用于将库和工具添加 ...
- 第九十八天请假 PHP TP框架 空操作和命名空间
访问空方法解决办法->在控制器里面创建 _empty 方法 <?php namespace Home\Controller; use Think\Controller; class Ind ...
- 万象客户端设置服务端ip保存在注册表的位置
HKEY_LOCAL_MACHINE\SOFTWARE\Sicent\wx2004Clt 这个注册表被保护了,不能修改和删除,但可以在安全模式操作.