STL的使用


Vector:不定长数组

Vector是C++里的不定长数组,相比传统数组vector主要更灵活,便于节省空间,邻接表的实现等。而且它在STL中时间效率也很高效:几乎与数组不相上下。

#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <vector> //定义头文件

using namespace std;

vector<int> v; //定义一个vector数组,类型为int

int main()
{
 v.clear(); //清空vector
 v.push_back(1); //从后端插入元素“1”
 
 int k=v[0]; //vector可以像数组一样读取
 int len=v.size(); //返回vector数组长度
 
 v.pop_back(); //从后端弹出元素
 
 if (v.empty()) printf("The vector is empty!\n"); //检测vector是否为空,是则返回true,否则返回false

 vector<int>::iterator it; //定义迭代器

 v.push_back(10); v.push_back(5);

 sort(v.begin(),v.end()); //vector也可排序,只是要用这种形式传递
 for (it=v.begin();it!=v.end();it++) //遍历vector
 	printf("%d\n",*it);
 return 0;
}

实际上vector还有push_front()等操作,但从前端插入会引起大量元素移动,浪费大量时间,不提倡使用。


SET:集合

C++里的集合SET就是数学上的集合:不允许重复元素。
另外,因为SET中元素是始终有序的,所以可用作某些“排序更新”类的操作。

#include <cstdio>
#include <set> //定义头文件
#include <algorithm>
#include <cstdlib>

using namespace std;

set<int> s; //定义SET

int main()
{
 s.clear(); //清空集合
 s.insert(1); //插入元素“1”
 if (s.count(1)) printf("Yes\n"); else printf("No\n"); //如果元素存在,返回true,否则返回false

 s.erase(1); //删除元素“1”
 if (s.count(1)) printf("Yes\n"); else printf("No\n");
 
 for (int i=0;i<6;i++)
 	s.insert(i);

 set<int>::iterator it; //迭代器
 
 for (it=s.begin();it!=s.end();it++) //依次遍历
 	printf("%d\n",*it);
 return 0;
}

尽管方便(实现红黑树?),但SET时间效率并不高,能别用还是别用吧……


Map:映射

map是一种“关联数组”,你可以把它看成两个数组之间的映射。

但这货实在用处不大 ( ̄o ̄) ,不仅速度慢的惊世骇俗,功能基本上数组也能实现……

具体用法和数组和SET差不多,不写了(蛤蛤)。


Stack:栈

栈就是一种简单数据结构,你可以把它想象成一挪碟子:先放的碟子后拿走,即“先进后出”。

#include <cstdio>
#include <stack> //头文件
#include <cstdlib>

using namespace std;

stack<int> s; //定义

int main()
{
 if (s.empty()) printf("The stack is empty!\n"); //判断是否为空

 s.push(1); //元素“1”入栈
 printf("%d\n",s.top()); //取栈顶元素(不弹出)
 s.pop(); //栈顶元素出栈

 return 0; 
}

速度还行 - (⊙ˍ⊙)


Queue:队列

队列类似于排队的顺序:先来排队的人先走人,即“先进先出”。

#include <cstdio>
#include <queue> //头文件
#include <cstdlib>

using namespace std;

queue<int> q; //定义

int main()
{
 if (q.empty()) printf("The queue is empty!\n"); //判断是否为空

 q.push(1); //元素“1”入栈队
 printf("%d\n",q.front()); //取队尾元素(不弹出)
 q.pop(); //队尾元素出队

 return 0; 
}

是不是和栈的操作很类似?


Deque:双端队列

双端队列是STL中queue的“高级版”,一般队列只支持从一个方向“先进后出”,而双端队列deque支持从两个方向插入和弹出元素

#include <queue>
#include <cstdio>
#include <cstdlib>

using namespace std;

int main()
{
  deque<int> dq; //定义队列
   
  dq.clear(); //清空队列

  dq.push_back(1); //从尾部插入元素“1”
  dq.push_front(4); //从头部插入元素“4”
  
  printf("%d\n",dq[0]); //使用数组方式读取
  printf("%d\n",dq.size()); //返回队列元素个数
  printf("%d\n",dq.front()); //返回队列首部元素
  printf("%d\n",dq.back()); //返回队列尾部元素

  deque<int>::iterator it=dq.begin(); //定义迭代器
  
  for (it=dq.begin();it!=dq.end();it++) //依次遍历输出
    printf("%d\n",*it);

  dq.pop_back(); //弹出队尾元素
  printf("%d\n",dq.back());
  dq.pop_front(); //弹出队首元素

  if (dq.empty()) printf("The queue is empty! %d \n",dq.size()); //检查队列是否为空
  
  system("pause");
  return 0;
}

deque在首尾插入等操作方面是几乎不耗时的,但初始化就不一定了:据说有人测过n=10^6时要0.3秒? 还有没介绍的中间插入和删除,如果你用了,那么卡个评测机几分钟应该是没问题的……(原理就像vector,中间插入需要移动大量元素)

所以,还是那句话:能不用STL尽量别用,还是老老实实开数组或者用vector吧……


Priority_queue:优先队列

优先队列也是队列的一种,但它不是按进队顺序决定出队顺序,而是按一个用户自定义的“优先度”:在优先队列中:“优先度”大的元素先出队。

#include <cstdio>
#include <queue>
#include <cstdlib>

using namespace std;

struct cmp{ //仿函数(不能直接写)
 bool operator() (const int a,const int b) {
  return a%10 < b%10;
 }
};

priority_queue<int,vector<int>,cmp> q; //注意它的定义:对于自定义的“优先度”,必须用这种方式定义

int main()
{
 if (q.empty()) printf("Empty!\n"); //判断是否为空
 
 for (int i=1;i<20;i++)
   q.push(i); //入队
 for (int i=1;i<20;i++)
 {
   printf("%d\n",q.top()); //队尾元素
   q.pop(); //出队
 }
 return 0;
}

当两个元素优先度相同时,先入队的元素先出队。

当然,优先队列是拿堆写的。具体速度也不慢,但手写堆还是要快那么“一点点的”……


Multiset:多重集

与集合同理,只是允许多个相同值存在。

{
 S.insert(x); //插入一个元素x
 S.erase(x); //移除S中所有的x
 S.erase(S.find(x)); //移除S中的一个x
}

Bitset:压位集合

可以自定义长度的整数集合,所有操作复杂度为\(O(n/32)\)

#include <cstdio>
#include <bitset>

const int maxn=100000+10;

bitset<maxn> S; //定义[0,maxn)的bitset

int main()
{
 S[0]=1,S[1]=1; //直接赋值
 if (S.any()) printf("YES\n"); //如果有二进制位为1,返回true,否则返回false
 int k=S.count(); //二进制位为1的个数
 
 S.flip(); //所有二进制位取反
 S.set(); //所有二进制位设为1
 S.reset(); //所有二进制位设为0

 /*
 bitset还可以直接使用整数的二进制运算,如&,^,|,<<,>>
 */

 return 0;
}

posted @ 2016-01-21 15:34  Krew  阅读(220)  评论(0编辑  收藏  举报