ACM算法题以及答案.docx
- 文档编号:8765338
- 上传时间:2023-02-01
- 格式:DOCX
- 页数:38
- 大小:524.15KB
ACM算法题以及答案.docx
《ACM算法题以及答案.docx》由会员分享,可在线阅读,更多相关《ACM算法题以及答案.docx(38页珍藏版)》请在冰豆网上搜索。
ACM算法题以及答案
ACM算法题使用C++实现
在做这些题目之前必须了解vector(数组),list(链表)、deque(双端队列)、queue(队列),priority_queue(优先队列)Stack(栈)、set(集合)、map(键值对),mutilset、mutilmap。
stack堆栈,没有迭代器,支持push()方法。
后进先出,top()返回最顶端的元素,pop()剔除最顶元素
deque双端队列,支持迭代器,有push_back()方法,跟vector差不多,比vector多了个pop_front,push_front方法
queue队列,先进先出,不支持迭代器,有push()方法,pop()剔除第一个元素,front()返回第一个元素
vector使用
vector是C++标准模板库中的部分内容,它是一个多功能的,能够操作多种数据结构和算法的模板类和函数库。
vector之所以被认为是一个容器,是因为它能够像容器一样存放各种类型的对象,简单地说vector是一个能够存放任意类型的动态数组,能够增加和压缩数据。
为了可以使用vector,必须在你的头文件中包含下面的代码:
#include
vector属于std命名域的,因此需要通过命名限定,如下完成你的代码:
usingstd:
:
vector; vector
或者连在一起,使用全名:
std:
:
vector
建议使用全局的命名域方式:
usingnamespacestd;
1.vector的声明
vector
vector
vector
vector
c.~vector
2.vector容器中常用的函数。
(c为一个容器对象)
c.push_back(elem); 在容器最后位置添加一个元素elem
c.pop_back(); 删除容器最后位置处的元素
c.at(index); 返回指定index位置处的元素
c.begin(); 返回指向容器最开始位置数据的指针
c.end(); 返回指向容器最后一个数据单元的指针+1
c.front(); 返回容器最开始单元数据的引用
c.back(); 返回容器最后一个数据的引用
c.max_size(); 返回容器的最大容量
c.size(); 返回当前容器中实际存放元素的个数
c.capacity(); 同c.size()
c.resize(); 重新设置vector的容量
c.reserve(); 同c.resize()
c.erase(p); 删除指针p指向位置的数据,返回下指向下一个数据位置的指针(迭代器)
c.erase(begin,end) 删除begin,end区间的数据,返回指向下一个数据位置的指针(迭代器)
c.clear(); 清除所有数据
c.rbegin(); 将vector反转后的开始指针返回(其实就是原来的end-1)
c.rend(); 将vector反转后的结束指针返回(其实就是原来的begin-1)
c.empty(); 判断容器是否为空,若为空返回true,否则返回false
c1.swap(c2); 交换两个容器中的数据
c.insert(p,elem); 在指针p指向的位置插入数据elem,返回指向elem位置的指针
c.insert(p,n,elem); 在位置p插入n个elem数据,无返回值
c.insert(p,begin,end)在位置p插入在区间[begin,end)的数据,无返回值
3.vector中的操作
operator[]如:
c.[i];
同at()函数的作用相同,即取容器中的数据。
list使用:
STL 中的list 就是一 双向链表,可高效地进行插入删除元素。
list不支持随机访问。
所以没有at(pos)和operator[]。
list 对象list1,list2 分别有元素list1(1,2,3),list2(4,5,6) 。
list< int>:
:
iteratorit;
list成员
说明
constructor
构造函数
destructor
析构函数
operator=
赋值重载运算符
assign
分配值
front
返回第一个元素的引用
back
返回最后一元素的引用
begin
返回第一个元素的指针(iterator)
end
返回最后一个元素的下一位置的指针
rbegin
返回链表最后一元素的后向指针(reverse_iteratororconst)
rend
返回链表第一元素的下一位置的后向指针
push_back
增加一元素到链表尾
push_front
增加一元素到链表头
pop_back
pop_back()删除链表尾的一个元素
pop_front
删除链表头的一元素
clear
删除所有元素
erase
删除一个元素或一个区域的元素(两个重载)
remove
删除链表中匹配值的元素(匹配元素全部删除)
remove_if
删除条件满足的元素(遍历一次链表),参数为自定义的回调函数
empty
判断是否链表为空
max_size
返回链表最大可能长度
size
返回链表中元素个数
resize
重新定义链表长度(两重载函数)
reverse
反转链表
sort
对链表排序,默认升序
merge
合并两个有序链表并使之有序
splice
对两个链表进行结合(三个重载函数) 结合后第二个链表清空
insert
在指定位置插入一个或多个元素(三个重载函数)
swap
交换两个链表(两个重载)
unique
删除相邻重复元素
Deque双端队列使用:
容器deque和vector非常相似,操作函数基本一致。
它采用动态数组来管理元素,提供随机存取,可以在头尾两端进行快速安插和删除元素操作。
特别要注意,除了头尾两端,在任何地方安插与删除元素,都将导致指向deque元素的任何pointersreferencesiterators失效。
包括的头文件为:
#include
usingnamespacestd;
声明一个deque时,一般需要前缀std:
:
,如std:
:
deque
因为类型deque是一个定义在namespacestd内的template。
构造函数:
deque
deque
deque
deque
//每个元素值都是elem。
dequer
//做为元素初值
析构函数:
c.~deque
非变动性操作
c.size();//返回当前的元素数量
c.empty();//判断大小是否为零。
等同于c.size()==0,但可能更快
c.max_size();//可容纳元素的最大数量
c.at(idx);//返回索引为idx所标示的元素。
如果idx越界,抛出out_of_range
c[idx];//返回索引idx所标示的元素。
不进行范围检查
c.front();//返回第一个元素,不检查元素是否存在
c.back();//返回最后一个元素
c.begin();//返回一个随机迭代器,指向第一个元素
c.end();//返回一个随机迭代器,指向最后元素的下一位置
变动性操作:
c1=c2;//将c2的所有元素赋值给c1;
c.assign(n,elem);//将n个elem副本赋值给c
c.assing(beg,end);//将区间[beg;end]中的元素赋值给c;
c.push_back(elem);//在尾部添加元素elem
c.pop_back();//移除最后一个元素(但不回传)
c.push_front();//在头部添加元素elem
c.pop_front();//移除头部一个元素(但不回传)
c.erase(pos);//移除pos位置上的元素,返回一元素位置
//如c.erase(c.begin()+5)//移除第五个元素
c.insert(pos,elem);//在pos位置插入一个元素elem,并返回新元素的位置
c.insert(pos,n,elem);//在pos位置插入n个元素elem,无返回值
c.insert(pos,beg,end);
c.resize(num);//将容器大小改为num。
可更大或更小。
c.resize(num,elem);//将容器大小改为num,新增元素都为elem
c.clear();//移除所有元素,将容器清空
PS:
Deque和Vector是智能容器,删除或者增加元素时,其他位置与元素会进行相应的移动。
queue的使用
queue模板类的定义在
与stack模板类很相似,queue模板类也需要两个模板参数,一个是元素类型,一个容器类
型,元素类型是必要的,容器类型是可选的,默认为deque类型。
定义queue对象的示例代码如下:
queue
queue
queue的基本操作有:
入队,如例:
q.push(x);将x接到队列的末端。
出队,如例:
q.pop();弹出队列的第一个元素,注意,并不会返回被弹出元素的值。
访问队首元素,如例:
q.front(),即最早被压入队列的元素。
访问队尾元素,如例:
q.back(),即最后被压入队列的元素。
判断队列空,如例:
q.empty(),当队列空时,返回true。
访问队列中的元素个数,如例:
q.size()
priority_queue的使用
在
优先队
列与队列的差别在于优先队列不是按照入队的顺序出队,而是按照队列中元素的优先权顺序
出队(默认为大者优先,也可以通过指定算子来指定自己的优先顺序)。
priority_queue模板类有三个模板参数,第一个是元素类型,第二个容器类型,第三个是比
较算子。
其中后两个都可以省略,默认容器为vector,默认算子为less,即小的往前排,大
的往后排(出队时序列尾的元素出队)。
定义priority_queue对象的示例代码如下:
priority_queue
priority_queue
priority_queue
priority_queue的基本操作与queue相同。
初学者在使用priority_queue时,最困难的可能就是如何定义比较算子了。
如果是基本数据类型,或已定义了比较运算符的类,可以直接用STL的less算子和greater
算子——默认为使用less算子,即小的往前排,大的先出队。
如果要定义自己的比较算子,方法有多种,这里介绍其中的一种:
重载比较运算符。
优先队
列试图将两个元素x和y代入比较运算符(对less算子,调用x
若结果为真,则x排在y前面,y将先于x出队,反之,则将y排在x前面,x将先出队。
看下面这个简单的示例:
#include
#include
usingnamespacestd;
classT
{
public:
intx,y,z;
T(inta,intb,intc):
x(a),y(b),z(c)
{
}
};
booloperator<(constT&t1,constT&t2)
{
returnt1.z } main() { priority_queue q.push(T(4,4,3)); q.push(T(2,2,5)); q.push(T(1,5,4)); q.push(T(3,3,6)); while(! q.empty()) { Tt=q.top();q.pop(); cout< } return1; } 输出结果为(注意是按照z的顺序从大到小出队的): 336 225 154 443 Statck使用 statck栈中的数据是先进后出的(FirstInLastOut,FILO)。 栈只有一个出口,允许新增元素(只能在栈顶上增加)、移出元素(只能移出栈顶元素)、取得栈顶元素等操作。 set和multiset的功能 和所有关联式容器类似,通常使用平衡二叉树完成。 事实上,set和multiset通常以红黑树实作而成。 自动排序的优点是使得搜寻元素时具有良好的性能,具有对数时间复杂度。 但是造成的一个缺点就是: 不能直接改变元素值。 因为这样会打乱原有的顺序。 改变元素值的方法是: 先删除旧元素,再插入新元素。 存取元素只能通过迭代器,从迭代器的角度看,元素值是常数。 三、操作函数 构造函数和析构函数 set的形式可以是: 有两种方式可以定义排序准则: 1、以template参数定义: [cpp] viewplaincopyprint? 1.set 此时,排序准则就是型别的一部分。 型别系统确保只有排序准则相同的容器才能被合并。 程序实例: [cpp] viewplaincopyprint? 1.#include 2.#include 3.using namespace std; 4. 5.int main() 6.{ 7. set 8. set 9. 10. for (int i = 1;i < 6;++i) 11. { 12. s1.insert(i); 13. s2.insert(i); 14. } 15. if(s1 == s2) 16. cout << "c1 equals c2 ! " << endl; 17. else 18. cout << "c1 not equals c2 ! " << endl; 19.} 程序运行会报错。 但是如果把s1的排序准则也指定为greater 2、以构造函数参数定义。 这种情况下,同一个型别可以运用不同的排序准则,而排序准则的初始值或状态也可以不同。 如果执行期才获得排序准则,而且需要用到不同的排序准则,这种方式可以派上用场。 程序实例: [cpp] viewplaincopyprint? 1.#include 2.#include "print.hpp" 3.#include 4.using namespace std; 5. 6.template 7.class RuntimeCmp{ 8.public: 9. enum cmp_mode{normal,reverse}; 10.private: 11. cmp_mode mode; 12.public: 13. RuntimeCmp(cmp_mode m = normal): mode(m){} 14. 15. bool operator()(const T &t1,const T &t2) 16. { 17. return mode == normal ? t1 < t2 : t2 < t1; 18. } 19. 20. bool operator==(const RuntimeCmp &rc) 21. { 22. return mode == rc.mode; 23. } 24.}; 25. 26.typedef set 27. 28.void fill(IntSet& set); 29. 30.int main() 31.{ 32. IntSet set1; 33. fill(set1); 34. PRINT_ELEMENTS(set1,"set1: "); 35. 36. RuntimeCmp : reverse); 37. 38. IntSet set2(reverse_order); 39. fill(set2); 40. PRINT_ELEMENTS(set2,"set2: "); 41. 42. set1 = set2;//assignment: OK 43. set1.insert(3); 44. PRINT_ELEMENTS(set1,"set1: "); 45. 46. if(set1.value_comp() == set2.value_comp())//value_comp verdana, arial, helvetica, sans-serif; ">Returns the comparison object associated with the container 47. cout << "set1 and set2 have the same sorting criterion" << endl; 48. else 49. cout << "set1 and set2 have the different sorting criterion" << endl; 50.} 51. 52.void fill(IntSet &set) 53.{ 54. set.insert(4); 55. set.insert(7); 56. set.insert(5); 57. set.insert (1); 58. set.insert(6); 59. set.insert (2); 60. set.insert(5); 61.} 运行结果: 虽然set1和set2的而比较准则本身不同,但是型别相同,所以可以进行赋值操作。 非变动性操作 注意: 元素比较操作只能用于型别相同的容器。 特殊的搜寻函数 赋值 赋值操作两端的容器必须具有相同的型别,但是比较准则本身可以不同,但是其型别必须相同。 如果比较准则的不同,准则本身也会被赋值或交换。 迭代器相关函数 元素的插入和删除 注意: 插入函数的返回值不完全相同。 set提供的插入函数: [cpp] viewplaincopyprint? 1.pair 2.iterator insert(iterator pos_hint, const value_type& elem); multiset提供的插入函数: [cpp] viewplaincopyprint? 1.iterator insert(const value_type& elem); 2.iterator insert(iterator pos_hint, const value_type& elem); 返回值型别不同的原因是set不允许元素重复,而multiset允许。 当插入的元素在set中已经包含有同样值的元素时,插入就会失败。 所以set的返回值型别是由pair组织起来的两个值: 第一个元素返回新元素的位置,或返回现存的同值元素的位置。 第二个元素表示插入是否成功。 set的第二个insert函数,如果插入失败,就只返回重复元素的位置! 但是,所有拥有位置提示参数的插入函数的返回值型别是相同的。 这样就确保了至少有了一个通用型的插入函数,在各种容器中有共通接口。 注意: 还有一个返回值不同的情况是: 作用于序列式容器和关联式容器的erase()函数: 序列式容器的erase()函数: [cpp] viewplaincopyprint? 1.it
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- ACM 算法 以及 答案