先前参加了蓝桥杯的省赛,侥幸进入了国赛,本来是准备全心考研,但又多了这么一次机会,那就好好准备吧。此前对于算法,我一直都是用纯C来编写。经过辅导老师点拨,国赛时纯C的算法很大可能会超时,所以为了能取得好成绩,还是了解一下吧。
一,STL的组成部分
1).容器(containers):是一种数据结构容器,使用类模板的方法提供,我们可以方便的进行数据的存储操作
2).适配器(adapters):以序列式容器为基础,提供的栈,队列和优先级队列的这种容器
3).迭代器(iterator):类似于指针,用来操作容器的元素
4).算法(algorithm):包含一系列常见的算法
5).空间适配器(allocator):其中的主要工作包括两部分:1,对象的创建和销毁。2,内存的创建与释放
6).仿函数(function):仿函数又称为函数对象,其实就是好重载了()操作符的struct,没有什么特别的地方
二,STL的容器
1,序列式容器
1).每个元素都有固定的位置,取决于插入时机和地点。与元素值无关。
2).vector(向量):底层数据结构是数组,可以随机存取数据元素(用索引直接存取),数组的尾部添加和移除元素很快,但在头部和中部插入元素比较耗时。
//vector容器简单用法
//输入
#include <iostream> #include <vector> #include <stdio.h> using namespace std; int main(void) { //vector(动态数组)有内存管理的机制, //也就是说对于插入和删除,vector可以动态调整所占用的内存空间。 vector<int> tmp; for(int i=0;i<10;i++) { tmp.push_back(i); } //获得tmp的迭代器it,it初始化为tmp的开头,遍历到tmp的结尾 for(vector<int>::iterator it = tmp.begin();it!=tmp.end();it++) { cout<<*it<<" "; //对迭代器it进行解引用 } return 0; }
#include <iostream> #include <vector> #include <algorithm> #include <ctime> using namespace std; void print(vector<int> tmp); bool comp(const int &a,const int &b) { return a>b; } int main(void) { vector<int> tmp; for(int i=0;i<10;i++) { tmp.push_back(rand()%100); } print(tmp); //颠倒 reverse(tmp.begin(),tmp.end()); print(tmp); //默认升序 sort(tmp.begin(),tmp.end()); print(tmp); //降序 sort(tmp.begin(),tmp.end(),comp); print(tmp); return 0; } void print(vector<int> tmp) { for(vector<int>::iterator it = tmp.begin();it!=tmp.end();it++) { cout<<*it<<" "; } cout<<endl; }
3).deque(双端队列):底层数据结构是数组,可以随机存取数据元素,在数组的头部和尾部插入和删除元素很快。
/* deque和vector一样,采用线性表,与vector唯一不同的是,deque采用的分块的线性存储结构, 每块大小一般为512字节,称为一个deque块,所有的deque块使用一个Map块进行管理, 每个map数据项记录各个deque块的首地址,这样以来,deque块在头部和尾部都可已插入和删除元素, 而不需要移动其它元素。使用push_back()方法在尾部插入元素,使用push_front()方法在首部插入元素, 使用insert()方法在中间插入元素。 */ #include <iostream> #include <deque> using namespace std; int main(void) { deque<int> tmp; for(int i=0;i<10;i++) { if(i%2==0) tmp.push_front(i); else tmp.push_back(i); } tmp.insert(tmp.begin+4,101); //用insert从中间插入 //可以使用下标遍历,此处使用迭代器 for(deque<int>::iterator it = tmp.begin();it!=tmp.end();it++) cout<<*it<<" "; return 0; }
4).list(列表):底层数据结构是双向链表,不提供随机存取数据元素(需要按顺序走到要存取的元素),在任何位置插入和删除都很快,只需要移动一下指针。
#include <iostream> #include <list> using namespace std; int main(void) { list<int> tmp; tmp.push_back(5); tmp.push_front(2); tmp.push_back(2); tmp.push_front(32); tmp.push_back(6); tmp.push_front(7); tmp.push_back(0); tmp.push_front(1); for(list<int>::iterator it = tmp.begin();it!=tmp.end();it++) cout<<*it<<" "; cout<<endl; //排序 tmp.sort(); for(list<int>::iterator it = tmp.begin();it!=tmp.end();it++) cout<<*it<<" "; cout<<endl; //排除重复的(得先排序) tmp.unique(); for(list<int>::iterator it = tmp.begin();it!=tmp.end();it++) cout<<*it<<" "; cout<<endl; return 0; }
2,关联式容器
1).元素位置取决于特定的排序准则,和插入的顺序无关,底层数据结构是二叉树。
2).set(集合):内部元素依据其值自动排序,set内相同的数值元素只能出现一次。
/* set是用红黑树的平衡二叉索引树的数据结构来实现的,插入时,它会自动调节二叉树排列, 把元素放到适合的位置,确保每个子树根节点的键值大于左子树所有的值、小于右子树所有的值, 插入重复数据时会忽略。set迭代器采用中序遍历,检索效率高于vector、deque、list, 并且会将元素按照升序的序列遍历。set容器中的数值,一经更改,set会根据新值旋转二叉树, 以保证平衡,构建set就是为了快速检索 multiset,multiset与set的不同之处就是key可以重复, 以及erase(key)的时候会删除multiset里面所有的key并且返回删除的个数。 */ #include <iostream> #include <set> using namespace std; struct Comp{ //自定义比较函数(元素本身不是结构体) bool operator()(const int &a,const int &b) { return a>b; } }; int main(void) { set<int> tmp; tmp.insert(5); tmp.insert(6); tmp.insert(1); tmp.insert(3); tmp.insert(4); tmp.insert(2); tmp.insert(6); //自动升序 for(set<int>::iterator it = tmp.begin();it!=tmp.end();it++) { cout<<*it<<" "; } cout<<endl; //降序遍历 for(set<int>::reverse_iterator it = tmp.rbegin();it!=tmp.rend();it++) { cout<<*it<<" "; } cout<<endl; set<int,Comp> tmpC; tmpC.insert(5); tmpC.insert(6); tmpC.insert(1); tmpC.insert(3); tmpC.insert(4); tmpC.insert(2); tmpC.insert(6); //自定义比较函数,降序 for(set<int,Comp>::iterator it = tmpC.begin();it!=tmpC.end();it++) { cout<<*it<<" "; } cout<<endl; return 0; }3).multiset(多重集合):内部元素依据其值自动排序,set内可以出现重复的元素。
4).map(映射):map的元素是成对的键值对,内部元素的值依据键自动排序,键只可以出现一次
/* map也是使用红黑树,他是一个键值对(key:value映射),便利时依然默认按照key程序的方式遍历,同set。 */ #include <iostream> #include <map> #include <string> using namespace std; int main(void) { map<string,double> tmp; tmp["A"] = 12.5; tmp["B"] = 35.2; tmp["D"] = 45.2; tmp["C"] = 452.1; //遍历时,按照键排序输出 for(map<string,double>::iterator it = tmp.begin(); it != tmp.end(); ++it) { cout<<(*it).first<<"->"<<(*it).second<<endl; } return 0; }
三,STL的适配器
1),什么是适配器
STL提供了三种适配器stack,queue和priority_queue。这些适配器是包装了序列式容器(vector,deque,list)中的一种。
因此所谓的适配器就是序列式容器的包装器,注意:适配器没有提供迭代器。
2).stack(栈)
栈可以使用序列式容器中的vector,deque,list中的任意一种作为其底层的数据结构。默认是使用deque来实现的stack。
#include <iostream> #include <stack> using namespace std; int main(void) { stack<int> tmp; tmp.push(2); tmp.push(1); tmp.push(3); tmp.push(4); tmp.push(5); tmp.push(28); tmp.push(7); cout<<"size is:"<<tmp.size()<<endl; while(!tmp.empty()) //栈不为空 ,适配器没有迭代器 { cout<<tmp.top()<<" "; tmp.pop(); //移除栈顶元素 } return 0; }
3).queue(队列)
队列可以使用deque和list中的任意一种作为其底层的数据结构。默认是使用deque来实现的queue。
4).priority_queue(优先队列)
优先队列也是一种队列,不过在进入队列之后会对元素进行排序,可以使用vector和deque来实现其底层结构,默认是使用
vector来实现priority_queue。
#include <iostream> #include <queue> using namespace std; int main(void) { priority_queue<int> tmp; tmp.push(1); tmp.push(3); tmp.push(2); tmp.push(8); tmp.push(9); tmp.push(0); cout << "size: " << tmp.size() << endl; while(!tmp.empty())//如果优先队列为空,则返回真 { cout << tmp.top()<<" "; //返回优先队列中有最高优先级的元素 tmp.pop(); //删除第一个元素 } return 0; }
5).序列式容器和适配器比较