1 / 21

习 题课 3

习 题课 3. 赵嘉明 . Topic. 了解仿函数( functor ) 讨论 bfs&dfs 网上作业习题. 何谓仿函数. 仿函数,顾名思义,就是具有函数的性质但是本身又不是函数的四不像(是一个 class ) In essential ,我们把在重载过 operator() 的类叫做仿函数。 For example : class FunctionObject { public: void operator()( int a,int b) {…………;} }.

fordon
Download Presentation

习 题课 3

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. 习题课 3 赵嘉明

  2. Topic • 了解仿函数(functor) • 讨论bfs&dfs • 网上作业习题

  3. 何谓仿函数 • 仿函数,顾名思义,就是具有函数的性质但是本身又不是函数的四不像(是一个class) • In essential,我们把在重载过operator()的类叫做仿函数。 For example: class FunctionObject { public: void operator()(inta,int b) {…………;} } In this way. 我们可以像使用普通函数一样使用这种类。 FunctionObjectfunctor; functor(a,b); 上述操作会自动调用重载过的operator()完成函数操作。

  4. 仿函数可以让程序变的简洁 Class average {private: intnum; int sum; public: average():num(0),sum(0) {} void operator()(intelem) { num++; sun+=elem;} double value() { return (double)(sum)/(double)(num);} }; in main….. 我们使用algorithm中的for_each()函数,它对区间内每一个元素执行相同的函数操作 vector<int> coll; initialize coll……. average result=for_each(coll.begin(),coll.end(),average()); cout<<average.value(); 我们可以把多个操作整合在一个仿函数中,让main函数一目了然,而且STL中提供了许多这样的借口,可以方便我们的使用,例: 此处通过调用average类的构造函数,产生了一个临时的average类对象。 Algorithm中的for_each()函数具有一个仿函数类型的返回值,该仿函数类型与第三个参数保持一致。

  5. C++STL中内置的仿函数 • 我们需要include <functional>来使用它们。 • plus minus multiplies divides modulus negate • greater less greater_equalless_equal • logical_andlogical_orlogical_not,

  6. 将仿函数作为set和map的排序准则 • Set默认为元素从小到大排序,map默认为按key值从小到大排序,但是我们可以根据应用需要用仿函数更改默认值,让它们变的更灵活。 • 在set的定义文件中,set有三个模板参数 Template<class T, class Compare = less<T>, class Allocator = allocator<T> > Class set { …….. } 其中第二个模板参数就是它的排序准则,具有less<T>的仿函数默认值,我们可以通过指定其它仿函数改变它. set<int ,greater<int> > intset; 当然你也可以自己撰写仿函数,但是为了被STL识别,我们需要加上一些接口。

  7. 将仿函数作为算法的逻辑判断式 • count_if (iterator iteratorfunctor); remove_if(iterator iteratorfunctor); find_if(iterator iteratorfunctor); 此处的仿函数具有bool型返回值,我们将对使functor执行结果为true的元素进行前面的操作。

  8. 仿函数接配器—化二元仿函数为一元 对于modulus<int>() ,应该有两个参数,该函数计算第一个参数对第二个参数的取模值,并返回。 可是如果我们想要将一个容器中偶数的值都删除,应该如何做? 显然我们应该把对二取模,结果等于0的值删除,但remove函数中,我们实际上只给仿函数传了一个值。 remove_if(iterator, iterator, modulus<int>() ) 为此我们定义了仿函数接配器,让它们嵌套在仿函数的外面,来解决参数不足的问题。 bind1st(functor,指定的第一参数) bind2nd(functor, 指定的第二参数) not1(functor) //对仿函数中计算的结果反相操作 即false->true true->false 因此我们可以对上述函数进行如下修改 remove_if(iterator , iterator , not1(bind2nd(modulus<int>(),2))); 将该区间内的一个元素传给仿函数作为参数,但却无法传递关键的取模数2

  9. Another example: 找到第一个小于5的数; vector<int>::iterator pos; pos=find_if(coll.begin(),coll.end(),bind2nd(less<int>(),5)); 或者 pos=find_if(coll.begin(),coll.end();bind1st(greater<int>(),5));

  10. BFS & DFS DFS:主要使用递归嵌套来实现 dfs(n) { if(达到满足的条件) 给出一个解决办法; if(满足剪枝的条件) 进行剪枝; 对数据进行修改,准备下次递归; dfs(n+1); 将更改的数据全部更改回来,恢复原始状态; }

  11. BFS:用一个队列实现 bfs() { queue.enqueue(初始结点); while(!queue.empty()) { 搜索与初始结点有直接关系的那些结点; if(满足条件) 给出解答办法,return if(该节点以前入队过) 不做处理 if(该节点没入队过) 让其入队 } } (第五章中树的层次遍历就是简化了的bfs)

  12. 1 4 3 3 2

  13. 3 2 3 1 3 2 3 3 2

  14. BFS 1.能较快找出问题的最优解。 2.需要大量内存空间记录已探索过的结点从而实现剪枝 • DFS 1.dfs通过递归调用,时间相对较慢,但不需要占用很多内存空间。 2.Dfs剪枝很重要(最优性和可行性),通过剪枝可以节省大量的时间。

  15. The Clocks 1.对每一种变换重复四次相当于没操作过。 2.结果和操作的顺序没有关系。 剪枝方案: 1.对每种变换进行次数进行记录,最多只重复三次。 2.从第一种变换开始试验,再试验接下去的变换,变换种类是单调不减的。 3.最优性剪枝。

  16. 用way[n]记录变化的编号 用use[n]记录每次变化执行的次数 dfs(int n) { if(变化次数大于已有的最优解) return; if(得到可行解) 将其设为最优 return; for(int i=way[n-1];i<=9;++i) { if(use[i]==3) continue; use[i]++; 进行变化 ; way[n]=i; dfs(n+1); use[i]--; 进行逆变化;} }

  17. ariprog 1.将所有的p^2+q^2全部计算出来,保存在num数组里。 并用一个exist数组记录它们是否存在(hash table) num数组大小不超过 250^2 exist数组不超过 2*250^2 2.将num数组进行排序(merge sort| quick sort) 3.search算法: Search() { for(int i=0;i<numsize;++i) { if(num[i]=num[i-1]) continue; for(int j=0;j<n;++j) {if(!exist[m[i]+difference*j]) break; if(j=n-1) 给出可行解; }} } 其中difference取值范围从1~num[maxnum-1]/(n-1)+1

More Related