模板:C++语言相关

运算符优先级

算法

a为容器时直接传迭代器;a为数组,那么beg变成a,end变成a+m,其中m为a的大小(即传地址)。

//用排序sort、去重unique、二分查找lower_bound实现离散化
sort(beg,end);
int n=unique(beg,end)-beg;//离散化后元素个数,vector可直接resize
int k=lower_bound(beg,beg+n,w)-beg;//k为经排序后原来的元素w离散化后对应的值(从0开始)

//以下算法,用于求给定区间的后一\前一字典序排列,不存在返回0,存在返回1
next_permutation(beg,end);
prev_permutation(beg,end);

nth_element(beg,beg+n,end);//将第n大的元素放在第n位,并且比其小的元素都在它前面,比它大的元素都在后面,线性,但不保证有序
max_element(beg,end);//最大值地址
min_element(beg,end);//最小值地址

copy(beg,end,beg2);//指定区间拷贝到beg2开始的地址,需要保证空间足够
fill(beg,end,val);//区间赋值,比memset安全
reverse(beg,end);//区间翻转

容器/数据结构

struct tm,time_t,mktime

C++没有用于处理时间日期的数据结构,而直接沿用C的。

pair

pair是一个用于保存两个元素的“快速而随意”的结构,原生重载了字典序的比较函数。
可以用pair嵌套保存多个元素,C++11中还可用tuple直接保存多个元素,操作类似。

迭代器

c++为顺序容器和关联容器定义了迭代器(iterator),一种可以遍历元素的数据类型。迭代器比下标更通用,因为所有的标准库的容器都支持迭代器,但不一定支持下标操作(例如顺序容器list和关联容器set)。
顺序容器和关联容器容器都定义了begin和end函数用于返回迭代器,如果容器不空,则begin返回的迭代器指向容器内的第一个元素;否则与end相等。因此,我们可以通过反复递增begin到达end。换言之,begin和end迭代器构成这样的左闭合区间[begin,end)。
我们可以像下面这样方便的使用迭代器。
注意:改变容器大小的操作,例如push_back、erase等都可能使之前保存的迭代器失效,需要重新生成。

string str("ull");
set<char> s(str.begin(),str.end());//s中有'l'和'u'(set中相同元素仅保存一个,并按从小到大的顺序保存)
for(string::iterator i=str.begin(); i!=str.end(); ++i)
    cout<<*i;//输出"ull",这里循环里的string和str改成set和s后输出"lu"(set值相同元素只保存一个并按顺序存储)

顺序容器

主要介绍vector、deque、list。
vector将数据保存在连续的空间中,并预分配少量空间。因此,通过下标访问vector中的元素很快,但是要在中间或头部插入元素就很慢;在末尾加入元素时,会判断预分配的空间是否足够,若不足够则要重新分配空间。一般用vector模拟栈、大小可变的数组、邻接表等。注意,用vector<int>代替vector<bool>否则影响性能。用于实现栈。
deque可以理解为能够向前插入元素的vector,但是常数比vector大很多,一般用在要向前部插入元素的场合。用于实现(双端)队列。
list为双向链表,要通过迭代器访问其中的元素;在任意位置插入元素都很快。不借助迭代器无法访问list首尾位置之外的元素。向前部插元素速度比deque慢。
stl中的stack、queue相当于vector/deque的阉割版(不能访问中间元素),不做介绍。

//C是容器类型名,如vector
//T是元素类型,如int、string或者容器等等一切可以赋值的类型
//T为模板类型时,老版本的c++需要再打一个空格例如list<list<int> >以区分>>运算符
C<T> c;//创建一个空容器c
C<T> c(n,t);//创建含n个值为t的元素的容器c,比memset方便,t是类型T或是可以转成T的类型,但不能是静态常量(static const)
C<T> c(beg,end);//用迭代器beg和end确定的区间初始化cc

c.clear();//将c清空
c.assign(args);//args等同于以上初始化的参数,可以将c重新初始化
c.resize(n,t);//改变c的大小,若原来c大于n,那么尾部元素被删除;否则在尾部插入n-c.size()个值为t的元素(只改变容器大小快于assign)

c.size();//c的大小,运行很快,常数级
c.empty();//c是否为空

c[pos];//c中下标为pos的元素,list不支持

c.begin();//c的首迭代器,常数级
c.end();//c的尾迭代器,指向c最后一个元素的下一个位置,常数级

c.front();//c的首元素,比c[0]更加易懂通用
c.back();//c的尾元素,比c[c.size()-1]更加易懂通用

c.push_back(t);//把t放到c尾部
c.pop_back(t);//把c尾部元素删除,若c为空则出错
c.push_front(t);//把t放到c头部,vector很慢
c.pop_front(t);//把c头部元素删除,vector很慢,若c为空则出错

c.insert(p,n,t);//在迭代器p指向的位置插入n个值t,原有元素后移;vector、deque很慢
c.insert(p,b,e);//在迭代器p指向的位置插入元素区间[b,e),原有元素后移;[b,e)不能指向c;vector、deque很慢

p=c.erase(p);//删除迭代器p指向的元素,并返回被删元素后面一个元素的迭代器;若p为end,则返回值也为end;vector、deque很慢
p=c.erase(b,e);//删除[b,e)内元素,其余同上

string

string也属于顺序容器,用法(以及后台的实现)与vector<char>相当。string还附带其他操作:

string s1("c_stri");//用c_string初始化
string s2(s1,pos,n);//用s1从pos位开始的n个初始化s2,n省略时到末尾

s1.substr(pos,n);//s1从pos位开始的n个字符构成的子串,n省略时到末尾

//以下均为查找函数均为O(N*N)的暴力查找而非匹配算法,其中args均为s2,pos,代表从pos开始查找s2,s2亦可为单个字符,pos默认0;不存在返回一个值s.npos
s.find(args);//第一个args
s.rfind(args);//最后一个args,即反向查找
s.find_first_of(args);//s中args任意一个字符第一个出现的位置
s.find_last_of(args);//最后一个
s.find_first_not_of(args);//s中非args中任意一个字符第一个出现的位置
s.find_last_not_of(args);//最后一个

s1+s2;//返回s1尾部缀上s2的结果
s1+=s2;//s1=s1+s2

< > <= >= == !=//比较字典序

关联容器

关联容器有四种:set、multiset、map、multimap,内部实现是二叉查找树的红黑树,可以按O(logN)的速度插入\查找元素;内部元素按照字典序从小到大排列,可以用迭代器遍历,迭代器单次移动的速度是O(logN)。
set可以用于高效判断给定元素是否在一个集合中,而multiset则允许重复元素出现,用于判定给定元素的出现次数。
map和multimap可以理解成对应set的二元pair版本,其中map还提供了[]运算符,可以提供类似于数组的索引操作,而下标可以不是整数,很多情况下可以用这个来避开离散化操作。map可以嵌套从而实现接近多维数组的效果。
可以根据multiset和multimap从小到大遍历值的特性可以用来实现优先队列。
stl中还有个用堆排序实现的优先队列priority_queue,速度比multiset快,这里略去。

//初始化,其中T、T1都要是支持<运算符的类型
set<T> s,s1(beg,end);
multiset<T> ms,ms1(beg,end);
map<T1,T2> m;
multimap<T1,T2> mm;

//自定义排序的初始化,以set为例,传一个比较类进去
strcut Cmp
{
    bool operater()(const T &t1,const T &t2)
    {
        return t1>t2;
    }
};//这个Cmp其实就是greater<T>
set<T,Cmp> s2;

_s.insert(t);//s或ms中插一个t
_m.insert(make_pair(t1,t2));//m和mm插入需要插入一个pair

p=c.begin();//获得c的首迭代器,指向c最小的元素,效率O(logN);insert操作后失效,需要重新获得
p=c.end();//c的尾迭代器,指向c最大的元素后一位,效率O(logN);insert操作后失效,需要重新获得
//对于map和multimap的迭代器,解引用之后是一个pair

++p;--p;//移动迭代器,效率O(logN),移动到边界后不再移动

c.erase(t);//删除值为t的所有元素,map类的t为pair,返回实际删除元素的数量
q=c.erase(p);//删除迭代器p指向的元素,返回后一个位置的迭代器
q=c.erase(beg,end);//返回[beg,end)返回end

m[t1];//m中下标为t1的索引,若不存在则会执行T2的默认初始化,可能会插入新元素所以m不能为const;否则应使用find代替;mm不支持

c.count(t);//返回c中元素t的数量,不存在为0,非multi容器最多为1
c.find(t);//返回c中第一个值为t的迭代器,不存在返回c.end();
c.lower_bound(k);//指向第一个不小于k元素的迭代器,不存在返回c.end()
c.upper_bound(k);//指向第一个大于k元素的迭代器,不存在返回c.end()
c.equal_range(k);//返回一个迭代器pair表示值为k的元素的范围,不存在均为c.end()
//map和multiset中参数t均表示第一关键字

猜你喜欢

转载自blog.csdn.net/w_weilan/article/details/78846018