STL线段树代码库文档格式.docx
《STL线段树代码库文档格式.docx》由会员分享,可在线阅读,更多相关《STL线段树代码库文档格式.docx(30页珍藏版)》请在冰豆网上搜索。
\t
endl;
}
while
(next_permutation(myVec.begin(),
myVec.end()));
ACM
/
ICPC
竞赛之STL
简介
一、关于STL
STL(Standard
Template
Library,标准模板库)是C++
语言标准中的重
要组成部分。
以模板类和模板函数的形式为程序员提供了各种数据结构和
算法的精巧实现,程序员如果能够充分地利用STL
,可以在代码空间、执行时
间和编码效率上获得极大的好处。
大致可以分为三大类:
算法(algorithm)
、容器
(container)
、迭代器
(iterator)。
容器是一些模板类,提供了多种组织数据的常用方法,例如vector(向量,
类似于数组)
、list(
列表,类似于链表)
、deque(双向队列)
、set(集合)
、
map(映象)
、stack(
栈)
、queue(
队列)
、priority_queue(优先队列)
等,
通过模板的参数我们可以指定容器中的元素类型。
算法是一些模板函数,提供了相当多的有用算法和操作,从简单如
for_each
(遍历)到复杂如stable_sort
(稳定排序)。
迭代器是对C
中的指针的一般化,用来将算法和容器联系起来。
几乎所有
的STL
算法都是通过迭代器来存取元素序列进行工作的,而STL
中的每一个
容器也都定义了其本身所专有的迭代器,用以存取容器中的元素。
有趣的是,
普通的指针也可以像迭代器一样工作。
熟悉了STL
后,你会发现,很多功能只需要用短短的几行就可以实现了。
通过
,我们可以构造出优雅而且高效的代码,甚至比你自己手工实现的代码效
果还要好。
的另外一个特点是,它是以源码方式免费提供的,程序员不仅可以自由地
使用这些代码,也可以学习其源码,甚至按照自己的需要去修改它。
下面是用STL
写的题Ugly
Numbers的代码:
iostream>
queue>
typedef
pair<
unsigned
long,
node_type;
main()
long
result[1500];
priority_queue
node_type,
node_type>
greater<
>
Q;
Q.push(
make_pair(1,
2)
);
(int
0;
1500;
i++)
node_type
node
Q.top();
Q.pop();
switch(node.second)
case
2:
make_pair(node.first
*
2,
3:
3,
3)
5:
5,
5)
result[i]
node.first;
n;
cin
(n
0)
result[n-1]
return
在ACM
竞赛中,熟练掌握和运用STL
对快速编写实现代码会有极大的帮助。
二、使用STL
在C++
标准中,STL
被组织为以下的一组头文件(注意,是没有.h后缀的!
):
algorithm
deque
functional
iterator
list
map
memory
numeric
queue
set
stack
utility
vector
当我们需要使用STL
的某个功能时,需要嵌入相应的头文件。
但要注意的是,
是被定义在std
命名空间中的。
如下例所示:
stack>
std:
:
stack<
s;
s.push(0);
...
如果希望在程序中直接引用STL
,也可以在嵌入头文件后,用using
语句将std
命名空间导入。
1;
是C++
语言机制运用的一个典范,通过学习STL
可以更深刻地理解C++
语言的思想和方法。
在本系列的文章中不打算对STL
做深入的剖析,而只是想
介绍一些STL
的基本应用。
有兴趣的同学,建议可以在有了一些STL
的使用经验后,认真阅读一下《C++
》这本书(电力出版社有该书的中文版)。
竞赛之STL--pair
的<
utility>
头文件中描述了一个看上去非常简单的模板类pair,用来
表示一个二元组或元素对,并提供了按照字典序对元素对进行大小比较的比较
运算符模板函数。
例如,想要定义一个对象表示一个平面坐标点,则可以:
吉林大学ACM
Group
39
double,
double>
p1;
p1.first
p1.second;
pair
模板类需要两个参数:
首元素的数据类型和尾元素的数据类型。
模
板类对象有两个成员:
first和second
,分别表示首元素和尾元素。
在<
中已经定义了pair
上的六个比较运算符:
==
!
,
其规则是先比较first,first相等时再比较second
,这符合大多数应用的
逻辑。
当然,也可以通过重载这几个运算符来重新指定自己的比较逻辑。
除了直接定义一个pair
对象外,如果需要即时生成一个pair
对象,也可以
调用在<
中定义的一个模板函数:
make_pair。
make_pair
需要两
个参数,分别为元素对的首元素和尾元素。
在题1067--Ugly
Numbers
中,就可以用pair
来表示推演树上的结点,用
first表示结点的值,用second
表示结点是由父结点乘以哪一个因子得到的。
看上去是很简单的一个头文件,但是<
的设计中却浓缩
反映了STL
设计的基本思想。
有意深入了解和研究STL
的同学,仔细阅读和
体会这个简单的头文件,不失为一种入门的途径。
竞赛之STL--vector
在STL
vector>
头文件中定义了vector
(向量容器模板类),vector
容器以连续数组的方式存储元素序列,可以将vector
看作是以顺序结构实现
的线性表。
当我们在程序中需要使用动态数组时,vector
将会是理想的选择,
可以在使用过程中动态地增长存储空间。
模板类需要两个模板参数,第一个参数是存储元素的数据类型,第二
个参数是存储分配器的类型,其中第二个参数是可选的,如果不给出第二个参
数,将使用默认的分配器。
下面给出几个常用的定义vector
向量对象的方法示例:
定义一个空的vector
对象,存储的是int
类型的元素。
s(n);
定义一个含有n
个int
元素的vector
对象。
s(first,
last);
定义一个vector
对象,并从由迭代器first和last
定义的序列[first,
last)中复制初值。
的基本操作有:
s[i]
直接以下标方式访问容器中的元素。
s.front()
返回首元素。
s.back()
返回尾元素。
s.push_back(x)
向表尾插入元素x
。
s.size()
返回表长。
s.empty()
当表空时,返回真,否则返回假。
s.pop_back()
删除表尾元素。
s.begin()
返回指向首元素的随机存取迭代器。
s.end()
返回指向尾元素的下一个位置的随机存取迭代器。
s.insert(it,
x)
向迭代器it指向的元素前插入新元素val
n,
向迭代器it指向的元素前插入n
个x
first,
last)
将由迭代器first和last
所指定的序列[first,
插入到迭代器it
指向的元素前面。
s.erase(it)
删除由迭代器it所指向的元素。
s.erase(first,
删除由迭代器first和last
s.reserve(n)
预分配缓冲空间,使存储空间至少可容纳n
个元素。
s.resize(n)
改变序列的长度,超出的元素将会被删除,如果序列需要扩展(原空间小于n
),
元素默认值将填满扩展出的空间。
s.resize(n,
val)
将用val
填满扩展出的空间。
s.clear()
删除容器中的所有的元素。
s.swap(v)
将s
与另一个vector
对象v
进行交换。
s.assign(first,
将序列替换成由迭代器first和last
[first,
不能是原序列中的一部分。
要注意的是,resize
操作和clear操作都是对表的有效元素进行的操作,但
并不一定会改变缓冲空间的大小。
另外,vector
还有其他一些操作如反转、取反等,不再一下列举。
上还定义了序列之间的比较操作运算符(>
=,
==,
=)
可以按照字典序比较两个序列。
还是来看一些示例代码。
输入个数不定的一组整数,再将这组整数按倒序输出,
如下所示:
L;
x;
(cin>
L.push_back(x);
i=L.size()-1;
i>
=0;
i--)
L[i]
竞赛之STL--iterator
iterator(迭代器)
是用于访问容器中元素的指示器,从这个意义上说,
相当于数据结构中所说的“
遍历指针”
,也可以把
看作是一种泛化的指针。
中关于iterator(迭代器)
的实现是相当复杂的,这里我们暂时不去详细
讨论关于iterator(迭代器)
的实现和使用,而只对iterator(迭代器)
做一
点简单的介绍。
简单地说,STL
中有以下几类iterator(迭代器)
:
输入iterator(迭代器)
,在容器的连续区间内向前移动,可以读取容器内任
意值;
输出iterator(迭代器)
,把值写进它所指向的容器中;
前向iterator(迭代器)
,读取队列中的值,并可以向前移动到下一位置
(++p,
p++);
双向iterator(迭代器)
,读取队列中的值,并可以向前向后遍历容器;
随机访问iterator(迭代器),
可以直接以下标方式对容器进行访问,
的iterator(迭代器)
就是这种iterator(迭代器)
;
流iterator(迭代器)
,可以直接输出、输入流中的值;
每种STL
容器都有自己的iterator(迭代器)
子类,下面先来看一段简单的示
例代码:
10;
s.push_back(i);
(vector<
it
s.begin();
s.end();
it++)
*it
的begin()和end()方法都会返回一个vector:
对象,
分别指向vector
的首元素位置和尾元素的下一个位置(我们可以称之为结束
标志位置)。
对一个iterator(迭代器)
对象的使用与一个指针变量的使用极为相似,或者
可以这样说,指针就是一个非常标准的iterator(迭代器)
再来看一段稍微特别一点的代码:
40
s.push_back
(1);
s.push_back
(2);
s.push_back(3);
copy(s.begin(),
s.end(),
ostream_iterator<
(cout,
));
这段代码中的copy
就是STL
中定义的一个模板函数,copy(s.begin(),
的意思是将由
s.begin()至s.end()(
不含s.end())
所指定的序列复制到标准输出流
中,用"
作为每个元素的间隔。
也就是说,这句话的作用其实就是将表
中的所有内容依次输出。
是STL
容器和算法之间的“
胶合剂”
,几乎所有的STL
算
法都是通过容器的iterator(迭代器)
来访问容器内容的。
只有通过有效地运
用iterator(迭代器)
,才能够有效地运用STL
强大的算法功能。
竞赛之STL--string
字符串是程序中经常要表达和处理的数据,我们通常是采用字符数组或字符指
针来表示字符串。
为我们提供了另一种使用起来更为便捷的字符串的表达
方式:
string
类的定义在头文件<
string>
中。
类其实可以看作是一个字符的vector
,vector
上的各种操作都可以
适用于string
,另外,string
类对象还支持字符串的拼合、转换等操作。
下面先来看一个简单的例子:
s
Hello!
name;
+=
'
再以题1064--Parencoding为例,看一段用string
作为容器,实现由P
代码还原括号字符串的示例代码片段:
m;
P
编码的长度
str;
用来存放还原出来的括号字符串
leftpa
记录已出现的左括号的总数
j
j++)
p;
k
p
-
leftpa;
k++)
str
('
)'
竞赛之STL--stack
stack(
和queue(
也是在程序设计中经常会用到的数据容器,STL
为我们提供了方便的stack(
的queue(
的实现。
准确地说,STL
中的stack和queue不同于vector
、list
等容器,而是对
这些容器的重新包装。
这里我们不去深入讨论
的stack和queue的实现
细节,而是来了解一些他们的基本使用。
1
、stack
stack模板类的定义在<
头文件中。
stack模板类需要两个模板参数,一个是元素类型,一个容器类型,但只有元
素类型是必要的,在不指定容器类型时,默认的容器类型为deque。
定义stack对象的示例代码如下:
s1;
s2;
stack的基本操作有:
入栈,如例:
s.push(x);
出栈,如例:
s.pop();
注意,出栈操作只是删除栈顶元素,并不返回该元素。
访问栈顶,如例:
s.top()
判断栈空,如例:
s.empty(),当栈空时,返回true。
访问栈中的元素个数,如例:
下面是用string
和stack写的解题1064--Parencoding的程序。
(i