ACM算法题以及答案.docx

上传人:b****5 文档编号:8006611 上传时间:2023-01-27 格式:DOCX 页数:38 大小:524.19KB
下载 相关 举报
ACM算法题以及答案.docx_第1页
第1页 / 共38页
ACM算法题以及答案.docx_第2页
第2页 / 共38页
ACM算法题以及答案.docx_第3页
第3页 / 共38页
ACM算法题以及答案.docx_第4页
第4页 / 共38页
ACM算法题以及答案.docx_第5页
第5页 / 共38页
点击查看更多>>
下载资源
资源描述

ACM算法题以及答案.docx

《ACM算法题以及答案.docx》由会员分享,可在线阅读,更多相关《ACM算法题以及答案.docx(38页珍藏版)》请在冰豆网上搜索。

ACM算法题以及答案.docx

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;    vectorv;

或者连在一起,使用全名:

std:

:

vectorv;

建议使用全局的命名域方式:

usingnamespacestd;

1.vector的声明

  vectorc;  创建一个空的vector

  vectorc1(c2);创建一个vectorc1,并用c2去初始化c1

  vectorc(n);创建一个含有n个ElemType类型数据的vector;

  vectorc(n,elem);创建一个含有n个ElemType类型数据的vector,并全部初始化为elem;

  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:

:

dequec;

因为类型deque是一个定义在namespacestd内的template。

构造函数:

dequec;//产生一个空的deque,其中没有任何元素

dequec1(c2);//产生另一个同型deque的副本(所有元素都被拷贝)

dequec(n);//产生一个大小为n的deque

dequec(n,elem);//产生一个大小为n的deque,

//每个元素值都是elem。

dequerc(begin,end);//产生一个deque,以区间[begin;end]

//做为元素初值

析构函数:

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对象的示例代码如下:

queueq1;

queueq2;

queue的基本操作有:

入队,如例:

q.push(x);将x接到队列的末端。

出队,如例:

q.pop();弹出队列的第一个元素,注意,并不会返回被弹出元素的值。

访问队首元素,如例:

q.front(),即最早被压入队列的元素。

访问队尾元素,如例:

q.back(),即最后被压入队列的元素。

判断队列空,如例:

q.empty(),当队列空时,返回true。

访问队列中的元素个数,如例:

q.size()

priority_queue的使用

头文件中,还定义了另一个非常有用的模板类priority_queue(优先队列)。

优先队

列与队列的差别在于优先队列不是按照入队的顺序出队,而是按照队列中元素的优先权顺序

出队(默认为大者优先,也可以通过指定算子来指定自己的优先顺序)。

priority_queue模板类有三个模板参数,第一个是元素类型,第二个容器类型,第三个是比

较算子。

其中后两个都可以省略,默认容器为vector,默认算子为less,即小的往前排,大

的往后排(出队时序列尾的元素出队)。

定义priority_queue对象的示例代码如下:

priority_queueq1;

priority_queue>q2;//注意在两个尖括号之间一定要留空格。

priority_queue,greater>q3;//定义小的先出队

priority_queue的基本操作与queue相同。

初学者在使用priority_queue时,最困难的可能就是如何定义比较算子了。

如果是基本数据类型,或已定义了比较运算符的类,可以直接用STL的less算子和greater

算子——默认为使用less算子,即小的往前排,大的先出队。

如果要定义自己的比较算子,方法有多种,这里介绍其中的一种:

重载比较运算符。

优先队

列试图将两个元素x和y代入比较运算符(对less算子,调用xy),

若结果为真,则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_queueq;

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> col1;  

此时,排序准则就是型别的一部分。

型别系统确保只有排序准则相同的容器才能被合并。

程序实例:

[cpp] viewplaincopyprint?

1.#include   

2.#include   

3.using namespace std;  

4.  

5.int main()  

6.{  

7.    set s1;  

8.    set > s2;  

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 > IntSet;  

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_order(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 insert(const value_type& elem);   

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函数,如果插入失败,就只返回重复元素的位置!

但是,所有拥有位置提示参数的插入函数的返回值型别是相同的。

这样就确保了至少有了一个通用型的插入函数,在各种容器中有共通接口。

注意:

还有一个返回

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 外语学习 > 日语学习

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1