C with STL入门详解(适合初学者)
2018-01-27 17:52
393 查看
1.STL是什么?
STL是Standard Template Library的简称,中文名
2.
字面意思,咱们考试用得上的C++其实就是C+STL,大一上我们已经学习了C语言课程,大二上我们已经学习了数据结构课程,有了这两门课程的基础,学习C+STL并非难事。
3.为什么要学STL呢?
方便。比如你要实现一个链式队列,以及它的一系列功能,你需要敲几十乃至上百行代码,还要投入精力debug,可在STL里,给你做好现成的queue你用不用?现成的快排你用不用?平均复杂度
4.我有兴趣了,怎么学呢?
熟能生巧。
下面步入主题。
先来一点下酒菜。
1.
交换值在C语言课上作为指针讲解的典例,不会就直接套呗。
2.
使用sort是一个越用越活的过程,你要喜欢,还能用:
sort的平均时间复杂度是
3.
4.
5.
6.
功能:
我们来看看百度百科的解释
lower_bound()返回一个 iterator 它指向在[first,last)标记的有序序列中可以插入value,而不会破坏容器顺序的第一个位置,而这个位置标记了一个不小于value 的值。
意思就是:找到第一个位置,使得:在这个位置插入value后,原有序序列依旧有序。
这是lower_bound,那upperbound的效果呢?
找到最后一个位置,使得:在这个位置插入value后,原有序序列依旧有序。
用法如下(上面讲了upper的不同,下面只拿lower做样例,不赘述upper):
上面这些提到的函数都是些基础吧,不定期更新。
下面开始介绍一些好用的容器。
1.
1.1 vector(不定长数组,向量)。
1.2 我们有数组,为什么还要用vector呢?
菜刀可以削皮,削皮刀也可以削皮;菜刀可以切丝,切丝器也可以切丝。菜刀这么多用处,那我们为什么还要用削皮刀和切丝器呢?每种不同的数据结构在不同场合下能发挥出不同的作用。(致敬eric)
1.3实例:邻接表
传送门
2.
2.1 集合中的元素有三个特征:
1.确定性(集合中的元素必须是确定的)。
2.互异性(集合中的元素互不相同)。
3.无序性(集合中的元素没有先后之分)。
2.2 set容器是由红黑树实现的。在这里我们尽量把STL容器当作黑箱子使用,不需要知道原理,会用就行。
2.3 由于set的一些特性,我们可以用来做一些特定的工作。十分方便。
待更
STL是Standard Template Library的简称,中文名
标准模板库。简单来说就是封装好的一些组件。对于咱们考试而言,重要的有
容器(containers)和算法(algorithms)两部分。
2.
C with STL是什么?
字面意思,咱们考试用得上的C++其实就是C+STL,大一上我们已经学习了C语言课程,大二上我们已经学习了数据结构课程,有了这两门课程的基础,学习C+STL并非难事。
3.为什么要学STL呢?
方便。比如你要实现一个链式队列,以及它的一系列功能,你需要敲几十乃至上百行代码,还要投入精力debug,可在STL里,给你做好现成的queue你用不用?现成的快排你用不用?平均复杂度
O(nlogn)的排序只要几句话,手写一个冒泡也得好几行吧?还卡时。
4.我有兴趣了,怎么学呢?
熟能生巧。
下面步入主题。
先来一点下酒菜。
1.
swap(交换两元素值,在algorithm下,用法:swap(a,b);)
交换值在C语言课上作为指针讲解的典例,不会就直接套呗。
int a=1,b=2; swap(a,b); //此时a=2,b=1
2.
sort(对序列进行排序,在algorithm下)
//数组排序: int a[10]={1,3,5,7,9,2,4,6,8,0}; sort(a,a+10); //如果用的是vector,这样写 vector<int> a; sort(a.begin(),a.end());//之后会提到vector,这里不做解释 //默认由小到大排序,当然我们可以重载排序的顺序 bool cmp(int a,int b)//从大到小排序 { return a>b; } //然后 sort(a,a+10,cmp); sort(a.begin(),a.end(),cmp);
使用sort是一个越用越活的过程,你要喜欢,还能用:
sort(a,a+10,greater<int>()); sort(a.begin(),a.end(),less<int>());
sort的平均时间复杂度是
O(nlogn),适可而止,适可而止。
3.
reverse(翻转序列,在algorithm下)
//这个不难,翻转嘛,常用在字符串上 int a[5]={1,2,3,4,5}; reverse(a,a+5); //序列现在是 5 4 3 2 1 char s[]="ericxie"; reverse(s,s+strlen(s)); //序列现在是 "eixcire" 同样适用于string//这个待会儿说 string s="qwer"; reverse(s.begin(),s.end());
4.
min,max(取大,取小)
int a=1,b=2,c; c=min(a,b); //此时c等于1 c=max(a,b); //此时c等于2
5.
__gcd(这东西想必大家都不陌生了)
手写gcd函数也行,这里介绍一下用法。 int a=4,b=6; int c=__gcd(a,b); //注意下划线,此时c等于2
6.
lower_bound和
upper_bound(二分查找)
功能:
我们来看看百度百科的解释
lower_bound()返回一个 iterator 它指向在[first,last)标记的有序序列中可以插入value,而不会破坏容器顺序的第一个位置,而这个位置标记了一个不小于value 的值。
意思就是:找到第一个位置,使得:在这个位置插入value后,原有序序列依旧有序。
这是lower_bound,那upperbound的效果呢?
找到最后一个位置,使得:在这个位置插入value后,原有序序列依旧有序。
用法如下(上面讲了upper的不同,下面只拿lower做样例,不赘述upper):
//数组 int a[100]={1,2,4,4,9,12,12,15}; int pos1 = lower_bound(a,a+8,4)-a; int pos2 = upper_bound(a,a+8,4)-a; //在这个样例下,pos1!=pos2 根据我的理解,这里lower_bound(a,a+8,value)得到的是一个地址,拿这个地址减去数组首地址a[0],那么刚好就是value应该放入的位置。 //vector vector<int> a; 若a中目前的元素也是{1,2,4,4,9,12,12,15}; 那么 这里用lower_bound得到的应该也是一个类似于指针的东西,为什么不叫它指针呢?因为他有了一个名字,叫做迭代器。 vector<int>::iterator it; it = lower_bound(a.begin(),a.end(),4); //这里的it就是迭代器,那么*it就是该下标对应的value了。 //set(集合,放到后面讲) set<int> a; 这里只介绍它的使用方法: set<int>::iterator it; it = a.lower_bound(value); 差不多了。 //吧?
上面这些提到的函数都是些基础吧,不定期更新。
下面开始介绍一些好用的容器。
1.
vector
1.1 vector(不定长数组,向量)。
1.2 我们有数组,为什么还要用vector呢?
菜刀可以削皮,削皮刀也可以削皮;菜刀可以切丝,切丝器也可以切丝。菜刀这么多用处,那我们为什么还要用削皮刀和切丝器呢?每种不同的数据结构在不同场合下能发挥出不同的作用。(致敬eric)
1.3实例:邻接表
下面就以邻接表为例展开介绍。 struct edge{//定义边 int from,to,value; } const int maxn = 1e5+5; //声明: vector<edge> map[maxn];//一维向量相当于二维数组,便于理解。 在这里,如果我们使用二维数组存邻接表,需要开销一个1e10的空间,如果图中实际边数只有1e6,用数组无疑会造成极大浪费。 1.3.1 //初始化: for(int i=0;i<maxn;i++) { map[i].clear(); //clear函数能清空向量,不是变成0,是清空。 } 下面还是用vector<int> a作为样例 a:{1,2,3,4,5,6,7,8,9} 1.3.2 //求向量中元素个数 int n = a.size();//此时n等于9 1.3.3 //取向量首个元素的迭代器 vector<int>::iterator it = a.begin(); 注意这里得到的是迭代器,如果要直接得到值: 1.3.4 //取向量首个元素值 int value = a.front();//此时value等于1 1.3.5 //和begin对应的是end vector<int>::iterator it = a.end(); 注意,这里的it指向向量a末尾的下一个位置,注意是下一个位置,下一个位置。 1.3.6 //和front对应的是back,取向量尾部的元素值 int value = a.back();//此时value等于9 1.3.7 //直接下标访问(这个地方和数组很像) int value0 = a[0];//下标从0开始的,所以下标是不超过a.size()-1的 int value1 = a[1]; 1.3.8 //往尾部添加一个元素(重要,重要,重要) 由于我们不知道再添加元素是放在哪里,所以搞了个push_back函数,往尾部添加一个元素。 a.push_back(value); //若value为1,则 a:{1,2,3,4,5,6,7,8,9,1} 1.3.9 //与之对应,我们还有pop_back(),用于删除尾部第一个元素。 a.pop_back();//pop后,序列为 a:{1,2,3,4,5,6,7,8} 1.3.10 //前面提到了reverse函数,翻转向量。 a.reverse(a.begin() , a.end()); //翻转后的序列 a:{9,8,7,6,5,4,3,2,1} 1.3.11 //判断向量是否为空 bool isempty = a.empty(); 向量为空 isempty等于true,否则等于false 1.3.12 //常用的如上,一些不常用的可以在这里找到,这里贴个网址
传送门
2.
set(集合)
2.1 集合中的元素有三个特征:
1.确定性(集合中的元素必须是确定的)。
2.互异性(集合中的元素互不相同)。
3.无序性(集合中的元素没有先后之分)。
2.2 set容器是由红黑树实现的。在这里我们尽量把STL容器当作黑箱子使用,不需要知道原理,会用就行。
2.3 由于set的一些特性,我们可以用来做一些特定的工作。十分方便。
2.4 主要函数的使用方法 2.4.1 声明一个set容器 set<int> s; //下面用set<int> s作为例子 初始s:{1,2,3,4,5}; 2.4.2 清空集合 s.clear(); //清空后的 s:{}; 2.4.3 插入一个元素x s.insert(x); //如果x等于1,那么插入后的 s:{1,2,3,4,5};(互异性) //如果x等于6,那么插入后的 s:{1,2,3,4,5,6}; 前面我们提到set由树实现,那么插入一个元素的平均时间复杂度应该是O(logn)的,并且在用迭代器遍历set时,得到的元素应该是有序的。 2.4.4 查询集合里有无元素x int hav = s.count(x); 同样,平均时间复杂度是O(logn) 因为set的特性,集合里要么有x(表示为1),要么没有(为0)。 2.4.5 在集合里找到x的位置,返回迭代器 set<int>::iterator it = s.find(x); 如果找到了x,那么it指向x所在的位置 2.4.6 遍历集合所有元素 for(set<int>::iterator it = s.begin();it!=s.end();it++) { int x = *it;cout<<x<<","; } 或者 for(auto x:s) { cout<<x<<" ";//这里的x就是元素值 } //两种方法输出的结果都是1,2,3,4,5, 2.4.7 判断是否为空集 bool isempty = s.empty(); 2.4.8 求集合元素个数 int n = s.size(); 2.4.9 删除元素x s.erase(x); //如果x等于4,那么删除后的集合 s:{1,2,3,5};
待更
相关文章推荐
- STL基础篇(适合初学者快速入门)
- STL基础篇(适合初学者快速入门)
- Linux入门——适合初学者
- 适合初学者入门的Java基础视频
- java抽象类和接口详解(很适合初学者)
- golang采集,适合golang初学者入门,笔者亦是新手
- Linux入门——适合初学者
- 遗传算法详解(GA)(个人觉得很形象,很适合初学者)
- 分享一篇文章,关于Android Build系统的详解,很适合新手的入门
- Linux入门——适合初学者
- 强烈推荐visual c++ 2012入门经典适合初学者入门
- Linux入门——适合初学者
- html入门教程适合初学者(1)
- PHP视频从入门到精通---适合PHP初学者
- 转载:遗传算法详解(GA)(个人觉得很形象,很适合初学者)
- 课程1:历经5年锤炼(史上最适合初学者入门的Java基础视频)--视频列表
- OKHttp使用详解,步骤挺详细的,适合初学者使用!
- Linux入门——适合初学者
- 白话讲反射技术 --- 适合初学者入门引导
- Linux入门——适合初学者