转自:http://www.douban.com/group/topic/14551517/中科院大博士是如何进行文献检索和阅读的(好习惯受益终生) 一.如何进行文献检索 我是学自然科学的,平时确实需要不少外文文献,对于自然科学来讲英文文献检索首推Elsevier,Springer等。虽然这些数据库里面文献已经不算少了。但是有时还会碰到查不到的文献,而这些文献的数据库我们所在研究所或大学又没有买,怎么办?我基本通过以下向个途径来得到文献。 1.首先在Google 学术搜索里进行搜索,里面一般会搜出来你要找的文献,在Google学术搜索里通常情况会出现“每组几个”等字样,然后进入后,分别点击,里面的其中一个就有可能会下到全文,当然这只是碰运气,不是万能的,因为我常常碰到这种情况,所以也算是得到全文文献的一条途径吧。可以试一下。同时,大家有没有发现,从Google学术搜索中,还可以得到一些信息,Google学术搜索中会显示出你搜索文章的引用次数,不过这个引用次数不准确,但是从侧面反应了这篇文章的质量,经典文章的引用次数绝对很高的.同时如果你用作者进行搜索时,会按引用次数出现他写的全部的文章,就可以知道作者的哪些文章比较经典,在没有太多时间的情况下,就可以只看经典的. 2.如果上面的方法找不到全文,就把文章作者的名字或者文章的title在Google 里搜索(不是Google 学术搜索),用作者的名字来搜索,是因为我发现很多国外作者都喜欢把文章的全文(PDF)直接挂在网上,一般情况下他们会把自己的文章挂在自己的个人主页(home page)上,这样可能也是为了让别的研究者更加了解自己的学术领域,顺便推销自己吧。这样你就有可能下到你想要的文献的全文了。甚至可以下到那个作者相近的内容的其它文章。如果文献是由多个作者写的,第一作者查不到个人主页,就接上面的方法查第二作者,以此类推。用文章的title来搜索,是因为在国外有的网站上,例如有的国外大学的图书馆可能会把本校一年或近几年的学术成果的Publication的PDF全文献挂在网上,或者在这个大学的ftp上也有可能会有这样类似的全文.这样就很可能会免费下到你想要的全文了. 3.如果上面两个方法都没有查到你要的文献,那你就直接写邮件向作者要。一般情况下作者都喜欢把自己的文献给别人,因为他把这些文献给别人,也相当于在传播他自己的学术思想。下面是本人向老外作者要文献的一个常用的模板: Dear Professor ××× I am in ××× Institute of ×××, Chinese Academy of Sciences. I am writing to request your assistance. I search one of your papers: 。。。。。。。。。。。。。。。。。(你的文献题目) but I can not read full-text content, would you mind sending your papers by E-mail? Thank you for your assistance. Best wishes !(or best regards) ××× 本人的经验是讲英语的国家的作者给文章的机率会大,一般你要就会给,其它不讲英语的国家,如德国,法国,日本等国家的作者可能不会给。出于礼貌,如果你要的文献作者E-mail给你了,千万别忘记回信致谢. 4.最后一种方法其实大家都熟悉,就是发贴在小木虫上求助。我还用另一种方法,就是直接让我所在的研究所图书馆的管理员帮我从外面的图书馆文献传递。不过有的文献可能是要钱的。一页0.3元,由于我们看文献的钱都是由课题出,所以也就不太考虑钱的问题了。 二.如何快速而准确地获得最新的科研信息. 如何快速准确地从浩如烟海的信息海洋中获取所需的信息,并学会分析、利用信息资源已经成为人们立足于信息社会的一个重要技能.提高自己在当今复杂的信息世界中准确、快速地获取信息的能力,对我们科研人员是至关重要的.我们要时时刻刻了解最新的科研成果,最主要的途径还是要了解最新的科研文献,但是对于我们常用的数据库,我们又不可能每天都去访问一次数据库来查看是否有最新的文献出来,而对于许多国外的数据库.文章的出版效率非常高,有的是每周出几篇新的文章,有的是每半月出一次,还有一月出一次的,所以大家发现很难有精力保持每天都去浏览数据库.但是大家有没有发现,国外的数据库有个很好的服务功能就是如果你在其数据库的网站上注册了邮箱,数据库就会自动在每期有新的文章出来时把文章的内容及链接发到你的邮箱里,直接通知你.这样就对我们获取到最新的信息提供了方便.以Elsevier为例,在数据库网站上有"Alerts"点点击进入,要求你输入"User Name"和"Password",这是对已经注册了邮箱的人进行的.如果你还没有注册,同样会看到右边有一行英语"If not, Register Now. It's FREE and allows you to"这时点击右边的"Register Now",就可以进入进行注册,选择你要求的期刊以及你所研究的领域等等,当然还要填好你接受邮件的邮箱,注册成功后,以后就可以收到最新的文献了,同时你可以随时修改你的接受邮件的邮箱.不仅是象Elsevier这样的数据库有这个功能.几呼所有的外文数据库都有"Email-Alert"这一功能.大家可以试试. 三.如何进行文献阅读 其实做科研,不看文献要做好科研,可以说一点可能都没有。只有广看论文,深入学习,才能厚积薄发,写出响当当的文章出来。读文献一定不要心浮气躁,或者就是想着混个毕业。相反我们要沉下心来,大量阅读文献,在读的过程中有的文献看懂了,但是看不懂的文献也可能会居多。看懂的认真学习借鉴,看不懂的 深入探索,实在不行就暂时放下,过一段时间,随着知识和能力的提高慢慢也就弄明白了一些。即使还是看不懂,但是心里知道有那么回事,为将来的继续深造做了铺垫。另外千万不要只是为看文献而看文献,我们看的目的是为了能为我们自己的科研所用,所以看的过程中一定要和你自己的数据相结合,当看完一篇文献后,要好好总结,如果用自己的数据,又该怎么样解释。还有一些牛刊物上的文章,不但要学习文章里面的知识,还要学习牛人写文章的文风。好的文章肯定会有好的文风,这些都是我们将来写文章要学习的。 另外相信很多搞科研的同行会有个感觉,就是看过的文献,如果只是做做标记,划下划线,还是很容易忘记,过段时间要查询起来也费事。尤其是看过的文献有几百,上千篇时,虽然可以归类整理,但效果还是不好。 我建议大家边看一篇文献时,边打开word文档,边整理文章出彩和重要的部分,然后复制过去,标上文献的标题和作者等相关信息,把每一类文献归为一组。 方法操作简单,将来要查询和反复的时候会有很大帮助,尤其在写文章时,相关文献及其亮点都一目了然。这个方法积累久了,对提升写作和阅读都有很大帮助,除了这样,我还有时把一些很经典的段落或都语句翻译成中文,专门整理在一个本本上,这样不但在以后写文章时直接拿出来看,省事省时间,还能锤炼英汉互译的能力,很有利于以后你和老外交流时的口语表达。 最后,请大家始终记住,我们查文献都是为了科研,千万不要只查不看,费了那么大劲查到了就一定要看完.就算是你大概的看了一下也是有用的.同样对科学问题要辩证的看待,文献上别人的观点也只是一家之言,而且不要迷信权威. “ 科学本身是人类的一种实践。科学研究是一个思考过程。科学行动则是推行某种思考过程的活动,其目的是为了检验这些思考过程的有效性,进而修正和改善这些思考过程,以期达到最高的认识。像一切科学实践一样,科学的判断力取决于个人的经验、信仰和情绪。 我们中间的许多人,或者说我们全体,在我们的专业经历中,都犯过这样或那样的错误。科学工作者应当有虚怀若谷的精神,敢于摒弃先入之见,敢于摆脱对错误思想感情上的依附. NO.2 这是一位出国留学博士生的学习体会,放到师生互动栏目里与大家交流、分享。 这是我受网上一篇文章的启发并结合我们专业的特点,写的一点个人体会,希望对大家有所裨益。 要在高起点上开展学术研究,阅读英文原文是不可或缺的环节。英文文献阅读的重要性不需赘述,国内多数理工科院校的研究已经实现了和国际的接轨,管理和经济学科相对滞后,但是部分团队已经走在前列。 中文文献看多了之后就会发现很多内容似曾相识,英文文献在内容的广度和深度方面更胜一筹。阅读英文文献的目的不是为了论文增加几个参考文献而看上去好看,当然国内有些人是这么做的,更有甚者为了增加英文参考文献而引用二手或者三手文献,在转引过程中漏洞百出。广泛阅读英文文献是提高综合能力及水平,优化知识结构,转换思维方式,拓展研究视野的必由之路,当然最重要的是将国际先进和中国实际相结合。 (1)英文原文读不懂怎么办? 其实我以前也根本没读过原文,也看不懂。这儿有个好办法:找一本中文经典的书籍,仅看某一节你感兴趣或与你相关的内容,然后先找一两篇英文的综述(review)认真阅读一下,不会的单词可用金山词霸查一查,也许你读第一篇文章需要花两天,你过两天再读第2遍时,你也许只要一天;然后你再读第2篇时也许你只要半天!然后你一定会真正发现读英文文献的快感!(引用部分) 我和这位作者有相同的体会,刚开始阅读的时候可能有些困难,当你经过一个时期的训练之后,就会很快进入状态,并且感觉受益良多。 (2)我们需要阅读什么样的文献? 虽然英文文献总体上水平比较高,但并不是所有的文献都值得阅读,阅读文献的前提是能够检索到对你有价值的文献。第一步知道如何检索文献,现在学校的英文数据库平台很多,可以尝试检索和合理利用。当然机器检索不能完全找到和主题相关的文章,需要扩大检索范围,然后认真阅读摘要,筛选和自己工作相关的文献。第二步知道如何确定文章的价值,这和中文文献阅读具有相似之处,首先是重要期刊的文章,其次是著名学者的文章。例如在国家创新体系领域,Lundvall\Freeman\Nalson\OECD\Porter等这些重要的作者和机构的文献是必读的,不仅要精读他们的经典文献,而且要追踪其最新研究成果,包括工作论文、讨论稿等。通过对重要作者的研究和经典文献的阅读能给你打开一扇门,让你进入一个由核心作者、相关作者、主要期刊和主要研究机构形成的学术网络。 (3)阅读英文文献需要持之以恒 英文文献的阅读需要持之以恒。不只是为了写文章或者做项目才去检索和阅读文献,而是需要贯穿于研究生学习的全过程。这是选题和把握前沿领域的重要途径,同时也可以提高自己的英文阅读能力。当然,文献阅读的效果不会在短期内显现出来,不能说读了几篇英文文献就怎么样,但是当你把英文文献作为主要阅读对象时,可能会渐渐发生变化。 有些中文文献存在不足之处,例如,数据可靠性差、观点(判断)不可检验;方法运用存在缺陷;文献综述不全面等。对于多数社会科学而言我们最终还是要研究中国问题,中文文献是入门的基础,国内重要期刊的文章仍然需要有一个全面的了解。 如果平时读得多了,自然会有感觉,找更高级别杂志的文章读。国外著名的科学家一般都有一个习惯,即每周都认真读1-2篇Science, Nature, Cell等高级别文章。这个习惯希望每个人都能保持!而且Science对中国人是免费的!Nature中也有许多内容是免费的,即使没有密码之类,也能得到大量有用的信息呀。临床的同志一定要读读The lancet和新英格兰杂志!这两本简直太经典了! NO.3 如何阅读外文文献? 本人是学经济的.看了大量的外文文献.开始时也觉得效率低,不是单词不认识,而是看了后面忘了前面.后来摸索出了一些方法,和大家共享. 三步骤: 首先,通读各个小标题.通常英文文献都很长.拿来文献,先把各个小标题串一串.弄清楚内在的联系. 其次,跳进去读各个小标题内的内容.标注是必不可少的,就是在必要的段落标示出作者的观点.这是为了第三步做准备. 最后,跳出来,再把全文串一遍.根据做好的标示做好阅读摘要. 这样就完成了. 【转帖:读外文文献的一点体会】 PS:一直不会看外文文献,学学人家。 本人英语基础不好,没过六级,所以在硕士的时候基本上看的外文文献很少,现在想想很后悔,2年的时间少学了很多东西。上了博士,自己给自己的定位也高一些了,开始打算硬着头皮咬着牙很不情愿的也要多看些外文文献,一开始看比较慢,有些很难理解,到现在大约仔细阅读了100篇外文文献,泛读了100篇外文文章,受益匪浅,现在基本不怎么看中文的了,确实也觉得外文的质量就是高(也有凑数的烂文章),现在自己写外文的也很顺手了。谈几点自己的体会。 1.先找5篇跟自己论文最相关的外文文章,花一个月的时间认认真真的看,反复看,要求全部读懂,不懂的地方可以和同学和老师交流一下。一个月以后你已经上路了。 2.如何读标题:不要忽视一篇论文的标题,看完标题以后想想要是让你写你怎么用一句话来表达这个标题,根据标题推测一下作者论文可能是什么内容。有时候一句比较长的标题让你写,你可能还不会表达。下次你写的时候就可以借鉴了 3.如何读摘要:快速浏览一遍,这里主要介绍这篇文章做了些什么。也许初看起来不好理解,看不懂,这时候不要气馁,不管它往下看,等你看完这篇文章的时候也许你都明白了。因为摘要写的很简洁,省略了很多前提和条件,在你第一眼看到摘要而不明白作者意图的时候看不懂是正常的。 4.如何读引言(前言):当你了解了你的研究领域的一些情况,看引言应该是一件很容易的事情了,都是介绍性的东西,写的应该都差不多,所以看文献多了以后看这部分的内容就很快了,一扫而过。有些老外写得很经典得句子要记下了,下次你写就可以用了。 5.如何读材料及试验:当你文献看多了以后,这部分内容也很简单了,无非就是介绍试验方法,自己怎么做试验的。很快就能把它看完了吧 6.如何看试验结果:看结果这部分一定要结合结果中的图和表看,这样看的快。主要看懂试验的结果,体会作者的表达方法(例如作者用不同的句子结构描述一些数字的结果)。有时看完以后再想想:就这么一点结果,别人居然可以大篇幅的写这么多,要是我可能半页就说完了? 7.如何看分析与讨论:这是一篇文章的重点,也是最花时间的。我一般把前面部分看完以后不急于看分析讨论。我会想要是我做出来这些结果我会怎么来写这部分分析与讨论呢?然后慢慢看作者的分析与讨论,仔细体会作者观点,为我所用。当然有时候别人的观点比较新,分析比较深刻,偶尔看不懂也是情理之中。当你看的多了,你肯定会看的越来越懂,自己的idea越来越多 8.如何看结论:这个时候看结论就一目了然了,作后再反过去看看摘要,其实差不多 9.把下载的论文打印出来,根据与自己课题的相关性分三类,一类要精读,二类要泛读,三类要选择性的读。分别装订在一起 10.看完的文献千万不要丢在一边不管,3-4个月一定要温习一遍,可以根据需要,对比自己的试验结果来看 11.学会记笔记,重要的结论,经典的句子,精巧的试验方案一定要记下来,供参考和学习 12.有些试验方法相同,结论不同的文献,可以批判性的阅读。我想要是你自己做试验多的话,你应该有这个能力判断谁的更对一点。出现试验方法相同,结论不同的原因有下:试验方法描述不详细,可能方法有差别;试验条件不一样;某些作者夸大结果,瞎编数据 13.有时间还是多看点文献吧,最好定个目标:在学术上超过自己的老板。因为老板一般不看文献,他们都是凭经验做事,很多新东西他们都不知道,慢慢的你老板会觉得你很厉害。 反正我觉得多读了,读起来就快了,而且也会慢慢喜欢上看外文文献,收获自然也就多了。 可能写得有点乱,凑合看吧,我们一起奋斗!!!
posted @
2012-05-21 21:16 mengkai 阅读(325) |
评论 (0) |
编辑 收藏
摘要: 源地址:http://blog.csdn.net/v_july_v/article/details/7577684http://blog.csdn.net/v_july_v/article/details/6142146
数据挖掘领域十大经典算法初探
第一篇:从决策树学习谈到贝叶斯分类算法、EM、HMM
引言
最近在面...
阅读全文
posted @
2012-05-21 20:14 mengkai 阅读(710) |
评论 (0) |
编辑 收藏
最近在学opencv,先用vc6.0+opencv1.0,可以根据opencv论坛上的步骤配置完成,下面记录了配置过程。
下面是介绍如何安装opencv1.0
1 下载OpenCv1.0,可以在这里下载:http://www.opencv.org.cn/download/OpenCV_1.0.exe
2 安装OpenCv1.0,可以安装在D:\opencv1.0\OpenCV(用户可以自己选择),
3 在安装是勾选Add\OpenCV\bin to the systerm PATH(将\OpenCV\bin加入系统变量)
4 添加环境变量,右击我的电脑,选择属性,点击高级选项卡,点击环境变量,在用户变量下找到path(没有的话新建),点击编辑,在变量值的最后添加 D:\opencv1.0\OpenCV\bin,然后点击确定,重启电脑。
5 下载cxcore100.dll文件,可在以下网站下载:
http://www.codefans.net/dll/download.php?id=1425&type=wj
然后将文件cxcore100.dll以及安装目录D:\opencv1.0\OpenCV\bin下的highgui100.dll,libguide40.dll拷贝到C:\WINDOWS\system32目录下。
下面就是介绍vc6.0下配置opencv1.0
一 在VC编译器下,在Project菜单下选择setting,弹出对话框。
1 设置预编译的头文件
选择C/C++ 【Category】,在下拉菜单中选择Preprocessor,然后在Additional Include directories 中输入以下几项:
C:\Program Files \OpenCV\cv\include (根据本人机器上OpenCV的安装路径进行设置,如在D盘,则写D: ,以下同)
C:\Program Files \OpenCV\otherlibs\highgui
C:\Program Files \OpenCV\cxcore\include(新版本需要)
C:\Program Files \OpenCV\otherlibs\cvcam\include
每一条之间用逗号隔开。其中C:\Program Files\Intel\opencv 为OpenCV的安装路径,这是通用的安装路径,建议最好采用这种设置,以方便大家交流;不然,每次都要重新设置路径,比较麻烦。
2 设置链接库
在 Link按键下的 Category下拉菜单中选择 Input选项(指定要连接的库文件,放弃连接的库文件hao ),在Additional library path中,输入:
C:\Program Files \OpenCV\lib
最后在 Setting For下拉菜单中依次选择 Win32 Debug和 Win32 Release,分别在Object /library modules 输入:
cv.lib highgui .lib cxcore.lib cvcam.lib
注意每个库之间用一个空格隔开。
或者直接在all configurations中的Object /library modules 输入:cv.lib highgui.lib cxcore.lib(新版本需要) cvcam.lib
(cxcore.lib highgui.lib 是几乎所有OpenCV程序都要用到的函数库,分别封装了基本的函数和图形界面接口,cv.lib中封装了大量的图像处理函数,cvcam.lib中封装了很多针对视频流的处理函数)
当前工程就可以使用OpenCV的函数了。
二 如果一直要使用OpenCV的函数,把其路径设置到系统目录下
在Tools 菜单下选择 Options 子菜单,在弹出的对话框中选择Directory,将用到的几个库的路径添加进去。以后只需将所用的库在Object /library modules下输入就可以了,不用再每次指定路径。
在Show directories for 下拉菜单中选择Include files,输入:
C:\Program Files \OpenCV\cv\include
C:\Program Files \OpenCV\otherlibs\highgui
C:\Program Files \OpenCV\cxcore\include(新版本需要)
C:\Program Files \OpenCV\otherlibs\cvcam\include
在Show directories for 下拉菜单中选择Library files,输入:
C:\Program Files \OpenCV\lib
注意:(防止每次都拷贝.dll文件)
-
安装OpenCv是一定要勾选Add\OpenCV\bin to the systerm PATH
-
配置VC6.0时要选择用户自己的OpenCv安装路径。
-
编写OpenCv程序时,要手动添加lib文件,否则编译不会通过。
posted @
2012-03-03 21:02 mengkai 阅读(4082) |
评论 (0) |
编辑 收藏
回来已经不知不觉一个月了,但是根本没有找到感觉,自我定位还是不明确,所以需要写点计划
在网上看到很多人都写了自己的学期计划,大多目标都很明确。我刚开学的时候思想的很浮动,混乱了一段时间,做很多事情效率都很低。到现在已经过去四周的时间了,经过一些思考,基本上也有了一套学习计划。
第一是英语,以前的我没有重视英语真是一个大大的错误,虽然不是很喜欢,但是每天还是要花些时间学习,毕竟六级还没有过去,虽然听说比考试更重要,但是还得需要一个成绩来证明这些成果。
第二是算法,为以后的就业和找工作做好铺垫。要多看一些算法的书籍,来加强自己在算法方面的不足,数据结构更要努力。有机会一定多读读算法导论这边书。
第三是操作系统,顺便需要看看汇编,现在感觉操作系统和汇编有着紧密的联系,而且对编程有着事半功倍的效果,需要仔细看看。
第四是计算机组成原理,需要巩固这方面的知识,此外需要深入计算机体系结构这边书,是相当的经典,需要慢慢的去琢磨。
第四是linux,这方面比较欠缺,所以需要下点功夫。
第五是windows编程以及毕业设计相关的东西opencv,网络编程博大精深,需要慢慢的去研究,目标跟踪是我选的题目需要搭起框架,在目标跟踪算法进一步作出选择和改进。
我没有想好去大公司还是刚起步的小公司,只是努力把自己的基础搞好,希望入职的时候可以有一个好的薪水,能够未来能养活自己的家庭老婆。
posted @
2012-03-03 20:54 mengkai|
编辑 收藏
对于斐波那契数列的求解过程的几种方法的比较
(1)最基本的方法:递归实现,使用公式为f[n] = f[n-1] + f[n-2];递归
结束条件是f[1]=1,f[2]=1。
(2)数组实现:空间复杂度和时间复杂度都是O(N),效率一般,比递归来
的快。
(3)vector<int>实现,时间复杂度是O(N),空间复杂度O(1),但是不知道
效率会高不高,当然vector有自己的属性会占用资源。
(4)queue<int>实现,当然队列数组更适合实现斐波那契数列,时间复杂度
和空间复杂度和vector一样。但是queue太合适这里了,
f(n)=f(n-1)+f(n-2),f(n)只和f(n-1)和f(n-2)有关,f(n)入队列后,f(n-
2)就可以出队列了。
(5)迭代实现:迭代效率最高,时间复杂度是O(N),空间复杂度是O(1),
(6)百度的提供的一种公式法。 由于double类型的精度还不够,所以程
序算出来的结果会有误差,如果把公式展开计算,得出的结果就是正确的。
具体代码如下:
//递归
int fib1(int num)
{
if(num<1)
return -1;
if(num == 1 || num == 2)
return 1;
return f(n-1)+f(n-2);
}
//数组实现
int fib2(int num)
{
if(num<1)
return -1;
if(num<3)
{
return 1;
}
int *a = new int[num];
a[0] = a[1] = 1;
for(int i = 2;i<num;i++)
a[i] = a[i-1] + a[i-2];
int ret = a[num-1];
delete[] a;
return ret;
}
//vector<int>
int fib3(int num)
{
if(num<1)
return -1;
vector<int>a(2,1);
a.reserve(3);
for(int i = 2;i<num;i++)
{
a.insert(a.begin(),a.at(0)+a.at(1));
a.pop_back();
}
return a.at(0);
}
//queue<int>实现
int fib4(int num)
{
if(num<1)
return -1;
queue<int>q;
q.push(1);
q.push(1);
for(int i = 2;i<num;i++)
{
q.push(q.front()+q.back());
q.pop();
}
return q.pop();
}
//迭代实现
int fib5(int num)
{
int i,a=1,b = 1,c = 1;
if(num<1)
return -1;
for(i = 2;i<num;i++)
{
c= a + b;
a = b;
b = c;
}
return c;
}
//公式实现
int fib6(int num)
{
double gh = sqrt((double)5);
return pow(1+(1+gh),n-pow(1-gh))/(pow((double)2,n)*gh);
}
posted @
2011-10-26 17:46 mengkai 阅读(892) |
评论 (0) |
编辑 收藏
递归算法:基本含义,一个函数或者数学结构,如果在其定义或说明内部直接或间接得出现对其本身的引用,或者是为了描述问题的某一个状态,必须要用它的上一个状态,而描述上一个状态,又必须用到它的上一个状态,这种定义,称为递归或递归定义。在程序设计上,当函数直接调用本身或者间接调用本身,称为递归调用。
递归的最简单应用:通过各项关系及初值求数列的某一项。(1)
比如阶乘数列
1、2、6、24、120、720……
如果用上面的方式来描述它,应该是:
,程序实现
int fun(int x)
{
if(x == 1)
return 1;
return n*fun(n-1);
}
(2)找出组合数
找出从自然数1、2、……、n中任取r个数的所有组合。例如n=5,r=3的所有组合为:
(1)5、4、3 (2)5、4、2 (3)5、4、1
(4)5、3、2 (5)5、3、1 (6)5、2、1
(7)4、3、2 (8)4、3、1 (9)4、2、1
(10)3、2、1
如何实现呢?
首先分析10个组合,我们可以采用递归来实现,假设函数为combo(int m,int n);为找到自然数1-m中任取K个数组合,当第一个数选定后,后面的k-1个数是从m-1各数中选择得到。我们发现这将是将m选k个数转换为m-1个数中选k-1个数的组合数。为了解决此问题,我们可以定义个数组A,数组的第一个元素为k,约定函数将确定的k个数字的组合第一个数放在A[k]中,当一个组合求出后,才将数组A的一个组合输出,第一个数可以是m-k,函数将确定组合的第一个数放入数组后,有两种可能的选择,因还未到顶组合的其余元素,继续递归确定,或因一确定了组合的全部元素,输出这个组合,
具体代码:
//递归求解组合数
#define MAX 100
int a[MAX];
void combo(int m,int k)
{
int i,j;
for (i = m;i>=k;i--)
{
a[k] = i;
if (k>1)
{
comb(m-1,k-1);
}
else
{
for (j = a[0];j>0;j--)
{
printf("%4d",a[j]);
}
printf("\n");
}
}
}
更多的练习,
前几天在博客园看到有人面试时,遇到递归算法题,一时手痒就解了一个。顺便网上又找来几个,也实现了。给大家分享一下,开阔一下思路,没准你明天面试就能用上。
1、编写一个方法用于验证指定的字符串是否为反转字符,返回true和false。请用递归算法实现。(反转字符串样式为"abcdedcba")
2、一列数的规则如下: 1、1、2、3、5、8、13、21、34...... 求第30个是多少
3、一列数的规则如下: 1、12、123、1234、12345、123456......,求第n个数的递归算法(n<=9)。
4、将一整数逆序,如987654321变为123456789。
5、一个射击运动员打靶,靶一共有10环,连开10枪打中90环的可能行有多少种?
posted @
2011-10-22 21:22 mengkai|
编辑 收藏
关于#include "stdafx.h"
(1)Standard Application Frame Extend没有函数库,只是定义了一些环境参数,使得编译出来的程序能在32位的操作系统环境下运行。Windows和MFC的include文件都非常大,即使有一个快速的处理程序,编译程序也要花费相当长的时间来完成工作。由于每个.CPP文件都包含相同的include文件,为每个.CPP文件都重复处理这些文件就显得很傻了。为避免这种浪费,AppWizard和VisualC++编译程序一起进行工作,如下所示:
1.AppWizard建立了文件stdafx.h,该文件包含了所有当前工程文件需要MFCinclude 文件。且这一文件可以随被选择的选项而变化。
2.AppWizard然后就建立stdafx.cpp。这个文件通常都是一样的。
3.然后AppWizard就建立起工程文件,这样第一个被编译的文件就是stdafx.cpp。
4当VisualC++编译stdafx.cpp文件时,它将结果保存在一个名为stdafx.pch的文件里。(扩展名pch表示预编译头文件。)( 预编译头文件通过编译stdafx.cpp生成,以工程名命名,由于预编译的头文件的后缀是“pch”,所以编译结果文件是projectname.pch。)
5.当VisualC++编译随后的每个.cpp文件时,它阅读并使用它刚生成的.pch文件。
VisualC++不再分析Windows include文件,除非你又编缉了stdafx.cpp或stdafx.h。这个技术很精巧,你不这么认为吗?(还要说一句,Microsoft并非是首先采用这种技术的公司,Borland才是。)在这个过程中你必须遵守以下规则:
1.你编写的任何.cpp文件都必须首先包含stdafx.h。
2.如果你有工程文件里的大多数.cpp文件需要.h文件,顺便将它们加在stdafx.h(后部)上,然后预编译stdafx.cpp。
3.由于.pch文件具有大量的符号信息,它是你的工程文件里最大的文件。
如果你的磁盘空间有限,你就希望能将这个你从没使用过的工程文件中的.pch文件删除。执行程序时并不需要它们,且随着工程文件的重新建立,它们也自动地重新建立
(2)stdafx.h文件中包含了一些必要的头文件(如afxwin.h),对应于stdafx.h有一个stdafx.cpp文件,该文件内包含一句: #include "stdafx.h",其作用是令编译器编译出一个stdafx.obj预编译头文件(pre-compile header,需要设置编译选项),在下次编译时以降低总的编译时间。若使用ClassWizard定义新类,则有可能在stdafx.h中增加新的 include files。比如,若选用MFC template classes,stdafx.h中便会增加:#include <afxtempl.h>。
(3)注:1.afxwin.h是MFC编程的必需文件,其中包含如CString,CEdit类运行所必需的头文件,最好保证该句在头文件首行;它还会调用windows.h,改头文件包含有数据类型的定义、API入口点定义和其它有用的参数信息;
2.非MFC工程使用MFC库时最常见的问题就是windows.h重复包含错误:fatal error C1189: #error : WINDOWS.H already included. MFC apps must not #include <windows.h>;
3.#define WIN32_LEANAND_MEAN,在windows的头文件中拒绝接受MFC类库,以加速编译时间;
4.afx - afx中的af指的是Application Frame的缩写,曾经有一个技术开发团队专门作Application Frame,后来给这个团队命名用afx,x本身没有含义,只不过构成一个响亮的口号,后来就一直沿用下来。
5.建立了一个新的空的工程,项目中的stdafx.cpp使用的是Create Precompiled Header (/Yc),而其它.cpp是用的Use Precompiled Header (/Yu),并且Create/Use PCH Trhough File是stdafx.h
(4)stdafx是预编译头文件。你可以从VC++集成环境菜单Project/Settings...中
Project Settings Dialog/C/C++/Category:Precompiled Headers/Use precompiled header file(.pch)的Check Box中看到。已经将Stdafx.h文件作为预编译的头文件来使用。预编译头文件是在编译所有Code之前,首先进行的动作。通过解析这个文件,取得定义的结构和参数。这样就不用在编译每个文件时都重新进行解析。提高编译速度。stdafx.h这个名称是可以改变的,你可以指定预编译头文件的名称。这个只在vc中有用,并不是c++的特性,vc中可以在这里声明全局变量和ID的地方
(5) fatal error C1083: Cannot open include file: 'stdafx.h': No such file or directory
A如果根本没有stdafx.h,你为何要包含它.一般只有大工程才需要预编译头文件.stdafx.h
删除这一行#include "stdafx.h"
B project-> Settings->c/c++ category->Precomiled Headers 选择第一个 Not using precompiled headers
C Project->Settings->C/C++->Project Options中把/Fp"Debug/Your_Project_Name.pch"和/Yu"stdafx.h"两项删掉就可以了。要注意原来在stdafx.h内包含的文件要包含到各个.cpp文件中.
D在*.cpp中的开头加入#include "stdafx.h".(#include "stdAfx.h" 放到另外#include的前面,也就是程序的最前面。使用预编译头文件需要把它放到程序最前面,否则它前面的内容会被忽略)
E rebuild all
(6)设置了预编译,如果不加#include "stdafx.h", 就会报这个错: fatal error C1010:
unexpected end of file while looking for precompiled header directive。编译器通过一个头文件stdafx.h来使用预编译头文件。stdafx.h这个头文件名是可以在project的编译设置里指定的。编译器认为,所有在指令#include "stdafx.h"前的代码都是预编译的,它跳过#include "stdafx. h"指令,使用projectname.pch编译这条指令之后的所有代码。因此,所有的CPP实现文件第一条语句都是:#include "stdafx.h"。
posted @
2011-10-10 17:01 mengkai 阅读(467) |
评论 (0) |
编辑 收藏
对于阶乘是个很有意思的函数,给定一个整数,那么它的阶乘是多少那?而它末尾有多少个0,
对于这个问题,是不是要直接计算N!?如果溢出怎么办,我们如何快速的找到该题的结果?首先要思考的N!= M*10^E。在N之前你需要看看那几个的成绩满足即可,比如2*5=10,所有2和5乘积就可以得到一个10,于是由于能被2整除的整数的频率要高于能被5整除的,所以我们可以取5考即可。
方法一从1开始到N,算出符合要求的个数。int result=0;
for(i = 1;i<=N;i++)
{
j = i;
while(j%5 == 0)
{
result++;
j/5;
}
}
或者是while(N)
{
result+=N/5;
N/=5;
}
类似可以求解二进制的问题,比如求N!的二进制中最低位1的位置。
由于N!中含有质数2的个数。等于N/2+N/4+N/8....1.
int lowOfone(int n)
{
int result = 0;
while (n)
{
n>>=1;
result+=n;
}
return result;
}
对于
给定整数n,判断它是否为2的方幂(解答提示:n>0&&((n&(n-1))==0))。
转载:
【N!二进制的解法二】
N!含有质因数2的个数,还等于N减去N的二进制表示中1的数目。我们还可以通过这个规律来求解。
下面对这个规律进行举例说明,假设 N = 11011,那么N!中含有质因数2的个数为 N/2 + N/4 + N/8 + N/16 + …
即: 1101 + 110 + 11 + 1
=(1000 + 100 + 1)
+(100 + 10)
+(10 + 1)
+ 1
=(1000 + 100+ 10 + 1)+(100 + 10 + 1)+ 1
= 1111 + 111 + 1
=(10000 -1)+(1000 - 1)+(10-1)+(1-1)
= 11011-N二进制表示中1的个数
小结
任意一个长度为m的二进制数N可以表示为N = b[1] + b[2] * 2 + b[3] * 22 + … + b[m] * 2(m-1),其中b [ i ]表示此二进制数第i位上的数字(1或0)。所以,若最低位b[1]为1,则说明N为奇数;反之为偶数,将其除以2,即等于将整个二进制数向低位移一位。
posted @
2011-09-29 13:51 mengkai 阅读(517) |
评论 (0) |
编辑 收藏
STL容器的学习总结:
第一:迭代器iterator
首先,迭代器的定义,能够用来遍历STL容器中的部分或者全部元素,每个迭代器对象都代表着容易中的确定的地址,迭代器类似于指针类型,修改了常规指针的接口,是一种概念上的抽象,提供了*,++,==,!=,=操作,这些操作和C/C++操作数组元素时的指针接口一致。不同之处是该迭代器是一种smart pointer,具有遍历复杂数据结构的能力,所有操作行为都使用相同接口,虽然它们的型别不同。迭代器使开发人员能够在类或结构中支持foreach迭代
一般分为五种迭代器:输入迭代器istream_iterator<>和istreambuf_iterator<>,输出迭代器ostream_iterator<>和ostreambuf_iterator<>,前向迭代器,双向迭代器,随机访问迭代器
back_insert_iterator<Container> 使用Container的push_back成员函数
front_insert_iterator<Container> 使用Container的push_front成员函数
insert_iterator<Container> 使用Container的insert成员函数
reverse_iterator<Container> 从后向前使用Container的insert成员函数
const——iterator<>
二 分配算符(Allocators)
看看stl中默认的allocator:
namespace std {
template <class T>
class allocator {
public:
//type definitions
typedef size_t size_type; //represent the size of the largest object in the allocation model
typedef ptrdiff_t difference_type; //The type for signed integral values that can represent the distance between any two pointers in the
//allocation model
typedef T* pointer;
typedef const T* const_pointer;
typedef T& reference;
typedef const T& const_reference;
typedef T value_type; //The type of the elements
//rebind allocator to type U
template <class U>
struct rebind {
typedef allocator<U> other;
};
//return address of values
pointer address(reference value) const;
const_pointer address(const_reference value) const;
//constructors and destructor
allocator() throw();
allocator(const allocator&) throw();
template <class U>
allocator(const allocator<U>&) throw();
~allocator() throw();
//return maximum number of elements that can be allocated
size_type max_size() const throw();
// allocate but don't initialize num elements of type T
pointer allocate(size_type num,
allocator<void>::const_pointer hint = 0);
// initialize elements of allocated storage p with value value
void construct(pointer p, const T& value);
// delete elements of initialized storage p
void destroy(pointer p);
// deallocate storage p of deleted elements
void deallocate(pointer p, size_type num);
};
}
看了上面的allocator,我们已经基本知道他的用处,他一般用在容器中,作为容器的一个成员,但一般是用模版参数传入,这样才可以让我们换成我们自定义的allocator。
vector就是动态数组,在堆中分配内存,元素连续存放,有保留内存,如果减少大小后内存也不会释放。新值大于当前大小时才会再分配内存。[]可以使用,随机插入,删除要慢,快速的在末尾插入元素。最重要一点就是它的迭代器会失效。
比如:typedef vector IntArray;
IntArray array;
array.push_back( 1 );
array.push_back( 2 );
array.push_back( 2 );
array.push_back( 3 );
// 删除array数组中所有的2
for( IntArray::iterator itor=array.begin(); itor!=array.end(); ++itor )
{
if( 2 == *itor ) array.erase( itor );
}
这样是不行的,需要按照下面的实现:
for( IntArray::iterator itor=array.begin(); itor!=array.end(); ++itor )
{
if( 2 == *itor )
{
array.erase( itor );
itor--;
}
}
deque,与vector类似,支持随机访问和快速插入删除。与vector不同的是,deque还支持从开始端插入、删除数据0,[]可以使用,速度没有vector快。快速的访问随机的元素。快速的在开始和末尾插入元素,重新分配空间后,原有的元
素不需要备份。对deque排序时,可以先将deque的元素复制到vector,排序后在复制到deque
list。只能顺序访问不支持随机访问,不存在空间不够
关联容器:更注重快速和高效的检索数据的能力
set:快速查找,不允许重复值。
multiset快速查找,允许重复值。
map:一对一映射,基于关键字快速查找,不允许重复值,key不能重复
multimap一对多映射,基于关键字快速查找,允许重复值
容器适配器:对已有的容器进行某些特性的再封装,
stack:
queue:
(1)获取向量中的元素值可用三种方式,直接用向量数组,获得元素引用,获得元素的指针。
list:插入操作和删除操作都不会造成原有的list迭代器失效,每次插入或删除一个元素就配置或释放一个元素空间,对于任何位置的元素插入或删除,list永远是常数时间。
posted @
2011-09-27 17:52 mengkai 阅读(270) |
评论 (0) |
编辑 收藏