??xml version="1.0" encoding="utf-8" standalone="yes"?>国产成人久久激情91,久久美女网站免费,亚洲国产日韩欧美综合久久http://www.shnenglu.com/Walker/category/10284.html先学会{文章Q在仔细L章,最后自己写点东?.......zh-cnThu, 23 Jul 2009 08:33:45 GMTThu, 23 Jul 2009 08:33:45 GMT60同步/异步与阻?非阻塞的区别 Q{Q?/title><link>http://www.shnenglu.com/Walker/articles/82900.html</link><dc:creator>漫步者?amp;…?K?/dc:creator><author>漫步者?amp;…?K?/author><pubDate>Thu, 14 May 2009 00:44:00 GMT</pubDate><guid>http://www.shnenglu.com/Walker/articles/82900.html</guid><wfw:comment>http://www.shnenglu.com/Walker/comments/82900.html</wfw:comment><comments>http://www.shnenglu.com/Walker/articles/82900.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/Walker/comments/commentRss/82900.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/Walker/services/trackbacks/82900.html</trackback:ping><description><![CDATA[<div id="imscoy6" class=postTitle><a class=postTitle2 id=viewpost1_TitleUrl href="http://www.shnenglu.com/converse/archive/2009/05/13/82879.html"><font color=#1a8bc8>同步/异步与阻?非阻塞的区别</font></a> </div> 我喜Ƣ用自己的语a通过联系现实生活中的一些现象解释一些概?当我能做到这一Ҏ(gu),说明我已l理解了q个概念.今天要解释的概念?同步/异步与阻?非阻塞的区别.<br><br>q两l概念常常让?因ؓ它们都是涉及到IO处理,同时又有着一些相cM的地?<br><br>首先来解释同步和异步的概?q两个概念与<span style="FONT-WEIGHT: bold">消息的通知机制</span>有关.<br><br>举个例子,比如我去银行办理业务,可能选择排队{?也可能取一个小U条上面有我的号?{到排到我这一h由柜台的人通知我轮到我d理业务了.<br>前?排队{?是同步{待消息,而后?{待别h通知)是异步{待消息.在异步消息处理中,{待消息?在这个例子中是{待办理业务的h)往往注册一个回调机?在所{待的事件被触发时由触发机制(在这里是柜台的h)通过某种机制(在这里是写在纸条上的号?扑ֈ{待该事件的?<br>而在实际的程序中,同步消息处理好比简单的read/write操作,它们需要等待这两个操作成功才能q回;而异步处理机制就是类gselect/poll之类的多路复用IO操作,当所x的消息被触发?由消息触发机刉知触发Ҏ(gu)息的处理.<br><br>其次再来解释一下阻塞和非阻?q两个概念与<span style="FONT-WEIGHT: bold">E序{待消息(无所谓同步或者异?时的状?/span>有关.<br>l箋上面的那个例?不论是排队还是用号码等待通知,如果在这个等待的q程?{待者除了等待消息之外不能做其它的事?那么该机制就是阻塞的,表现在程序中,也就是该E序一直阻塞在该函数调用处不能l箋往下执?相反,有的人喜Ƣ在银行办理q些业务的时候一Ҏ(gu)打电(sh)话发发短信一边等?q样的状态就是非d?因ؓ?{待?没有d在这个消息通知?而是一边做自己的事情一边等?但是需要注意了,W一U同步非d形式实际上是效率低下?惌一下你一Ҏ(gu)着?sh)话一边还需要抬头看到底队伍排到你了没有,如果把打?sh)话和观察排队的位置看成是程序的两个操作的?q个E序需要在q两U不同的行ؓ之间来回的切?效率可想而知是低下的;而后?异步非阻塞Ş式却没有q样的问?因ؓ打电(sh)话是?{待?的事?而通知你则是柜?消息触发机制)的事?E序没有在两U不同的操作中来回切?<br><br>很多Z把同步和dh,我想是因为很多时候同步操作会以阻塞的形式表现出来,比如很多Z写阻塞的read/write操作,但是别忘了可以对fd讄O_NONBLOCK标志?q样可以将同步操作变成非阻塞的?同样?很多Z会把异步和非dh,因ؓ异步操作一般都不会在真正的IO操作处被d,比如如果用select函数,当selectq回可读时再去read一般都不会被阻?好比当你的L排到时一般都是在你之前已l没有h?所以你再去柜台办理业务׃会被d.<br><br>可见,同步/异步与阻?非阻塞是两组不同的概?它们可以共存l合,也可以参见这?<br>http://www.ibm.com/developerworks/cn/linux/l-async/<br> <img src ="http://www.shnenglu.com/Walker/aggbug/82900.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/Walker/" target="_blank">漫步者?…?K?/a> 2009-05-14 08:44 <a href="http://www.shnenglu.com/Walker/articles/82900.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Q{Qstrlen源码剖析 http://www.shnenglu.com/ant/archive/2007/10/12/32886.htmlhttp://www.shnenglu.com/Walker/articles/82347.html漫步者?amp;…?K?/dc:creator>漫步者?amp;…?K?/author>Sat, 09 May 2009 01:50:00 GMThttp://www.shnenglu.com/Walker/articles/82347.htmlhttp://www.shnenglu.com/Walker/comments/82347.htmlhttp://www.shnenglu.com/Walker/articles/82347.html#Feedback0http://www.shnenglu.com/Walker/comments/commentRss/82347.htmlhttp://www.shnenglu.com/Walker/services/trackbacks/82347.html阅读全文

]]>
【{】一个游戏程序员的学习资?http://www.shnenglu.com/Walker/articles/81443.html漫步者?amp;…?K?/dc:creator>漫步者?amp;…?K?/author>Wed, 29 Apr 2009 07:07:00 GMThttp://www.shnenglu.com/Walker/articles/81443.htmlhttp://www.shnenglu.com/Walker/comments/81443.htmlhttp://www.shnenglu.com/Walker/articles/81443.html#Feedback0http://www.shnenglu.com/Walker/comments/commentRss/81443.htmlhttp://www.shnenglu.com/Walker/services/trackbacks/81443.html一个游戏程序员的学习资?/span>

 

惌v写这文章是在看侯杰先生的《深入浅?span>MFC》时,H然觉得自己在大学这几年关于游戏~程斚wq算是有些心得,因此写出q篇文,介绍我眼中的游戏E序员的书单与源代码参考。一则是作ؓ自己今后两年学习目标的备忘录,二来没准对别Z有点参考h(hun)倹{我的原则是只写自己研究q或准备研究的资料,所以内Ҏ(gu)疑会带上强烈的个人喜好色?span>,比如对网l?span>,数据库等重要斚w完全没有涉及。因׃要对三维囑Ş引擎,人工法,脚本pȝ,反外?span>(反反外挂? ^Q?span>^){方面感兴趣。这学期?sh)脑都没联网?span>,在岳麓山闭关修炼?span>(^Q?span>^),q这文章都得在学校图书馆电(sh)子阅览室Q电(sh)影放映室Q)上传,内容很多凭记忆写?span>,如有误差敬请订正。程序员应该在理论学习与实践~程中反复P代,所以学习资料是一回事Q须知尽信书不如无书?/span>

 

一、书c:

法与数据结构:

《数据结构(C语言版)》——严蔚敏、吴伟民 清华出版C?/span>

我觉得其配套习题集甚x原书更有价|每个较难的题都值得做一下?/span>

 

?span>Introduction to Algorithms》第二版 中文名《算法导论?/span>

关于法的标准学习教材与工程参考手册,在去q?span>CSDN|站上其译版竟然评为年度二十大技术畅销书,同时《程序员》杂志上开设了“法擂台”栏目Q这些溯源固本的丑֊Q不由得使h对中国现今Qw不堪的所?#8220;IT”业又产生了一U希望。这本厚厚的书,q怺打折我才买得赗虽然厚辑֍,但其英文通俗晓畅Q内Ҏ(gu)入浅出,可见l典之作往往比一般水准的书还耐读。还能找?span>MIT的视频教E,W一节课侯捷先生_“源码面前Q了无秘?#8221;Q又?#8220;天下大事Q必作于l?#8221;Q可以与他的《上IL落下黄泉Q源码追t经验谈》参看?/span>

 

MFC:

《深入浅?span>MFC?/span>

我实在以为没有看q?st1:personname w:st="on" productid="侯捷">侯捷先生的《深入浅?span>MFC》的人多半不会懂?span>MFC~程。其实我是打用一q多的时间写一个给游戏工用的三维~辑器,Z作ؓ毕业设计。图形库qMFC吧,反正也没得选择。如果要?span>wxWidgets无非是猎奇而已Q还不是MFC的翻版,当然它跨q_了。就象阻L对自己枪械的零g了如指掌一P要想?span>MFC写出非玩L序的Z定要了解其内部构造。还有一本书叫?span>MFC深入出》,q不是同一本?/span>

 

IDE:

?span>Microsoft Visual Studio 2005 Unleashed?/span>

工欲善其事,必先利其器。当然我认ؓ与其用Ş?span>Source Insight?span>Slick Edit?span>Code Visualizer之类的代码阅d、图形化工具Q还不如用自q大脑。但如果你嫌打源代码慢的话,可以?span>Visual AssistX。如果嫌老是写重复相似的代码的话Q可以用Code Smith。单元测试可以用CppUnitQ?span>Boost库中的测试框架也不错。有心情可以?span>Visual Studio外接Intel?span>CompilerQ内?span>STLportQ但不是大工E,性能分析没必要动不动q?span>VTune吧?/span>

 

E序员之路:

《游戏之旅——我的编E感(zhn)?/span>

云风大哥。在我心目中游戏E序员国外首推卡马克Q国内首推云风。也许过两年我会到网易当云风大哥的助理程序员吧?span>Its my dream.Q?span>^-^Q他写这本书的时候本着只有透彻理解的东西才写出来,因此内容不会很酷斎ͼ但是怿我,每读一遍都有新的收P主要q不是知识上的,因ؓ知识是学无止境的Q授Zg如授Z渔,_上的启_才是长久的。诚如经典游戏《仙剑奇侠传》的dE序员兼术指导姚壮宪(人称姚仙Q在序言中所说的“云风得到的只是一些稿费,而整个中国民族游戏业得到的是一ơ知识的推动”Q此a不虚矣?/span>

 

《编E高手箴a?/span>

梁肇新是豪杰解霸的作者,本来每个合格的程序员Q?span>Programmer , 而非CoderQ都应该掌握的东西,现在变成了编E高手的独家言。不知是作者的q运q是中国IT业的(zhn)哀。知识点q是讲得蛮多的,不过?span>MFC的地位颇有微词。我实在认ؓMFC的名声就是那些不懂得用它的h搞臭的。不q作者的牢骚也情有可原,每个h创造力的程序员都应该不太喜?span>framework?/span>

 

?span>Masters of DOOM: How Two Guys Created an Empire and Transformed Pop Culture》中文名?span>DOOM启世录?/span>

卡马克,|洛斯,q些游戏史上如雷贯耳的名字。(现在卡马克已专注于火制造上Q罗z斯则携d乡隐居)要不是没上过大学的卡马克和图形学大师亚伯拉罕的功勋,可能到现在游戏中q不知三lؓ何物。勿庸置疑,在计机界历史是英雄们所推动的。这本书真实的记录了q些世英雄的所为所思?/span>

 

作ؓE序员的我对q几本策划与工的书也生了厚兴趣Q以前搞q一两年?span>3DS MAX插g~程Q觉得用maxscriptq是好过MaxSDKQ毕竟游戏开发中所多的是模型场景数据的导入导出Q大可不必大动干戈?/span>

 

{划Q?/span>

?span>Creating Emotion in Games : The Craft and Art of Emotioneering?/span>

在壮丽煊目的宏伟三维世界背后Q在D酷的杀戮,动h心魄的情节背后,我们q需要什么来抓住玩家的心Q答对了Q就?span>emotion.真正打动人心的,才是深入骨髓的?/span>

 

?span>Ultimate Game Design : Building Game Worlds?/span>

从名字可以看出,写给兛_设计师的Q特别是讲室外自然场景的构徏颇有可取之处?/span>

 

?span>Developing Online Games : An Insiders Guide?/span>

p名ؓ反模式的书讲软g团队q营一Pq本书讲商业q作多过技术。一个历l艰难,现在盛大的游戏程序员Q翻译了q本书?/span>

 

工Q?/span>

?span>Digital Cinematography & Directing?/span>

数字摄媄导演术,每当你在3DS MAX或?span>Maya{三l创作Y件中摆放摄媄机,设计其运动轨qҎ(gu)Q你可曾惌你也站在导演的位|上了?

 

?span>The Animators Survival Kit?/span>

看着q本讲卡通角色运动规律的书,一边生温习《猫和老鼠》的念头Q一边l对前不久新闻联播中关于中国产生了某计算动卡通动ȝ成Y件报道的蔑视Q这条报道称此D可大大加快中国卡通动ȝ产量。我且不从技术上探讨其是否是在放卫星Q其实我知道得很清楚Q前文已表,本h搞过一两年的卡通动画辅助Y件编E)Q但计算机机械生成的动画怎可代替人类充满灉|的创作Q?/span>

 

?span>The Dark Side of Game Texturing?/span>

?span>Photoshop制作材质贴图Q还真有些学问?/span>

 

三维囑Ş学:

搞三l图形学首先q是要扎扎实实的先看解析几何、线性代数、计几何的教材Q后面的习题一个都不能。国内数学书q是蛮好的。苏步青大师的《计几何》称得上h世界U水准,可惜中国CAD的宏图被盗版l击垮了。现在是我们接过接力的时候了?span>Its time!

 

 

?span>Computer Graphics Geometrical Tools?span>

《计机囑Ş学几何工L法详解》算法很多,U漏处也不少?/span>

 

?span>3D Math Primer for Graphics and Game Development?/span>

易Q可作ؓ三维数学?#8220;速食“?/span>

 

?span>Mathematics for 3D Game Programming & Computer Graphics》第二版

比上面那本深入一些,证明推理的数学气也浓一些,可作Z业的数学书与~程实践一个过渡的桥梁吧。内Ҏ(gu)猎也q,线q踪Q光照计,可视裁剪Q碰撞检,多边形技术,阴媄法Q刚体物理,体水LQ数值方法,曲线曲面Q还真够丰富?/span>

 

?span>Vector Game Math Processors?/span>

惛_MMX,SSE吗,那就看它吧,不过从基讲v的,要耐心哦?/span>

 

 DirectX:

?span>Introduction to 3D Game Programming with DirectX 9.0?/span>

DirectX入门的龙书,作者自己写的简单示例框Ӟ后面我干脆用State模式Q把所有例子绑C块儿M?/span>

 

?span>Beginning Direct3D Game Programming?/span>

作者取得律师学位后变成了游戏程序员Q真是怪也哉。本书虽定位为入门书,内容颇有独特可取之处。它用到的示例框架是DXSDK Sample FrameworkQ而不是现在通行?span>DXUT。要想编译有两种办法吧,一是自己改写成?span>DXUT的。二是找旧的Sample Framework。我又懒得ؓ了一个示例框架下载整个早期版本的DirectXQ后面在Nvidia SDK 9.5中发C?/span>

 

?span>Advanced Animation with DirectX?/span>

DirectX高动画技术。骨骼系l,渐变关键帧动画,偶h技术,表情变ŞQ粒子系l,布料柔体Q动态材质,不一而。我常常在想Q从三维创作软g导出的种U效果,变成一?span>text?span>binaryQ先加密压羃打包再解包解压解密,再用游戏E序重徏一?span>Lite动画pȝQ游戏程序员也真是辛苦?/span>

 

OpenGL:

?span>NeHe OpenGL Tutorials?/span>

虽是|络教程Q不比正式的书逊,本来?span>OpenGL׃q是看百来条C函数文档的工夫吧,如果囑Ş学基知识扎实的话?/span>

 

?span>OpenGL Shading Language?/span>

OpenGL支持最新显卡技术要靠修修补补的插g扩展Q所以还要配?/span>

?span>Nvidia OpenGL Extension Specifications?/span>

来看Z?/span>

 

?span>Focus on 3D Models?/span>

?span>Focus on 3D Terrain Programming?/span>

?span>Focus on Curves and Surfaces?span>

֐思义Q三本专论,虽然都很不深Q但要对未知三维模型格式作反向工E前Q研?span>Geomipmapping地Ş法论文前,CAD前,q是要看看它们ؓ上,如果没从别处得过到基的话?/span>

 

脚本Q?/span>

先看

?span>Game Scripting Mastery?span>

{自׃解了虚拟机的构造,可以设计出简单的脚本解释执行pȝ了?/span>

再去?span>Python , Lua Q?span>Ruby的手册吧Q会事半半功倍倍的?/span>

 

?span>Programming Role Playing Games with DirectX 8.0?/span>

一Ҏ(gu)学一边用DirectX写出了一?span>GameCore库,初具引擎EŞ?/span>

 

?span>Isometric Game Programming with DirectX 7.0?/span>

三维也是建立在二l的基础上,q就是这本书现在q值得看的原因?/span>

 

?span>Visual C++|络游戏建模与实现?/span>

联众的程序员写的Q功力很扎实Q讲牌cL戏编E,特别讲了UML建模?span>Rotional Rose?/span>

 

?span>Object-Oriented Game Development?/span>

套用某h的话Q?#8220;I like this book.

 

Shader:

要入门可先看

?span>Shaders for Game Programmers and Artists?/span>

讲在RenderMonkey中用HLSL高着色语a?span>Shader.

 

再看

?span>Direct3D ShaderX : Vertex and Pixel Shander Tips and Tricks?/span>

用汇~着色语aQ纯银赤金?/span>

 

三大宝库Q?/span>

?span>Game Programming Gems?/span>

我只见到1-6本,据说W?span>7?span>8本也出来了?附带的源代码常有bugQ不q瑕不掩瑜,q套世界游戏E序员每q一度的技术文集,涉及游戏开发的各个斚wQ我觉得富有开发经验的人更能在其中扑ֈ共鸣?/span>

 

?span>Graphics Gems》全五本

囑Ş学编E?span>BibleQ看了这套书你会明白计算机领域的U学家和工程师区别之所在。科学家L_q个东西在理Z可行。工E师会说Q要佉K题在logN的时限内解决我只能忍痛割爱,舍繁简?/span>

 

?span>GPU Gems》出了二?/span>

Nvidia公司召集囑Ş?span>Gurus写的Q等到看懂的那一天,我也有心情跑?span>Siggraph国际囑Ş学大会上投文章碰q气?/span>

 

游戏引擎~程Q?/span>

?span>3D Game Engine Programming?/span>

?span>ZFXEngine引擎的设计思\阐释Q很q_Q冇太多惊喜?/span>

 

?span>3D Game Engine Design?/span>

数学物理的理论知识讲解较多,本来q样够了,q能期待更多吗?

 

人工Q?/span>

?span>AI Techniques for Game Programming?/span>

讲遗传算法,人工经|络Q主要用C数组Q图法。书的原型是Ҏ(gu)作者发表到GameDev.net论坛上的内容整理出来的,q比较切中实际?/span>

 

?span>AI Game Programming Wisdom?/span>

相当?span>AI~程?span>Gems?/span>

 

?span>PC游戏~程(人机博弈)?/span>

以象程序ؓ蓝本Q介l了很多U搜索算法,除了常见的极大极值算法及其改q?span>--负极大值算法,q有深度优先搜烦以外。更提供了多U改q算法,如:Alpha-Beta,Fail-soft alpha-beta,Aspiration Search, Minimal Window Search,Zobrist Hash,Iterative Deepening,History Heuristic,Killer Heuristic,SSS*,DUAL*,MFD and more.琳琅满目Q实属难得?/span>

 

反外挂:

《加密与解密(W二?span>)?看雪论坛站长 D钢

破解序列号与反外挂有关系么?不过Q世上哪两g事情之间又没有关pdQ?/span>

 

?span>UML Distilled?Martin Fowler

很多人直到看了这本书才真正学?span>UML?/span>

Martin Fowler是真正的大师,从早期的分析模式,到这?span>UML_a,革命性的重构都是他提出的,后来又写了企业模式一书。现在领g个Y件开发咨询公司,dJavaOne中国大会他作Z家来华了吧。个人网站:MartinFowler.com

 

设计模式三剑客:

?span>Design Patterns Elements of Reusable Object-Oriented Software?/span>

?span>Design Patterns Explained?/span>

?span>Head First Design Patterns?span> 

 

重构三板斧:

?span>Refactoring : Improving the Design of Existing Code?/span>

?span>Refactoring to Patterns?/span>

?span>Refactoring Workbook?/span>

 

软g工程:

?span>Extreme Programming Explained : Embrace Change》第二版

其中Simplicity?span>Value真是振聋发聩Q这是我什么都喜欢轻量U的原因?/span>

 

?span>Agile Software Development Principles,Patterns,and Practices?/span>

敏捷真是炒得够火的,q企业都有敏捷一_不过大师是不会这?span>advertising的?/span>

 

?span>Code Complete》第二版

名著?/span>

 

数学Q?/span>

《数学,定性的丧失?span>M.克莱?/span>

原来数学也只不过是hcȝ发明与臆造,用不着供入殿Q想起历史上那么多不食h间烟火的U学Ӟ多半是数学家Q,自以为发C宇宙q作的奥U,是时候走下神坛了?/span>

 

物理Q?/span>

《普通物理学》第一?span> += ?span>Physics for Game Developers?/span>

物理我想到此ؓ此吧Q再复杂我可要用Newton Engine,ODE了,{待物理?span>PPU普及的那天,可充分发挥PhysX的功效了Q看q最新的《细?yu)分裂》游?span>Demo演示Q成千上万个Box疯狂CollideQ骨灰玩家该一Ҏ(gu)钱包一Ҏ(gu)口水了?/span>

 

二、开源代码:

Irrlicht

著名的鬼火引擎,从两q前W一眼看到它Q这个轻量的三l图形引擎,喜Ƣ上了它。源代码优雅Q高效,且不故弄玄虚。值得每个C++E序员一读,q不限于囑Ş~程者。它的周边中也有不少轻量U的东西。如Lightfeather扩展引擎Q?span>ICE?span>IrrlichtRPG?span>IrrWizard.q有IrrEdit?span>IrrKlang?span>IrrXML可用。(可能是ؓ了效率原因,很多开源作者往往喜欢自己?span>XML解析库,如以上的IrrXML?span>,即有现成的tinyXML库可用。这真会?span>tomcat里面?span>AxisQ?span>Axis里面?span>JUDDIQ弄得像俄罗斯套娃玩LJava Web Service Coder们汗颜。)

 

OGRE

排名W一的开源图形引擎,当然规模是很大的Q周边也很多。除了以C#写就?span>OgreStudio Q?span>ofusion嵌入3DS MAX作ؓWYSWYG式的三维~辑器也是棒的Q特别是其几个场景、地形插件值得研究。以至于?span>Pro OGRE 3D Programming》一书专论其用法。搜狐的《天龙八部》游戏就是以其作为图形引擎,当然q另外开发了引擎插块啦。我早知?span>OGRE开发组中有一个中国h谢程序员Q他以前做了很多q的传统软g~程。有一ơ天龙八部游戏的囑Ş模块的出错信息中包含了一串某E序员的工作目录Q有一个文件夹名即是谢E序员的英文名,我据此推断谢E序员即是搜狐北京的ȝ。看来中国对开源事业还是有所贡献的嘛Q王开源哥哥的努力看来不会白费Q(^-^Q不q我侦测的手法也有些像网站数据库爆库了,非君子之所Z?/span>

 

RakNet

ZUDI的网l库Q竟q支持声音传输,以后?span>OpenVisionl合h做个视聊E序试试?/span>

 

Blender

声誉最盛的开源三l动画YӞ竟还带一个游戏引擎。虽然操作以快捷键驱动,也就是说要背上百来个快捷键才能熟l用。但是作Z商业代码变ؓ开源之作,威胁三维商业巨头的轻骑兵Q历l十q锤|代码辄万行Q此代码只应天上有,人间哪得几回看,怎可不作为长期的源码参考?

 

风魂

二维囑Ş库。云风大哥的成名之作。虽然不代表其最高水qI最高水q作为商业代码保存在q州|易互动?span>SVN里呢Q,但是也可以一仰风采了?/span>

 

圣剑英雄?/span>

二维RPG。几个作者已成ؓ成都锦天的主力程序员。锦天的老M一百万发家Q三q时间n仯亿,也是一代枭雄了。这份代码作为几q前的学生作品也可以了Q因Z个工E讲I的是四q_EIq不一定要哪个模块多么出彩。反正我是没有时间写q么一个东东,q个工都找不到Q只能整天想着破解别h的资源(^-^Q?/span>

 

Boost

C++准标准库Q我x多的时候可以参考学习其源代码?/span>

 

Yake

我遇到的最好的轻量U游戏框架了。在以前把一个工E中的图形引擎从Irrlicht换成OGRE的尝试中Q遇C它?span>OGRE的周边工E在我看来都很庸肿,没有完善文档的情况下看v来和Linux内核差不多。不q这?span>Yake引擎倒是很喜Ƣ。它以一?span>FSM有限状态机作ؓ实时E序的调度核心,然后每个模块Q物理、图形、网l、脚本?span>GUI、输入等{都提供一个接口,接口之下再提供到每种具体开源引擎的接口Q然后再接具体引擎。通过q样层层抽象Q此时你是接Newton Engine,ODEq是PysX都可以;是接OGRE,Crystal Spaceq是Irrlicht都可以;是接RakNetq是LibCurl都可以;是接PythonQ?span>Luaq是Ruby都可以,是接CEGUIq是othersQ是?span>OISq是othersQ呵?span>,ChothersQ都可以。所?span>Yake本质上不?span>OGRE的周辏V虽然用Neoengine的h都倒向了它Q但是现在版本还很早。特别是我认为,学习研究时一定要有这U抽象之抽象Q接口之接口的东西把思维从具体的l定打开Q而开发时抽象要有限度的,像蔡学镛在?span>Java夜未眠》中讲的Q面向对象用得过滥也会得OOOO?span>(面向对象q敏?span>)?/span>

 

Quake Doompd

据说很经典,卡马克这U开源的黑客_值得赞许。把商业源代码放出来Q走自己的创C路,让别d。不q?span>Quake?span>Unreal引擎的三l编辑器是现在所有编辑器的E,看来要好好看看了?/span>

 

Nvidia SDK 9.X

三维囑Ş~程的大宝库Q这?span>Diret3D?span>OpenGL的示例程序都是用来展C其最新的昑֍技术的。硬件厂商往往对Y件品不甚在意,源代码给你看,东西l你用去吧,学完了还得买我的g?span>Intel的编译器Q?span>PhysX物理引擎大概也都是这栗?span>Havok会把它的Havok物理引擎免费l别人用吗?别说试用版,q个Demo都看不到。所以这?span>SDK的内容可?span>MS DirectX SDK里面那些入门U的CZ酷多了,反正我是如获臛_Q三月不知愁滋味。不q显卡要so-so哦。我?span>GeForce 6600有两三个跑不q去,差强人意?/span>

 

三、网站:

www.CSDN.net

E序员大本营吧,软文?#8220;新技术秀”讨厌了点Q?span>blog和社区是_֍之所在?/span>

 

www.GameRes.com

游戏E序员基圎ͼ文档库中q有点东ѝ投E的接收?span>Seabug与圣剑英雄传的主E?span>Seabug会是同一个h吗?一个在成都锦天担当技术重担的高手q有旉l护|站吗?我不得而知?/span>

 

“何苦做游?#8221;|站

名字很个性,站长也是历尽几年前业发展初期的艰难才出此名字?/span>

 

www.66rpg.com

二维游戏囄资源很多Q站长柳柳主推的RPGMaker 软g也可以玩一玩吧Q但对于专业开发者来说不可当真?/span>

 

www.GameDev.net

论坛中有不少热心的国外高手在zd?/span>

 

www.SourceForge.net

不用说了Q世界最大的开源代码库Q入金山怎可I手而返Q看到国外那些学生项目动不动像模像L。(DirectX的稚形就是英国的学生目Q在学校q被判ؓ不合根{)

 

www.koders.com

源代码搜索引?span>,支持正则表达?span>,google Lab中也有。当你某U功能写不出来时,可以看一下开源代码怎么写的,当然不过是仅供参?span>,开源代码未必都有品的强度。说?span>google,可看?span>Google Power Tools Bible》一书,你会发现Q?span>google的众多品原来也有这么多使用门道?/span>

 

q篇文写了一天半的时_不由得我对侯捷一L技术作安期伏案辛勤劳作深深敬佩了。看来对于书c或者YӞ都应该尊重作者或?span>programmer的才智劳?/span>



]]>
Q{QC、C++ 旉 http://www.shnenglu.com/Walker/articles/81194.html漫步者?amp;…?K?/dc:creator>漫步者?amp;…?K?/author>Mon, 27 Apr 2009 03:11:00 GMThttp://www.shnenglu.com/Walker/articles/81194.htmlhttp://www.shnenglu.com/Walker/comments/81194.htmlhttp://www.shnenglu.com/Walker/articles/81194.html#Feedback0http://www.shnenglu.com/Walker/comments/commentRss/81194.htmlhttp://www.shnenglu.com/Walker/services/trackbacks/81194.htmlC++ 旉

      本文从介l基概念入手Q探讨了在C/C++中对日期和时间操作所用到的数据结构和函数Qƈ对计时、时间的获取、时间的计算和显C格式等斚wq行了阐q。本文还通过大量的实例向你展CZtime.h头文件中声明的各U函数和数据l构的详l用方法?nbsp; 

关键字:UTCQ世界标准时_QCalendar TimeQ日历时_QepochQ时间点Q,clock tickQ时钟计时单元)  

1Q概?nbsp; 
      在C/C++中,对字W串的操作有很多值得注意的问题,同样QC/C++Ҏ(gu)间的操作也有许多值得大家注意的地斏V最q,在技术群中有很多|友也多ơ问?qC++语言中对旉的操作、获取和昄{等的问题。下面,在这文章中Q笔者将主要介绍在C/C++中时间和日期的用方?  

通过学习许多C/C++库,你可以有很多操作、用时间的Ҏ(gu)。但在这之前你需要了解一?#8220;旉”?#8220;日期”的概念,主要有以下几个:  

Coordinated Universal TimeQUTCQ:协调世界Ӟ又称Z界标准时_也就是大家所熟知的格林威L准时_Greenwich Mean TimeQGMTQ。比如,中国内地的时间与UTC的时差ؓ+8Q也是UTC+8。美国是UTC-5?nbsp; 

Calendar TimeQ日历时_是用“从一个标准时间点到此时的旉l过的秒?#8221;来表C的旉。这个标准时间点对不同的~译器来说会有所不同Q但对一个编译系l来 _q个标准旉Ҏ(gu)不变的,该编译系l中的时间对应的日历旉都通过该标准时间点来衡量,所以可以说日历旉?#8220;相对旉”Q但是无Z在哪一个时区, 在同一时刻对同一个标准时间点来说Q日历时间都是一L?nbsp; 

epochQ?nbsp;   旉炏V时间点在标准C/C++中是一个整敎ͼ它用此时的时间和标准旉点相差的U数Q即日历旉Q来表示?nbsp; 

clock tickQ时钟计时单元(而不把它叫做旉滴答ơ数Q,一个时钟计时单元的旉长短是由CPU控制的。一个clock tick不是CPU的一个时钟周期,而是C/C++的一个基本计时单位?nbsp; 

我们可以使用ANSI标准库中的time.h头文件。这个头文g中定义的旉和日期所使用的方法,无论是在l构定义Q还是命名,都具有明昄C语言风格。下面,我将说明在C/C++中怎样使用日期的时间功能?nbsp; 

2Q?计时  

C/C++中的计时函数是clock()Q而与其相关的数据cd是clock_t。在MSDN中,查得对clock函数定义如下Q?nbsp; 

clock_t clock( void );  

     q?个函数返回从“开启这个程序进E?#8221;?#8220;E序中调用clock()函数”时之间的CPU旉计时单元Qclock tickQ数Q在MSDN中称之ؓ挂钟旉Qwal-clockQ。其中clock_t是用来保存时间的数据cdQ在time.h文g中,我们可以扑ֈ?它的定义Q?nbsp; 

#ifndef _CLOCK_T_DEFINED  
typedef long clock_t;  
#define _CLOCK_T_DEFINED  
#endif  

很明显,clock_t是一个长整Ş数。在time.h文g中,q定义了一个常量CLOCKS_PER_SECQ它用来表示一U钟会有多少个时钟计时单元,其定义如下:  

#define CLOCKS_PER_SEC ((clock_t)1000)  

可以看到每过千分之一U(1毫秒Q,调用clockQ)函数q回的值就?。下面D个例子,你可以用公式clock()/CLOCKS_PER_SEC来计一个进E自w的q行旉Q?nbsp; 

void elapsed_time()  
{  
printf("Elapsed time:%u secs.\n",clock()/CLOCKS_PER_SEC);  
}  

当然Q你也可以用clock函数来计你的机器运行一个@环或者处理其它事件到底花了多时_  

#include “stdio.h”  
#include “stdlib.h”  
#include “time.h”  

int main( void )  
{  
long i = 10000000L;  
clock_t start, finish;  
double duration;  
/* 量一个事件持l的旉*/  
printf( "Time to do %ld empty loops is ", i );  
start = clock();  
while( i-- ) ;  
finish = clock();  
duration = (double)(finish - start) / CLOCKS_PER_SEC;  
printf( "%f seconds\n", duration );  
system("pause");  
}  

在笔者的机器上,q行l果如下Q?nbsp; 

Time to do 10000000 empty loops is 0.03000 seconds  

     上面我们看到旉计时单元的长度ؓ1毫秒Q那么计时的_ֺ也ؓ1毫秒Q那么我们可不可以通过改变CLOCKS_PER_SEC的定义,通过把它定义的大一些,从而计时_ֺ更高呢?通过试Q你会发现这h不行的。在标准C/C++中,最的计时单位是一毫秒?nbsp; 

3Q与日期和时间相关的数据l构  

在标准C/C++中,我们可通过tml构来获得日期和旉Qtml构在time.h中的定义如下Q?nbsp; 

#ifndef _TM_DEFINED  
struct tm {  
int tm_sec; /* U?– 取值区间ؓ[0,59] */  
int tm_min; /* ?- 取值区间ؓ[0,59] */  
int tm_hour; /* ?- 取值区间ؓ[0,23] */  
int tm_mday; /* 一个月中的日期 - 取值区间ؓ[1,31] */  
int tm_mon; /* 月䆾Q从一月开始,0代表一月) - 取值区间ؓ[0,11] */  
int tm_year; /* q䆾Q其值等于实际年份减?900 */  
int tm_wday; /* 星期 – 取值区间ؓ[0,6]Q其?代表星期天,1代表星期一Q以此类?*/  
int tm_yday; /* 从每q的1?日开始的天数 – 取值区间ؓ[0,365]Q其?代表1?日,1代表1?日,以此cL */  
int tm_isdst; /* 夏o时标识符Q实行夏令时的时候,tm_isdst为正。不实行夏o时的q候,tm_isdst?Q不了解情况Ӟtm_isdst()?/  
};  
#define _TM_DEFINED  
#endif  

ANSI C标准UC用tml构的这U时间表CZؓ分解旉(broken-down time)?nbsp; 

      而日历时_Calendar TimeQ是通过time_t数据cd来表C的Q用time_t表示的时_日历旉Q是从一个时间点Q例如:1970q?????U)到此时的U数。在time.h中,我们也可以看到time_t是一个长整型敎ͼ  

#ifndef _TIME_T_DEFINED  
typedef long time_t; /* 旉?*/  
#define _TIME_T_DEFINED /* 避免重复定义 time_t */  
#endif  

      ?家可能会产生疑问Q既然time_t实际上是长整型,到未来的某一天,从一个时间点Q一般是1970q?????U)到那时的U数Q即日历旉Q?出了长整Ş所能表C的数的范围怎么办?对time_t数据cd的值来_它所表示的时间不能晚?038q??8?9?4?7U。ؓ了能够表C?更久q的旉Q一些编译器厂商引入?4位甚x长的整Ş数来保存日历旉。比如微软在Visual C++中采用了__time64_t数据cd来保存日历时_q过_time64()函数来获得日历时_而不是通过使用32位字的time()?敎ͼQ这样就可以通过该数据类型保?001q?????U(不包括该旉点)之前的时间?nbsp; 

在time.h头文件中Q我们还可以看到一些函敎ͼ它们都是以time_t为参数类型或q回值类型的函数Q?nbsp; 

double difftime(time_t time1, time_t time0);  
time_t mktime(struct tm * timeptr);  
time_t time(time_t * timer);  
char * asctime(const struct tm * timeptr);  
char * ctime(const time_t *timer);  

此外Qtime.hq提供了两种不同的函数将日历旉Q一个用time_t表示的整敎ͼ转换为我们^时看到的把年月日时分U分开昄的时间格式tmQ?nbsp; 

struct tm * gmtime(const time_t *timer);  
struct tm * localtime(const time_t * timer);  

      ?q查阅MSDNQ我们可以知道Microsoft C/C++ 7.0中时间点的|time_t对象的|是从1899q?2?1???U到该时间点所l过的秒敎ͼ而其它各U版本的Microsoft C/C++和所有不同版本的Visual C++都是计算的从1970q?????U到该时间点所l过的秒数?nbsp; 

4Q与日期和时间相关的函数及应?nbsp; 
      在本节,我将向大家展C怎样利用time.h中声明的函数Ҏ(gu)间进行操作。这些操作包括取当前旉、计时间间隔、以不同的Ş式显C时间等内容?nbsp; 

4.1 获得日历旉  

       我们可以通过time()函数来获得日历时_Calendar TimeQ,其原型ؓQ?br>time_t time(time_t * timer);  

       ?果你已经声明了参数timerQ你可以从参数timerq回现在的日历时_同时也可以通过q回D回现在的日历旉Q即从一个时间点Q例如:1970q?1????U)到现在此时的U数。如果参CؓI(NULQ,函数只通过q回D回现在的日历旉Q比如下面这个例子用来显C当前的日历旉Q?  

#include "time.h"  
#include "stdio.h"  
int main(void)  
{  
struct tm *ptr;  
time_t lt;  
lt =time(NUL);  
printf("The Calendar Time now is %d\n",lt);  
return 0;  
}  

q行的结果与当时的时间有养I我当时运行的l果是:  

The Calendar Time now is 1122707619  

其中1122707619是我运行程序时的日历时间。即?970q?????U到此时的秒数?nbsp; 

4.2 获得日期和时?nbsp; 

      q里说的日期和时间就是我们^时所说的q、月、日、时、分、秒{信息。从W?节我们已l知道这些信息都保存在一个名为tm的结构体中,那么如何一个日历时间保存ؓ一个tml构的对象呢Q?nbsp; 

其中可以使用的函数是gmtime()和localtime()Q这两个函数的原型ؓQ?nbsp; 

struct tm * gmtime(const time_t *timer);  
struct tm * localtime(const time_t * timer);  

       ?中gmtime()函数是将日历旉转化Z界标准时_x林尼L_Qƈq回一个tml构体来保存q个旉Q而localtime()函数是将日历 旉转化为本地时间。比如现在用gmtime()函数获得的世界标准时间是2005q??0??8?0U,那么我用localtime()函数?中国地区获得的本地时间会比世界标准时间晚8个小Ӟ?005q??0?5?8?0U。下面是个例子:  

#include "time.h"  
#include "stdio.h"  
int main(void)  
{  
struct tm *local;  
time_t t;  
t=time(NUL);  
local=localtime(&t);  
printf("Local hour is: %d\n",local->tm_hour);  
local=gmtime(&t);  
printf("UTC hour is: %d\n",local->tm_hour);  
return 0;  
}  

q行l果是:  

Local hour is: 15  
UTC hour is: 7  

4.3 固定的时间格?nbsp; 

      我们可以通过asctime()函数和ctime()函数时间以固定的格式显C出来,两者的q回值都是char*型的字符丌Ӏ返回的旉格式为:  

星期?月䆾 日期 ??U?q\n\0  
例如QWed Jan 02 02:03:55 1980\n\0  

其中\n是一个换行符Q\0是一个空字符Q表C字W串l束。下面是两个函数的原型:  

char * asctime(const struct tm * timeptr);  
char * ctime(const time_t *timer);  

      ?中asctime()函数是通过tml构来生成具有固定格式的保存旉信息的字W串Q而ctime()是通过日历旉来生成时间字W串。这L话, asctimeQ)函数只是把tml构对象中的各个域填到时间字W串的相应位|就行了Q而ctimeQ)函数需要先参照本地的时间设|,把日历时间{化ؓ 本地旉Q然后再生成格式化后的字W串。在下面Q如果t是一个非I的time_t变量的话Q那么:  

printf(ctime(&t));  

{h(hun)于:  

struct tm *ptr;  
ptr=localtime(&t);  
printf(asctime(ptr));  

那么Q下面这个程序的两条printf语句输出的结果就是不同的了(除非你将本地时区设ؓ世界标准旉所在的时区Q:  

#include "time.h"  
#include "stdio.h"  
int main(void)  
{  
struct tm *ptr;  
time_t lt;  
lt =time(NUL);  
ptr=gmtime(<);  
printf(asctime(ptr));  
printf(ctime(<));  
return 0;  
}  

q行l果Q?nbsp; 

Sat Jul 30 08:43:03 2005  
Sat Jul 30 16:43:03 2005  

4.4 自定义时间格?nbsp; 

我们可以使用strftimeQ)函数时间格式化为我们想要的格式。它的原型如下:  

size_t strftime(  
char *strDest,  
size_t maxsize,  
const char *format,  
const struct tm *timeptr  
);  
      我们可以Ҏ(gu)format指向字符串中格式命o把timeptr中保存的旉信息攑֜strDest指向的字W串中,最多向strDest中存放maxsize个字W。该函数q回向strDest指向的字W串中放|的字符数?nbsp; 

      ?数strftime()的操作有些类gsprintf()Q识别以癑ֈ?%)开始的格式命o集合Q格式化输出l果攑֜一个字W串中。格式化命o说明?strDest中各U日期和旉信息的确切表C方法。格式串中的其他字符原样放进串中。格式命令列在下面,它们是区分大写的?nbsp; 

%a 星期几的?nbsp; 
%A 星期几的全称  
%b 月分的简?nbsp; 
%B 月䆾的全U?nbsp; 
%c 标准的日期的旉?nbsp; 
%C q䆾的后两位数字  
%d 十进制表C的每月的第几天  
%D ??q?nbsp; 
%e 在两字符域中Q十q制表示的每月的W几?nbsp; 
%F q???nbsp; 
%g q䆾的后两位数字Q用基于周的年  
%G q分Q用基于周的年  
%h 写的月䆾?nbsp; 
%H 24时制的时  
%I 12时制的时  
%j 十进制表C的每年的第几天  
%m 十进制表C的月䆾  
%M 十时制表C的分钟?nbsp; 
%n 新行W?nbsp; 
%p 本地的AM或PM的等hC?nbsp; 
%r 12时的时?nbsp; 
%R 昄时和分钟:hh:mm  
%S 十进制的U数  
%t 水^制表W?nbsp; 
%T 昄时分U:hh:mm:ss  
%u 每周的第几天Q星期一为第一?Qg0?Q星期一?Q?nbsp; 
%U W年的第几周Q把星期日做为第一天(g0?3Q?nbsp; 
%V 每年的第几周Q用基于周的年  
%w 十进制表C的星期几(g0?Q星期天?Q?nbsp; 
%W 每年的第几周Q把星期一做ؓW一天(g0?3Q?nbsp; 
%x 标准的日期串  
%X 标准的时间串  
%y 不带世纪的十q制q䆾Qg0?9Q?nbsp; 
%Y 带世U部分的十进制年?nbsp; 
%zQ?Z 时区名称Q如果不能得到时区名U则q回I字W?nbsp; 
%% 癑ֈ?nbsp; 

如果xC现在是几点了,q以12时制显C,p下面q段E序Q?nbsp; 

#include “time.h”  
#include “stdio.h”  
int main(void)  
{  
struct tm *ptr;  
time_t lt;  
char str[80];  
lt=time(NUL);  
ptr=localtime(<);  
strftime(str,100,"It is now %I %p",ptr);  
printf(str);  
return 0;  
}  

其运行结果ؓQ?nbsp; 
It is now 4PM  

而下面的E序则显C当前的完整日期Q?nbsp; 

#include <stdio.h>  
#include <time.h>  

void main( void )  
{  
struct tm *newtime;  
char tmpbuf[128];  
time_t lt1;  
time( <1 );  
newtime=localtime(<1);  
strftime( tmpbuf, 128, "Today is %A, day %d of %B in the year %Y.\n", newtime);  
printf(tmpbuf);  
}  

q行l果Q?nbsp; 

Today is Saturday, day 30 of July in the year 2005.  

4.5 计算持箋旉的长?nbsp; 

      有时候在实际应用中要计算一个事件持l的旉长度Q比如计打字速度。在W?节计旉分中Q我已经用clock函数举了一个例子。Clock()函数可以_到毫U。同Ӟ我们也可以用difftime()函数Q但它只能精到U。该函数的定义如下:  

double difftime(time_t time1, time_t time0);  

      虽然该函数返回的以秒计算的时间间隔是doublecd的,但这q不说明该时间具有同double一L_度,q是由它的参数觉得的Qtime_t是以Uؓ单位计算的)。比如下面一D늨序:  

#include "time.h"  
#include "stdio.h"  
#include "stdlib.h"  
int main(void)  
{  
time_t start,end;  
start = time(NUL);  
system("pause");  
end = time(NUL);  
printf("The pause used %f seconds.\n",difftime(end,start));//<-  
system("pause");  
return 0;  
}  

q行l果为:  
hL键l? . .  
The pause used 2.000000 seconds.  
hL键l? . .  

      可以惛_Q暂停的旉q不那么巧是整整2U钟。其实,你将上面E序的带?#8220;//<-”注释的一行用下面的一行代码替换:  

printf("The pause used %f seconds.\n",end-start);  

其运行结果是一L?nbsp; 

4.6 分解旉转化为日历时?nbsp; 

      q里说的分解旉是以年、月、日、时、分、秒{分量保存的旉l构Q在C/C++中是tml构。我们可以用mktimeQ)函数用tml构表示的时间{化ؓ日历旉。其函数原型如下Q?nbsp; 

time_t mktime(struct tm * timeptr);  

其返回值就是{化后的日历时间。这h们就可以先制定一个分解时_然后对这个时间进行操作了Q下面的例子可以计算?997q??日是星期几:  

#include "time.h"  
#include "stdio.h"  
#include "stdlib.h"  
int main(void)  
{  
struct tm t;  
time_t t_of_day;  
t.tm_year=1997-1900;  
t.tm_mon=6;  
t.tm_mday=1;  
t.tm_hour=0;  
t.tm_min=0;  
t.tm_sec=1;  
t.tm_isdst=0;  
t_of_day=mktime(&t);  
printf(ctime(&t_of_day));  
return 0;  
}  
q行l果Q?nbsp; 
Tue Jul 01 00:00:01 1997  
     现在注意了,有了mktime()函数Q是不是我们可以操作现在之前的Q何时间呢Q你可以通过q种办法出1945q??5h星期几吗Q答案是否定的。因个时间在1970q??日之前,所以在大多数编译器中,q样的程序虽然可以编译通过Q但q行时会异常l止?
5Qȝ
本文介绍了标准C/C++中的有关日期和时间的概念Qƈ通过各种实例讲述了这些函数和数据l构的用方法。笔者认为,和时间相关的一些概忉|相当重要的,理解q些概念是理解各U时间格式的转换的基Q更是应用这些函数和数据l构的基?/p>



]]>
Q{Q?排序法ȝhttp://www.shnenglu.com/Walker/articles/81101.html漫步者?amp;…?K?/dc:creator>漫步者?amp;…?K?/author>Sun, 26 Apr 2009 02:19:00 GMThttp://www.shnenglu.com/Walker/articles/81101.htmlhttp://www.shnenglu.com/Walker/comments/81101.htmlhttp://www.shnenglu.com/Walker/articles/81101.html#Feedback0http://www.shnenglu.com/Walker/comments/commentRss/81101.htmlhttp://www.shnenglu.com/Walker/services/trackbacks/81101.html学的排序法有:插入排序Q合q排序,冒排序Q选择排序Q希排序,堆排序,快速排序,计数排序Q基数排序,桶排序(没有实现Q。比较一下学习后的心得?br>我不是很清楚他们的时间复杂度Q也真的不知道他们到底谁快谁慢,因ؓ书上的推导我实只是小了解Qƈ没有消化。也没有完全理解他们的精髓,所以又什么错误的q需要高手指炏V呵c?br>1.普及一下排序稳定,所谓排序稳定就是指Q如果两个数相同Q对他们q行的排序结果ؓ他们的相寚w序不变。例如A={1,2,1,2,1}q里排序之后是A = {1,1,1,2,2} E_是排序后第一?是排序前的W一?Q第二个1是排序前第二个1Q第三个1是排序前的W三?。同?也是一栗这里用颜色标明了。不E_呢就是他们的序不应和开始顺序一致。也是可能会是A={1,1,1,2,2}q样的结果?br>2.普及一下原地排序:原地排序是指不甌多余的空间来q行的排序,是在原来的排序数据中比较和交换的排序。例如快速排序,堆排序等都是原地排序Q合q排序,计数排序{不是原地排序?br>3.感觉谁最好,在我的印象中快速排序是最好的Q时间复杂度Qn*log(n)Q不E_排序。原地排序。他的名字很,快速嘛。当然快了。我觉得他的思想很不错,分治Q而且q是原地排序Q省d很多的空间浪贏V速度也是很快的,n*log(n)。但是有一个Y肋就是如果已l是排好的情况下旉复杂度就是n*n,不过在加入随机的情况下这U情况也得以好{Q而且他可以做L的比较,只要你能l出两个元素的大关pd可以了。适用范围q,速度快?br>4.插入排序Qn*n的时间复杂度Q稳定排序,原地排序。插入排序是我学的第一个排序,速度q是很快的,特别是在数组已排好了之后Q用它的思想来插入一个数据,效率是很高的。因Z用全部排。他的数据交换也很少Q只是数据后U,然后攑օ要插入的数据。(q里不是指调用插入排序,而是用它的思想Q。我觉得Q在数据大部分都排好了,用插入排序会l你带来很大的方ѝ数据的Ud和交换都很少?br>5.冒排序Qn*n的时间复杂度Q稳定排序,原地排序。冒泡排序的思想很不错,一个一个比较,把小的上U,依次定当前最元素。因Z单,E_排序Q而且好实玎ͼ所以用处也是比较多的。还有一点就是加上哨兵之后他可以提前退出?br>6.选择排序Qn*n的时间复杂度Q?E_排序Q原地排序。选择排序是冒的基本思想Q从的定位Q一个一个选择Q直到选择l束。他和插入排序是一个相反的q程Q插入是定一个元素的位置Q而选择是确定这个位|的元素。他的好处就是每ơ只选择定的元素,不会对很多数据进行交换。所以在数据交换量上应该比冒泡小?br>7.插入排序Q选择排序Q冒泡排序的比较Q他们的旉复杂度都是n*n。我觉得他们的效率也是差不多的,我个人喜Ƣ冒泡一些,因ؓ要用它的时候数据多半不多,而且可以提前的返回已l排序好的数l。而其他两个排序就已l排好了Q他也要做全部的扫描。在数据的交换上Q冒泡的比他们都多。呵cD例说明插入一个数据在末尾后排序,冒只要一ơ就能搞定,而选择和插入都必须要n*n的复杂度才能搞定。就看你怎么看待咯?br>8.合ƈ排序Qn*log(n)的时间复杂度Q?E_排序Q非原地排序。他的思想是分治,先分成小的部分,排好部分之后合ƈQ因为我们另外申LI间Q在合ƈ的时候效率是0(n)的。速度很快。貌g的上限是n*log(n)Q所以如果说是比较的ơ数的话Q他比快速排序要一些。对L的数l都能有效地在n*log(n)排好序。但是因Z是非原地排序Q所以虽然他很快Q但是貌g的h气没有快速排序高?br>9.堆排序:n*log(n)的时间复杂度Q?非稳定排序,原地排序。他的思想是利用的堆这U数据结构,堆可以看成一个完全二叉树Q所以在排序中比较的ơ数可以做到很少。加上他也是原地排序Q不需要申请额外的I间Q效率也不错。可是他的思想感觉比快速难掌握一些。还有就是在已经排好序的基础上添加一个数据再排序Q他的交换次数和比较ơ数一炚w不会减少。虽然堆排序在用的中没有快速排序广泛,但是他的数据l构和思想真的很不错,而且用它来实C先队列,效率没得说。堆Q还是要好好学习掌握的?br>10.希尔排序Qn*log(n)的时间复杂度(q里是错误的Q应该是n^lamda(1 < lamda < 2), lamda和每ơ步镉K择有关?Q?非稳定排序,原地排序。主要思想是分治,不过他的分治和合q排序的分治不一P他是按步长来分组的,而不是想合ƈ那样左一半右一半。开始步长ؓ整个的长度的一半。分成nLen/2个组Q然后每l排序。接个步长减为原来的一半在分组排序Q直到步长ؓ1Q排序之后希排序就完成了。这个思\很好Q据说是插入排序的升U版Q所以在实现每组排序的时候我故意用了插入排序。我觉得他是一个特别好的排序方法了。他的缺点就是两个数可能比较多次Q因Z个数据会多次分不q他们不会出现数据的交换。效率也是很高的?br>11.快速排序,堆排序,合ƈ排序Q希排序的比较Q他们的旉复杂的都是n*log(n)Q我认ؓ在用上快速排序最q泛Q他原地排序Q虽然不E_Q可是很多情况下排序Ҏ(gu)׃在意他是否稳定。他的比较次数是比较?yu)的Q因Z把数据分成了大和的两部分。每ơ都定了一个数的位|,所以理Z说不会出C个数比较两次的情况,也是在最后在交换数据Q说以数据交换上也很。合q排序和堆排序也有这些优点,但是合ƈ排序要申请额外的I间。堆排序堆已l排好的数据交换上比快速多。所以目前快速排序用的要q泛的多。还有他很容易掌握和实现?br>12.计数排序Qn的时间复杂度Q稳定排序,非原地排序。他的思想比较新颖Q就是先U定数据的范围不是很大,而且数据都是整数(或能定位到整?的情况,然后直接甌一个空间。把要排序的数组A的元素g甌I间B的下标对应,然后B中存放该下标元素值的个数Q从而直接定位A中每个元素的位置。这h率只为n。因为比较很Ҏ(gu)Q虽然很快,但是用的地方q不多?br>13.基数排序Qn的时间复杂度Q稳定排序,非原地排序。他的思想是数据比较集中在一个范_例如都是4位数Q都?位数Q或数据有多个关键字Q我们先从各位开始排Q然后排十位Q依ơ排到最高位Q因为我们可以用一个n的方法排一位,所以ȝҎ(gu)为d*n的复杂度。关键字也一P我们先排W?个关键字Q在排第3个关键字Q最后排W一个关键字。只有能保证每个关键字在n的时间复杂度完成Q那么整个排序就是一个d*n的时间复杂度。所以ȝ速度是很快的。不q有一点就是要保关键字能在n的时间复杂度完成?br>14.桶排序:n的时间复杂度Q稳定排序,非原地排序。主要思\和基数排序一P也是假设都在一个范围例如概率都?-1Q而且分布q挺均匀Q那么我们也是和基数排序一样对一个数把他划分在他指定的区域。然后在q接q些区域可以了。书上对每个区域使用链表的存储,我认为在寸小区域的时候也会有旉在里面。所以只是理Z的n旉复杂度。这U思\是不错的。呵c?br>15.计数排序Q基数排序,桶排序的比较Q我觉得他们都很有思想Q不q都是在特定情况下才能发挥最大的效果。虽然效率很高,但是用的不会很广泛。他们之间我更喜Ƣ计数排序,来个映射的方式就直接扑ֈ了自q位置Q很高明。和基数排序和同排序只是理论上的n旉复杂度,基数排序要确定一个关键字的排序是n复杂度的Q桶排序要确定每个区域的排序是n复杂度的?br>16.排序法的最后感(zhn):黑格说q:存在卛_理。所以这些排序的法都是很好的,他确实给了我们思想上的帮助。感谢前人把_֍留给了我们。我得到的收获很大,ȝ一下各自排序的收获Q?br>冒Q好实现Q速度不慢Q用于轻量U的数据排序?br>插入排序Q也使用于小数据的排序,但是我从他的思想中学到怎么插入一个数据。呵呵,q样q道在排好的数据里面,不用再排序了Q而是直接调用一下插入就可以了?br>选择排序Q我学会了怎么去获得最大|最值等Ҏ(gu)。只要选择一下,不就可以了?br>合ƈ排序Q我学会分而治之的Ҏ(gu)Q而且在合q两个数l的时候很适用?br>堆排序:可以用它来实C先队列,而且他的思想应该l我加了很多内力?br>快速排序:本来q的最多的排序Q对我的帮助大的都不知道怎么说好?br>希尔排序Q也是分治,让我看到了分ȝ不同Q原来还有这U思想的存在?br>计数排序Q基数排序,桶排序:Ҏ(gu)情况Ҏ(gu)处理?br>附上我学习这里排序的q接

快速排序学?            快速排序学?Q随机化版本Q?/a>

快速排序学?Q最初版Q?/a>  快速排序学?Q最初版加随机版Q?/a>

插入排序   冒排序    选择排序

希尔排序   合ƈ排序  堆排?/a>  用堆实现优先队列

基数排序  计数排序

posted on 2009-04-25 19:30 shongbee2 阅读(313) 评论(5)  ~辑 收藏 引用 所属分c? 数据l构和算?/font>

评论

# re: 排序法ȝ[未登录] 2009-04-25 22:10 R

shell sort 复杂度是n^lamda, lamda是大?于2的实? qnlogn.   回复  更多评论   

# re: 排序法ȝ 2009-04-26 00:30 shongbee2

@R
哦。谢谢,原来跟lamda有关pd。呵呵,因ؓ我每ơ都是折半,所以就误认为是nlogn了。嘻嘻,谢谢哈?nbsp; 回复  更多评论   



]]>
E序员应该读的论?/title><link>http://www.shnenglu.com/Walker/articles/81018.html</link><dc:creator>漫步者?amp;…?K?/dc:creator><author>漫步者?amp;…?K?/author><pubDate>Sat, 25 Apr 2009 02:41:00 GMT</pubDate><guid>http://www.shnenglu.com/Walker/articles/81018.html</guid><wfw:comment>http://www.shnenglu.com/Walker/comments/81018.html</wfw:comment><comments>http://www.shnenglu.com/Walker/articles/81018.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/Walker/comments/commentRss/81018.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/Walker/services/trackbacks/81018.html</trackback:ping><description><![CDATA[<p>a归正传,看看是哪10论文入了Feathers大师的法眼吧Q?/p> <ol> <li><a ><font color=#336699>On the criteria to be used in decomposing systems into modules</font></a> – David Parnas <li><a ><font color=#336699>A Note On Distributed Computing</font></a> – Jim Waldo, Geoff Wyant, Ann Wollrath, Sam Kendall <li><a ><font color=#336699>The Next 700 Programming Languages</font></a> – P. J. Landin <li><a ><font color=#336699>Can Programming Be Liberated from the von Neumann Style?</font></a> – John Backus <li><a ><font color=#336699>Reflections on Trusting Trust</font></a> – Ken Thompson <li><a ><font color=#336699>Lisp: Good News, Bad News, How to Win Big</font></a> – Richard Gabriel <li><a ><font color=#336699>An experimental evaluation of the assumption of independence in multiversion programming</font></a> – John Knight and Nancy Leveson <li><a ><font color=#336699>Arguments and Results</font></a> – James Noble <li><a ><font color=#336699>A Laboratory For Teaching Object-Oriented Thinking</font></a> – Kent Beck, Ward Cunningham <li><a ><font color=#336699>Programming as an Experience: the inspiration for Self</font></a> – David Ungar, Randall B. Smith </li> </ol> <p>Feathers的文章显然成了这几天|上的热门话题,我们另外一本已l获得版权的书《SOA Patterns》(ManningQ?009Q的作者Arnon Rotem-Gal-Oz受他启发Q写?a ><font color=#336699>“所有架构师都应该至读上两遍的十篇论文”</font></a>Q?/p> <p>1. <a ><font color=#336699>The Byzantine Generals Problem</font></a> (1982) by Leslie Lamport, Robert Shostak and Marshall Pease<br>2. <a ><font color=#336699>Go To statements considered harmfull</font></a> (1968) - by Edsger W. Dijkstra <br>3.<a ><font color=#336699> A Note on Distributed Computing</font></a> (1994) - by Samuel C. Kendall, Jim Waldo, Ann Wollrath and Geoff Wyant <br>4. <a ><font color=#336699>Big Ball of Mud</font></a> (1999) - Brian Foote and Joseph Yoder <a ><br></a>5. <a ><font color=#336699>No Silver Bullet Essence and Accidents of Software Engineering</font></a> (1987) - Frederick P. Brooks <br>6. <a ><font color=#336699>The Open Closed Principle</font></a> (1996) - Robert C. Martin (Uncle Bob) <br>7. <a ><font color=#336699>IEEE1471-2000 A recommended practice for architectural description of software intensive systems</font></a> (2000) <br>8. <a ><font color=#336699>Harvest, Yield, and Scalable Tolerant Systems</font></a> (1999) Armando Fox, Eric A. Brewer <br>9. <a ><font color=#336699>An Introduction to Software Architecture</font></a> (1993) - David Garlan and Mary Shaw <br>10. <a ><font color=#336699>Who Needs an Architect?</font></a> (2003) Martin Fowler </p> <img src ="http://www.shnenglu.com/Walker/aggbug/81018.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/Walker/" target="_blank">漫步者?…?K?/a> 2009-04-25 10:41 <a href="http://www.shnenglu.com/Walker/articles/81018.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Q{QA*法入门http://www.shnenglu.com/Walker/articles/80564.html漫步者?amp;…?K?/dc:creator>漫步者?amp;…?K?/author>Mon, 20 Apr 2009 12:29:00 GMThttp://www.shnenglu.com/Walker/articles/80564.htmlhttp://www.shnenglu.com/Walker/comments/80564.htmlhttp://www.shnenglu.com/Walker/articles/80564.html#Feedback0http://www.shnenglu.com/Walker/comments/commentRss/80564.htmlhttp://www.shnenglu.com/Walker/services/trackbacks/80564.html在看下面q篇文章之前Q先介绍几个理论知识Q有助于理解A*法?/span>

 

启发式搜?/span>Q启发式搜烦是在状态空间中的搜索对每一个搜索的位置q行评估Q得到最好的位置Q再从这个位|进行搜索直到目标。这样可以省略大量无畏的搜烦路径Q提C效率。在启发式搜索中Q对位置的估h十分重要的。采用了不同的估价可以有不同的效果?/span>

Ch(hun)函数Q从当前节点Ud到目标节点的预估费用Q这个估计就是启发式的。在寻\问题和迷宫问题中Q我们通常用曼哈顿Q?span>manhattanQ估价函敎ͼ下文有介l)预估费用?/span>

A*法?span>BFSQ可以这栯Q?span>BFS?span>A*法的一个特例。对于一?span>BFS法Q从当前节点扩展出来的每一个节点(如果没有被访问过的话Q都要放q队列进行进一步扩展。也是?span>BFS的估计函?span>h永远{于0Q没有一点启发式的信息,可以认ؓBFS?#8220;最烂的”A*法?/span>

选取最估P如果学过数据l构的话Q应该可以知道,对于每次都要选取最估L节点Q应该用到最优先队列Q也叫最二叉堆Q。在C++?span>STL里有现成的数据结?span>priority_queueQ可以直接用。当然不要忘了重载自定义节点的比较操作符?/span>

A*法的特点:A*法在理Z是时间最优的Q但是也有缺点:它的I间增长是指数别的?/span>

IDA*法Q?/span>q种法被称P代加?span>A*法Q可以有效的解决A*I间增长带来的问题,甚至可以不用C先队列。如果要知道详细Q?span>google一下?/span>


 

A*寻\初探Q{载)

 

作者:Patrick Lester

译者:Panic2005q?/span>

 

译者序Q很久以前就知道?span>A*法Q但是从未认真读q相关的文章Q也没有看过代码Q只是脑子里有个模糊的概c这ơ决定从头开始,研究一下这个被人推崇备至的单方法,作ؓ学习人工的开始?/span>

q篇文章非常知名Q国内应该有不少人翻译过它,我没有查找,觉得译本n也是对自w英文水q的ȝ。经q努力,l于完成了文档,也明白的A*法的原理。毫无疑问,作者用形象的描qͼz诙谐的语言由浅入深的讲qCq一奇的算法,怿每个读过的h都会Ҏ(gu)有所认识Q如果没有,那就是偶的翻译太差了--bQ?/span>

现在是年月日的版本,应原作者要求,Ҏ(gu)中的某些法l节做了修改?/span>

原文链接Q?span>http://www.gamedev.net/reference/articles/article2003.asp

原作者文章链接:http://www.policyalmanac.org/games/aStarTutorial.htm

以下是翻译的正文

会者不难,A*(念作A?span>)法对初学者来说的有些难度。这文章ƈ不试囑֯q个话题作权威的陈述。取而代之的是,它只是描q算法的原理Q你可以在q一步的阅读中理解其他相关的资料。最后,q篇文章没有E序l节。你可以用L的计机E序语言实现它。如你所愿,我在文章的末֌含了一个指向例子程序的链接。压~包包括C++?span>Blitz Basic两个语言的版本,如果你只是想看看它的q行效果Q里面还包含了可执行文g。我们正在提高自己。让我们从头开始。。?/span>

 

序:搜烦区域

假设有h想从A点移动到一墙之隔的B点,如下图,l色的是LAQ红色是l点BQ蓝色方块是中间的墙?/span>

[?span>-1]

你首先注意到Q搜索区域被我们划分成了方Ş|格。像q样Q简化搜索区域,是寻路的W一步。这一Ҏ(gu)把搜索区域简化成了一个二l数l。数l的每一个元素是|格的一个方块,方块被标Cؓ可通过的和不可通过的。\径被描述ZA?span>B我们l过的方块的集合。一旦\径被扑ֈQ我们的人就从一个方格的中心走向另一个,直到到达目的地?/span>

q些中点被称?/span>节点。当你阅d他的寻\资料Ӟ你将l常会看Ch们讨炏Vؓ什么不把他们描qCؓҎ(gu)呢?因ؓ有可能你的\径被分割成其他不是方格的l构。他们完全可以是矩ŞQ六角ŞQ或者其他Q意Ş状。节点能够被攄在Ş状的L位置Q可以在中心Q或者沿着边界Q或其他什么地斏V我们用这U系l,无论如何Q因为它是最单的?/span>

开始搜?/span>

正如我们处理上图|格的方法,一旦搜索区域被转化为容易处理的节点Q下一步就是去引导一ơ找到最短\径的搜烦。在A*寻\法中,我们通过从点A开始,查相L格的方式Q向外扩展直到找到目标?/span>

我们做如下操作开始搜索:

 

   1Q从?span>A开始,q且把它作ؓ待处理点存入一?/span>开启列?/span>。开启列表就像一张购物清单。尽现在列表里只有一个元素,但以后就会多h。你的\径可能会通过它包含的Ҏ(gu)Q也可能不会。基本上Q这是一个待查方格的列表?/span>

   2Q寻找v点周围所有可到达或者可通过的方|跌有墙Q水Q或其他无法通过地Ş的方根{也把他们加入开启列表。ؓ所有这些方g存点A作ؓ父方?/span>。当我们xq\径的时候,父方格的资料是十分重要的。后面会解释它的具体用途?/span>

   3Q从开启列表中删除?span>AQ把它加入到一?/span>关闭列表Q列表中保存所有不需要再ơ检查的Ҏ(gu)。在q一点,你应该Ş成如囄l构。在图中Q暗l色Ҏ(gu)是你起始Ҏ(gu)的中心。它被用蓝色描边,以表C它被加入到关闭列表中了。所有的盔R格现在都在开启列表中Q它们被用浅l色描边。每个方格都有一个灰色指针反指他们的父方|也就是开始的Ҏ(gu)?/span>

[?span>-2]

接着Q我们选择开启列表中的͘q方|大致重复前面的过E,如下。但是,哪个Ҏ(gu)是我们要选择的呢Q是那个F值最低的?/span>

路径评分

选择路径中经q哪个方格的关键是下面这个等式:F = G + H

q里Q?/span>

    * G = 从v?span>AQ沿着产生的\径,Ud到网g指定Ҏ(gu)的移动耗费?/span>

    * H = 从网g那个Ҏ(gu)Ud到终?span>B的预估移动耗费。这l常被称为启发式的,可能会让你有点迷惑。这样叫的原因是因ؓ它只是个猜测。我们没办法事先知道路径的长度,因ؓ路上可能存在各种障碍(墙,_{等)。虽然本文只提供了一U计?span>H的方法,但是你可以在|上扑ֈ很多其他的方法?/span>

我们的\径是通过反复遍历开启列表ƈ且选择h最?span>F值的Ҏ(gu)来生成的。文章将对这个过E做更详l的描述。首先,我们更深入的看看如何计算q个方程?/span>

正如上面所_G表示沿\径从L到当前点的移动耗费。在q个例子里,我们令水qx者垂直移动的耗费为,对角U方向耗费为。我们取q些值是因ؓ沿对角线的距L沿水qx垂直Ud耗费的的根号Q别怕)Q或者约.414倍。ؓ了简化,我们用和q似。比例基本正,同时我们避免了求根运和数。这不是只因为我们怕麻烦或者不喜欢数学。用这L整数对计机来说也更快捷。你不就׃发现Q如果你不用这些简化方法,寻\会变得很慢?/span>

既然我们在计沿特定路径通往某个Ҏ(gu)?span>G|求值的Ҏ(gu)是取它父节点的G|然后依照它相对父节点是对角线方向或者直角方?span>(非对角线)Q分别增加和。例子中q个Ҏ(gu)的需求会变得更多Q因为我们从LҎ(gu)以外获取了不止一个方根{?/span>

H值可以用不同的方法估。我们这里用的Ҏ(gu)被称为曼哈顿Ҏ(gu)Q它计算从当前格到目的格之间水^和垂直的Ҏ(gu)的数量dQ忽略对角线方向Q然后把l果乘以10。这被称为曼哈顿Ҏ(gu)是因为它看v来像计算城市中从一个地方到另外一个地方的街区敎ͼ在那里你不能沿对角线方向I过街区。很重要的一点,我们忽略了一切障物。这是对剩余距离的一个估,而非实际|q也是这一Ҏ(gu)被称为启发式的原因。想知道更多Q你可以在这里找到方E和额外的注解?/span>

F的值是G?span>H的和。第一步搜索的l果可以在下面的图表中看到?span>F,G?span>H的评分被写在每个Ҏ(gu)里。正如在紧挨起始格右侧的Ҏ(gu)所表示的,F被打印在左上角,G在左下角Q?span>H则在右下角?/span>

[?span>-3]

现在我们来看看这些方根{写字母的方格里Q?span>G = 10。这是因为它只在水^方向偏离起始g个格距。紧邻v始格的上方,下方和左边的Ҏ(gu)?span>G值都{于。对角线方向?span>G值是?/span>

H值通过求解到红色目标格的曼哈顿距离得到Q其中只在水q_垂直方向UdQƈ且忽略中间的墙。用q种Ҏ(gu)Qv点右侧紧ȝҎ(gu)ȝ色方格有D,H值就是。这块方g方的Ҏ(gu)有格距离(CQ只能在水^和垂直方向移?span>)Q?span>H值是。你大致应该知道如何计算其他Ҏ(gu)?span>Hg~。每个格子的F|q是单的?span>G?span>H相加得到

l箋搜烦

Zl箋搜烦Q我们简单的从开启列表中选择F值最低的Ҏ(gu)。然后,寚w中的方格做如下处理Q?/span>

   4Q把它从开启列表中删除Q然后添加到关闭列表中?/span>

   5Q检查所有相L子。蟩q那些已l在关闭列表中的或者不可通过?span>(有墙Q水的地形,或者其他无法通过的地?span>)Q把他们dq开启列表,如果他们q不在里面的话。把选中的方g为新的方格的父节炏V?/span>

   6Q如果某个相L已经在开启列表里了,查现在的q条路径是否更好。换句话_查如果我们用新的路径到达它的话,G值是否会更低一些。如果不是,那就什么都不做?/span>

      另一斚wQ如果新?span>G值更低,那就把相L格的父节Ҏ(gu)为目前选中的方|在上面的图表中,把箭头的方向改ؓ指向q个Ҏ(gu)Q。最后,重新计算F?span>G的倹{如果这看v来不够清晎ͼ你可以看下面的图C?/span>

好了Q让我们看看它是怎么q作的。我们最初的格方gQ在L被切换到关闭列表中后Q还剩格留在开启列表中。这里面Q?span>F值最低的那个是v始格右侧紧邻的格子,它的F值是。因此我们选择q一gZ一个要处理的方根{在紧随的图中,它被用蓝色突出显C?/span>

[?span>-4]

首先Q我们把它从开启列表中取出Q放入关闭列?span>(q就是他被蓝色突出显C的原因)。然后我们检查相ȝ格子。哦Q右侧的格子是墙Q所以我们略q。左侧的格子是v始格。它在关闭列表里Q所以我们也跌它?/span>

其他格已l在开启列表里了,于是我们?span>G值来判定Q如果通过q一格到N里,路径是否更好。我们来看选中格子下面的方根{它?span>G值是。如果我们从当前格移动到那里Q?span>G值就会等?span>(到达当前格的G值是Q移动到上面的格子将使得G值增?span>)。因?span>G值大于,所以这不是更好的\径。如果你看图Q就能理解。与光过先水q移动一|再垂直移动一|q不如直接沿对角U方向移动一格来得简单?/span>

当我们对已经存在于开启列表中的个临近格重复这一q程的时候,我们发现没有一条\径可以通过使用当前格子得到改善Q所以我们不做Q何改变。既然我们已l检查过了所有邻q格Q那么就可以UdC一g?/span>

于是我们索开启列表,现在里面只有7gQ我们仍焉择其中F值最低的。有的是,q次Q有两个格子的数值都是。我们如何选择Q这q不ȝ。从速度上考虑Q选择最后添加进列表的格子会更快捗这U导致了寻\q程中,在靠q目标的时候,优先使用新找到的格子的偏好。但q无关紧要。(对相同数值的不同对待Q导致不同版本的A*法扑ֈ{长的不同\径)那我们就选择起始格右下方的格子,如图Q?/span>

[?span>-5]

q次Q当我们查相L的时候,发现右侧是墙Q于是略q。上面一g被略q。我们也略过了墙下面的格子。ؓ什么呢Q因Z不能在不I越墙角的情况下直接到达那个格子。你的确需要先往下走然后到达那一|按部q的走q那个拐角?span>(注解Q穿拐角的规则是可选的。它取决于你的节Ҏ(gu)如何攄的?span>)

q样一来,剩下了其他根{当前格下面的另外两个格子目前不在开启列表中Q于是我们添加他们,q且把当前格指定Z们的父节炏V其余格Q两个已l在关闭列表中(起始|和当前格上方的格子,在表g蓝色高亮昄),于是我们略过它们。最后一|在当前格的左侧,被查通过q条路径Q?span>G值是否更低。不必担心,我们已经准备好检查开启列表中的下一g?/span>

我们重复q个q程Q直到目标格被添加进关闭列表(注解)Q就如在下面的图中所看到的?/span>

[?span>-6]

注意Qv始格下方格子的父节点已经和前面不同的。之前它?span>G值是Qƈ且指向右上方的格子。现在它?span>G值是Q指向它上方的格子。这在寻路过E中的某处发生,当应用新路径ӞG值经q检查变得低了-于是父节点被重新指定Q?span>G?span>FD重新计算。尽这一变化在这个例子中q不重要Q在很多场合Q这U变化会D寻\l果的巨大变化?/span>

那么Q我们怎么定q条路径呢?很简单,从红色的目标格开始,按箭头的方向朝父节点Ud。这最l会引导你回到v始格Q这是你的路径Q看h应该像图中那栗从起始?span>AUd到目标格B只是单的从每个格子(节点Q的中点沿\径移动到下一个,直到你到辄标点。就q么单?/span>

[?span>-7]

A*Ҏ(gu)ȝ

好,现在你已l看完了整个说明Q让我们把每一步的操作写在一P

   1Q把起始格添加到开启列表?/span>

   2Q重复如下的工作Q?/span>

      a) L开启列表中F值最低的格子。我们称它ؓ当前根{?/span>

      b) 把它切换到关闭列表?/span>

      c) 对相ȝg的每一个?

          * 如果它不可通过或者已l在关闭列表中,略过它。反之如下?/span>

          * 如果它不在开启列表中Q把它添加进厅R把当前g一格的父节炏V记录这一格的F,G,?span>H倹{?/span>

          * 如果它已l在开启列表中Q用Ggؓ参考检查新的\径是否更好。更低的G值意味着更好的\径。如果是q样Q就把这一格的父节Ҏ(gu)成当前格Qƈ且重新计这一格的G?span>F倹{如果你保持你的开启列表按F值排序,改变之后你可能需要重新对开启列表排序?/span>

      d) 停止Q当?/span>

          * 把目标格dq了关闭列表(注解)Q这时候\径被扑ֈQ或?/span>

          * 没有扑ֈ目标|开启列表已l空了。这时候,路径不存在?/span>

   3.保存路径。从目标格开始,沿着每一格的父节点移动直到回到v始格。这是你的路径?/span>

 

(注解:在这文章的较早版本中,的做法是当目标格Q或节点Q被加入到开启列表,而不是关闭列表的时候停止寻路。这么做会更q速,而且几乎L能找到最短的路径Q但不是l对的。当从倒数W二个节点到最后一个(目标节点Q之间的Ud耗费(zhn)殊很大Ӟ例如刚好有一条河I越两个节点中间Q这时候旧的做法和新的做法׃有显著不同?span>)

 

题外?/span>

题一下,见谅Q值得一提的是,当你在网上或者相兌坛看到关?span>A*的不同的探讨Q你有时会看C些被当作A*法的代码而实际上他们不是。要使用A*Q你必须包含上面讨论的所有元素-Q特定的开启和关闭列表Q用F,G?span>H作\径评仗有很多其他的寻路算法,但他们ƈ不是A*Q?span>A*被认为是他们当中最好的?span>Bryan Stout在这文章后面的参考文档中了一部分Q包括他们的一些优点和~点。有时候特定的场合其他法会更好,但你必须很明你在作什么。好了,够多的了。回到文章?/span>

 

实现的注?/span>

现在你已l明白了基本原理Q写你的E序的时候还得考虑一些额外的东西。下面这些材料中的一些引用了我用C++?span>Blitz Basic写的E序Q但对其他语a写的代码同样有效?/span>

1.其他单位(避免撞)Q如果你恰好看了我的例子代码Q你会发现它完全忽略了其他单位。我的寻路者事实上可以怺I越。取决于具体的游戏,q也许可以,也许不行。如果你打算考虑其他单位Q希望他们能互相l过Q我你只考虑静止或那些在计算路径时͘q当前单位的单位Q把它们当前的位|标志ؓ可通过的。对于͘q的q动着的单位,你可以通过惩罚它们各自路径上的节点Q来鼓励q些寻\者找C同的路径(更多的描q见#2).

如果你选择了把其他正在Udq且q离当前寻\单位的那些单位考虑在内Q你需要实CU方法及旉在何时何地撞可能会发生,以便恰当的避免。否则你极有可能得到一条怪异的\径,单位H然转弯试图避免和一个已l不存在的单位发生碰撞?/span>

当然Q你也需要写一些碰撞检的代码Q因为无的时候\径有多完,它也会因旉而改变。当撞发生Ӟ一个单位必d找一条新路径Q或者,如果另一个单位正在移动ƈ且不是正面碰撞,在l沿当前路径Ud之前Q等待那个单位离开?/span>

q些提示大概可以让你开始了。如果你想了解更多,q里有些你可能会觉得有用的链接:

    *自治角色的指D为:Craig Reynold在指D力上的工作和寻\有些不同Q但是它可以和寻路整合从而Ş成更完整的移动和撞系l?/span>

    *?sh)脑游戏中的长短距指|指导和寻路方面著作的一个有的考察。这是一?span>pdf文g?/span>

    *协同单位UdQ一个两部分pd文章的第一,内容是关于编队和Z分组的移动,作者是帝国时代(Age of Empires)的设计?span>Dave Pottinger.

    *实现协同UdQ?span>Dave Pottinger文章pd的第二篇?/span>

2. 不同的地形损耗:在这个教E和我附带的E序中,地Ş只能是二者之Q可通过的和不可通过的。但是你可能会需要一些可通过的地形,但是Ud耗费更高Q沼泽,山Q地牢的楼梯Q等{。这些都是可通过但是比^坦的开阔地Ud耗费更高的地形。类似的Q道路应该比自然地ŞUd耗费更低?/span>

q个问题很容易解冻I只要在计Q何地形的G值的时候增加地形损耗就可以了。简单的l它增加一些额外的损耗就可以了。由?span>A*法已经按照L最低耗费的\径来设计Q所以很Ҏ(gu)处理q种情况。在我提供的q个单的例子里,地Ş只有可通过和不可通过两种Q?span>A*会找到最短,最直接的\径。但是在地Ş耗费不同的场合,耗费最低的路径也许会包含很长的Ud距离Q就像沿着路绕q沼泽而不是直接穿q它?/span>

一U需额外考虑的情冉|被专家称之ؓinfluence mapping的东西(暂译为媄响映图Q。就像上面描q的不同地Ş耗费一P你可以创Z格额外的分数pȝQƈ把它应用到寻路的AI中。假设你有一张有大批寻\者的地图Q他们都要通过某个山区。每ơ电(sh)脑生成一条通过那个兛_的\径,它就会变得更拥挤。如果你愿意Q你可以创徏一个媄响映图Ҏ(gu)大量屠杀事g的格子施以不利媄响。这会让计算机更們֐安全些的路径Qƈ且帮助它避免L仅仅因ؓ路径?span>(但可能更危险)而持l把队伍和寻路者送到某一特定路径?/span>

另一个可能得应用是惩|周围移动单位\径上得节炏V?span>A*的一个底限是Q当一单位同时试囑֯路到接近的地点,q通常会导致\径交叠。以Z个或者多个单位都试图走相同或者近似的路径到达目的地。对其他单位已经认领了的节点增加一些惩|会有助于你在一定程度上分离路径Q降低碰撞的可能性。然而,如果有必要,不要把那些节点看成不可通过的,因ؓ你仍然希望多个单位能够一字纵队通过拥挤的出口。同Ӟ你只能惩|那些͘q单位的路径Q而不是所有\径,否则你就会得到奇怪的w避行ؓ例如单位w避路径上其他已l不在那里的单位。还有,你应该只惩罚路径当前节点和随后的节点Q而不应处理已l走qƈ甩在w后的节炏V?/span>

3. 处理未知区域Q你是否玩过q样?span>PC游戏Q电(sh)脑L知道哪条路是正确的,即它还没有侦察q地图?对于游戏Q寻路太好会昑־不真实。幸q的是,q是一格可以轻易解决的问题?/span>

{案是为每个不同的玩家和电(sh)脑(每个玩家Q而不是每个单位-Q那L话会耗费大量的内存)创徏一个独立的knownWalkability数组Q每个数l包含玩家已l探索过的区域,以及被当作可通过区域的其他区域,直到被证实。用q种Ҏ(gu)Q单位会在\的死端徘徊ƈ且导致错误的选择直到他们在周围找到\。一旦地图被探烦了,寻\像往帔R栯行?/span>

4. qx路径Q尽?span>A*提供了最短,最低代L路径Q它无法自动提供看v来^滑的路径。看一下我们的例子最lŞ成的路径Q在图)。最初的一步是起始格的右下方,如果q一步是直接往下的话,路径不是会更qx一些吗Q有几种Ҏ(gu)来解册个问题。当计算路径的时候可以对改变方向的格子施加不利媄响,?span>G值增加额外的数倹{也可以换种Ҏ(gu)Q你可以在\径计完之后沿着它跑一遍,N些用盔R格替换会让\径看h更^滑的地方。想知道完整的结果,查看Toward More Realistic PathfindingQ一?span>(免费Q但是需要注?span>)Marco Pinter发表?span>Gamasutra.com的文?/span>

5. 非方形搜索区域:在我们的例子里,我们使用单的D方Ş图。你可以不用这U方式。你可以使用不规则Ş状的区域。想惛_险棋的游戏,和游戏中那些国家。你可以设计一个像那样的寻路关卡。ؓ此,你可能需要徏立一个国家相dpȝ表格Q和从一个国家移动到另一个的G倹{你也需要估?span>H值的Ҏ(gu)。其他的事情和例子中完全一样了。当你需要向开启列表中d新元素的时候,不需使用盔R的格子,取而代之的是从表格中寻扄ȝ国家?/span>

cM的,你可以ؓ一张确定的地Ş囑ֈ\径点pȝQ\径点一般是路上Q或者地牢通道的{折点。作为游戏设计者,你可以预设这些\径点。两个\径点被认为是盔R的如果他们之间的直线上没有障的话。在冒险的例子里,你可以保存这些相M息在某个表格里,当需要在开启列表中d元素的时候用它。然后你可以记录关联的G|可能使用两点间的直线距离Q,H|可以使用到目标点的直U距)Q其他都按原先的做就可以了?span>Amit Patel 写了其他Ҏ(gu)的摘要。另一个在非方形区域搜?span>RPG地图的例子,查看我的文章Two-Tiered A* Pathfinding?span>(译者注Q译文: A*分层寻\)

6. 一些速度斚w的提C:当你开发你自己?span>A*E序Q或者改写我的,你会发现寻\占据了大量的CPU旉Q尤其是在大地图上有大量对象在寻路的时候。如果你阅读q网上的其他材料Q你会明白,即是开发了星际争霸或帝国时代的专家Q这也无可奈何。如果你觉得寻\太过~慢Q这里有一些徏议也许有效:

    * 使用更小的地图或者更的寻\者?/span>

    * 不要同时l多个对象寻路。取而代之的是把他们加入一个队列,把寻路过E分散在几个游戏周期中。如果你的游戏以周期每秒的速度q行Q没察觉。但是当大量寻\者计自p\径的时?span>,他们会发觉游戏速度H然变慢?/span>

    * 量使用更大的地囄根{这降低了寻路中搜烦的ȝ格数。如果你有志气,你可以设计两个或者更多寻路系l以便用在不同场合Q取决于路径的长度。这也正是专业h士的做法Q用大的区域计算长的路径Q然后在接近目标的时候切换到使用格?span>/区域的精l寻路。如果你对这个观Ҏ(gu)兴趣Q查阅我的文?span>Two-Tiered A* Pathfinding?span>(译者注Q译?span>:A*分层寻\)

    * 使用路径点系l计长路径Q或者预先计好路径q加入到游戏中?/span>

    * 预处理你的地图,表明地图中哪些区域是不可到达的。我把这些区域称?/span>孤岛。事实上Q他们可以是岛屿或其他被墙壁包围{无法到辄L区域?span>A*的下限是Q当你告诉它要寻N往那些区域的\径时Q它会搜索整个地图,直到所有可到达的方?span>/节点都被通过开启列表和关闭列表的计。这会浪费大量的CPU旉。可以通过预先定q些区域Q比如通过flood-fill或类似的Ҏ(gu))来避免这U情늚发生,用某些种cȝ数组记录q些信息Q在开始寻路前查它?/span>

    * 在一个拥挤的cMq宫的场合,把不能连通的节点看作ȝ。这些区域可以在地图~辑器中预先手动指定Q或者如果你有雄心壮志,开发一个自动识别这些区域的法。给定死端的所有节点可以被赋予一个唯一的标志数字。然后你可以在寻\q程中安全的忽略所有死端,只有当vҎ(gu)者终Ҏ(gu)好在ȝ的某个节点的时候才需要考虑它们?/span>

7. l护开启列表:q是A*寻\法最重要的组成部分。每ơ你讉K开启列表,你都需要寻?span>F值最低的Ҏ(gu)。有几种不同的方法实现这一炏V你可以把\径元素随意保存,当需要寻?span>F值最低的元素的时候,遍历开启列表。这很简单,但是太慢了,其是对长\径来说。这可以通过l护一格排好序的列表来改善Q每ơ寻?span>F值最低的Ҏ(gu)只需要选取列表的首元素。当我自己实现的时候,q种Ҏ(gu)是我的首选?/span>

在小地图。这U方法工作的很好Q但它ƈ不是最快的解决Ҏ(gu)。更苛求速度?span>A*E序员用叫做二叉堆的方法,q也是我在代码中使用的方法。凭我的l验Q这U方法在大多数场合会快~倍,q且在长路经上速度呈几何数提?span>(10倍以上速度)。如果你想了解更多关于二叉堆的内容,查阅我的文章Q?span>Using Binary Heaps in A* Pathfinding?span>(译者注Q译文:?span>A*寻\中用二叉堆)

另一个可能的瓉是你在多ơ寻路之间清除和保存你的数据l构的方法。我个h更們֐把所有东襉K存储在数l里面。虽然节点可以以面向对象的风D动态的产生Q记录和保存Q我发现创徏和删除对象所增加的大量时_以及多余的管理层ơ减慢的整个q程的速度。但是,如果你用数l,你需要在调用之间清理数据。这中情形你惛_的最后一件事是在寻路调用之后花Ҏ(gu)间把一切归Ӟ其是你的地囑־大的时候?/span>

我通过使用一个叫?span>whichList(x,y)的二l数l避免这U开销Q数l的每个元素表明了节点在开启列表还是在关闭列表中。尝试寻路之后,我没有清零这个数l。取而代之的是,我在新的寻\中重|?span>onClosedList?span>onOpenList的数|每次寻\两个?span>+5或者类似其他数倹{这U方法,法可以安全的蟩q前面寻路留下的脏数据。我q在数组中储存了诸如F,G?span>H的倹{这样一来,我只需单的重写M已经存在的D无需被清除数l的操作q扰。将数据存储在多l数l中需要更多内存,所以这里需要权衡利弊。最后,你应该用你最得心应手的方法?/span>

8. Dijkstra的算法:管A*被认为是通常最好的寻\法(看前面的题外?/span>),q是有一U另外的法有它的可取之?span>-Dijkstra法?span>Dijkstra法?span>A*本质是相同的Q只有一点不同,是Dijkstra法没有启发?span>(H值L)。由于没有启发式Q它在各个方向上q_搜烦。正如你所预料Q由?span>Dijkstra法在找到目标前通常会探索更大的区域Q所以一般会?span>A*更慢一些?/span>

那么Z么要使用q种法呢?因ؓ有时候我们ƈ不知道目标的位置。比如说你有一个资源采集单位,需要获取某U类型的资源若干。它可能知道几个资源区域Q但是它惛_最q的那个。这U情况,Dijkstra法比A*更适合Q因为我们不知道哪个更近。用A*Q我们唯一的选择是依ơ对每个目标许\q计距,然后选择最q的路径。我们寻扄目标可能会有不计其数的位|,我们只想扑օ中最q的Q而我们ƈ不知道它在哪里,或者不知道哪个是最q的?/span>


 

看完上面的介l,再来看一个比较经典的题目:knight moves。貌g叫汉密尔\径,具体的我也不记得了。对q个问题我用A*法来求解,正所谓光说不l是没有用的

http://acm.pku.edu.cn/JudgeOnline/problem?id=2243
problem statement

A friend of you is doing research on the Traveling Knight Problem (TKP) where you are to find the shortest closed tour of knight moves that visits each square of a given set of n squares on a chessboard exactly once. He thinks that the most difficult part of the problem is determining the smallest number of knight moves between two given squares and that, once you have accomplished this, finding the tour would be easy.
Of course you know that it is vice versa. So you offer him to write a program that solves the "difficult" part.

Your job is to write a program that takes two squares a and b as input and then determines the number of knight moves on a shortest route from a to b.

Input Specification

The input file will contain one or more test cases. Each test case consists of one line containing two squares separated by one space. A square is a string consisting of a letter (a-h) representing the column and a digit (1-8) representing the row on the chessboard.

Output Specification

For each test case, print one line saying "To get from xx to yy takes n knight moves.".

Sample Input

e2 e4

a1 b2

b2 c3

a1 h8

a1 h7

h8 a1

b1 c3

f6 f6

Sample Output

To get from e2 to e4 takes 2 knight moves.

To get from a1 to b2 takes 4 knight moves.

To get from b2 to c3 takes 2 knight moves.

To get from a1 to h8 takes 6 knight moves.

To get from a1 to h7 takes 5 knight moves.

To get from h8 to a1 takes 6 knight moves.

To get from b1 to c3 takes 1 knight moves.

To get from f6 to f6 takes 0 knight moves.
题目的意思大概是_在国际象的盘上,一匚w共有8个可能的跌方向Q求从v点到目标点之间的最蟩跃次数?br>A* code:

 1 #include <iostream>
 2 #include <queue>
 3 using namespace std;
 4 
 5 struct knight{
 6     int x,y,step;
 7     int g,h,f;
 8     bool operator < (const knight & k) const{      //重蝲比较q算W?/span>
 9         return f > k.f;
10     }
11 }k;
12 bool visited[8][8];                                //已访问标?关闭列表)
13 int x1,y1,x2,y2,ans;                               //L(x1,y1),l点(x2,y2),最移动次数ans
14 int dirs[8][2]={{-2,-1},{-2,1},{2,-1},{2,1},{-1,-2},{-1,2},{1,-2},{1,2}};//8个移动方?/span>
15 priority_queue<knight> que;                        //最优先队列(开启列?
16 
17 bool in(const knight & a){                         //判断knight是否在棋盘内
18     if(a.x<0 || a.y<0 || a.x>=8 || a.y>=8)
19         return false;
20     return true;
21 }
22 int Heuristic(const knight &a){                    //manhattanCh(hun)函数
23     return (abs(a.x-x2)+abs(a.y-y2))*10;
24 }
25 void Astar(){                                      //A*法
26     knight t,s;
27     while(!que.empty()){
28         t=que.top(),que.pop(),visited[t.x][t.y]=true;
29         if(t.x==x2 && t.y==y2){
30             ans=t.step;
31             break;
32         }
33         for(int i=0;i<8;i++){
34             s.x=t.x+dirs[i][0],s.y=t.y+dirs[i][1];
35             if(in(s) && !visited[s.x][s.y]){
36                 s.g = t.g + 23;                 //23表示根号5乘以10再取其ceil
37                 s.h = Heuristic(s);
38                 s.f = s.g + s.h;
39                 s.step = t.step + 1;
40                 que.push(s);
41             }
42         }
43     }
44 }
45 int main(){
46     char line[5];
47     while(gets(line)){
48         x1=line[0]-'a',y1=line[1]-'1',x2=line[3]-'a',y2=line[4]-'1';
49         memset(visited,false,sizeof(visited));
50         k.x=x1,k.y=y1,k.g=k.step=0,k.h=Heuristic(k),k.f=k.g+k.h;
51         while(!que.empty()) que.pop();
52         que.push(k);
53         Astar();
54         printf("To get from %c%c to %c%c takes %d knight moves.\n",line[0],line[1],line[3],line[4],ans);
55     }
56     return 0;
57 }
58 


]]>
Debug函数的实玎ͼ转)http://www.shnenglu.com/Walker/articles/80471.html漫步者?amp;…?K?/dc:creator>漫步者?amp;…?K?/author>Sun, 19 Apr 2009 13:04:00 GMThttp://www.shnenglu.com/Walker/articles/80471.htmlhttp://www.shnenglu.com/Walker/comments/80471.htmlhttp://www.shnenglu.com/Walker/articles/80471.html#Feedback0http://www.shnenglu.com/Walker/comments/commentRss/80471.htmlhttp://www.shnenglu.com/Walker/services/trackbacks/80471.html   do{ \
    FILE* fp= fopen("/home/debug.log","a+"); \
    if( fp != NULL ) \
    { \
     fprintf(fp," \n %s(%d)-%s: \n",__FILE__,__LINE__,__FUNCTION__); \
     fprintf(fp,fmt,##args); \
     fclose(fp); \
     } \
   }while(0);

]]>
函数指针与Y件设?/title><link>http://www.shnenglu.com/Walker/articles/80469.html</link><dc:creator>漫步者?amp;…?K?/dc:creator><author>漫步者?amp;…?K?/author><pubDate>Sun, 19 Apr 2009 12:49:00 GMT</pubDate><guid>http://www.shnenglu.com/Walker/articles/80469.html</guid><wfw:comment>http://www.shnenglu.com/Walker/comments/80469.html</wfw:comment><comments>http://www.shnenglu.com/Walker/articles/80469.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/Walker/comments/commentRss/80469.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/Walker/services/trackbacks/80469.html</trackback:ping><description><![CDATA[<p style="TEXT-INDENT: 2em">记得刚开始工作时Q一位高手告诉我Q说Qlongjmp和setjmp玩得不熟Q就不要自称为C语言高手。当时我半信半疑Qؓ了让自己向高手方向迈q,q是׃一Ҏ(gu)间去学习longjmp和setjmp的用法。后来明白那不单是蟩来蟩去那L单,而是一U高U的异常处理机制Q在某些情况下确实很有用?/p> <p style="TEXT-INDENT: 2em"> </p> <p style="TEXT-INDENT: 2em">Z昄自己的技巧,也在自己的程序中用过几次。渐渐发现这L技巧带来的好处是有代h(hun)的,破坏了程序的l构化设计,E序变得很难读,其Ҏ(gu)手来说。终于明白这U技巧不q是一U调xQ在数情况使用几次Q可以简化对问题的处理。如果把调味拿来当饭吃,一定会本末倒置Q写出的E序会呈现营M良之状?/p> <p style="TEXT-INDENT: 2em"> </p> <p style="TEXT-INDENT: 2em">事实上,longjmp和setjmp玩得熟不熟与是不是C语言高手Q不是因果关pR但是,如果可以套用那位高手的话Q我倒想说如果函数指针玩得不熟,׃要自UCؓC语言高手。ؓ什么这么说呢,函数指针有那么复杂吗Q当然不是,M一个稍有编E常识的人,不管他懂不懂C语言Q在10分钟内,我想他一定可以明白C语言中的函数指针是怎么回事?/p> <p style="TEXT-INDENT: 2em"> </p> <p style="TEXT-INDENT: 2em">原因在于Q难的不是函数指针的概念和语法本w,而是在什么时候,什么地方该使用它。函数指针不仅是语法上的问题Q更重要的是它是一个设计范畴。真正的高手当然不单应该懂得语法层面上的技巧,更应该懂得设计上的方法。不懂设计,能算高手吗?怀疑我在夸大其辞吗Q那我们先看看函数指针与哪些设计Ҏ(gu)有关Q?/p> <p style="TEXT-INDENT: 2em"> </p> <p style="TEXT-INDENT: 2em"><strong>与分层设计有兟?/strong>分层设计早就不是什么新的概念,分层的好处是众所周知的,比较明显好处是化复杂度、隔d化。采用分层设计,每层都只需兛_自己的东西,q减了pȝ的复杂度Q层与层之间的交互仅限于一个很H的接口Q只要接口不变,某一层的变化不会影响其它层,q隔M变化?/p> <p style="TEXT-INDENT: 2em"> </p> <p style="TEXT-INDENT: 2em">分层的一般原则是Q上层可以直接调用下层的函数Q下层则不能直接调用上层的函数。这句话说来单,在现实中Q下层常常要反过来调用上层的函数。比如你在拷贝文件时Q在界面层调用一个拷贝文件函数。界面层是上层,拯文g函数是下层,上层调用下层Q理所当然。但是如果你惛_拯文g时还要更新进度条Q问题就来了。一斚wQ只有拷贝文件函数才知道拯的进度,但它不能L新界面的q度条。另外一斚wQ界面知道如何去更新q度条,但它又不知道拯的进度。怎么办?常见的做法,是界面讄一个回调函数给拯文g函数Q拷贝文件函数在适当的时候调用这个回调函数来通知界面更新状态?/p> <p style="TEXT-INDENT: 2em"> </p> <p style="TEXT-INDENT: 2em"><strong>与抽象有兟?/strong>抽象是面向对象中最重要的概念之一Q也是面向对象威力强大之处。面向对象只是一U思想Q大安知道Q用C语言一样可以实现面向对象的~程。这可不是ؓ了赶旉Q而是一U实用的Ҏ(gu)。如果你Ҏ(gu)表示怀疑,可以ȝ看GTK+、linux kernel{开源代码?/p> <p style="TEXT-INDENT: 2em"> </p> <p style="TEXT-INDENT: 2em">接口是最高的抽象。在linux kernel里面Q接口的概念无处不在Q像虚拟文gpȝ(VFS)Q它定义一个文件系l的接口Q只要按照这U接口的规范Q你可以自己开发一个文件系l挂上去。设备驱动程序更是如此,不同的设备驱动程序有自己一套不同的接口规范。在自己开发设备开发驱动程序时Q只要遵循相应的接口规范?yu)p了。接口在C语言中如何表C?很简单,是一l函数指针?/p> <p style="TEXT-INDENT: 2em"> </p> <p style="TEXT-INDENT: 2em"><strong>与接口与实现分开有关</strong>。针Ҏ(gu)口编E,而不是针对实现编E,此ؓ《设计模式》的W一条设计准则。分开接口与实现的目标是要隔离变化。Y件是变化的,如果不能把变化的东西隔离开来,D牵一发而动全nQ代h巨大的。这是大家所不愿看到的?/p> <p style="TEXT-INDENT: 2em"> </p> <p style="TEXT-INDENT: 2em">C语言既然可以实现面向对象的编E,自然可以利用设计模式来分L口与实现。像桥接模式、策略模式、状态模式、代理模式等{,在C语言中,无一不需要利用函数指针来实现?/p> <p style="TEXT-INDENT: 2em"> </p> <p style="TEXT-INDENT: 2em"><strong>与松耦合原则有关</strong>。面向过E与面向对象相比Q之所以显得苍白无力,原因之一是它不像面向对象一P可以直观的把现实模型映射到计机中。面向过E讲的是层层控制Q而面向对象更的对象间的分工合作。现实世界中的对象处于层ơ关pȝ较少Q处于对{关pȝ居多。也是_对象间的交互往往是双向的。这会加强对象间的耦合性?/p> <p style="TEXT-INDENT: 2em"> </p> <p style="TEXT-INDENT: 2em">耦合本n没有错,实际上耦合是必不可的Q没有耦合没有协作,对象之间无法形成一个整体,什么事也做不了。关键在于耦合要恰当,在实现预定功能的前提下,耦合要尽可能的松散。这Ppȝ的一部分变化对其它部分的影响会很?/p> <p style="TEXT-INDENT: 2em"> </p> <p style="TEXT-INDENT: 2em">函数指针是解耦对象关pȝ最?jng)_器。Signal(如boost的signal和glib中的signal)机制是一个典型的例子Q一个对象自w的状态可能是在变化的Q或者会触发一些事ӞQ而其它对象关心它的变化。一旦该对象有变化发生,其它对象要执行相应的操作?/p> <p style="TEXT-INDENT: 2em"> </p> <p style="TEXT-INDENT: 2em">如果该对象直接去调用其它对象的函敎ͼ功能是完成了Q但对象之间的耦合太紧了。如何把q种耦合降到最低呢Qsignal机制是很好的办法。它的原理大致如下:其它x该对象变化的对象d注册一个回调函数到该对象中。一旦该对象有变化发生,p用这些回调函数通知其它对象。功能同样实CQ但它们之间的耦合度降低了?/p> <p style="TEXT-INDENT: 2em"> </p> <p style="TEXT-INDENT: 2em">在C语言中,要解决以上这些问题,不采用函数指针,是非常困难的。在~程中,如果你从没有惛_用函数指针,很难惛_你是一个C语言高手?/p> <img src ="http://www.shnenglu.com/Walker/aggbug/80469.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/Walker/" target="_blank">漫步者?…?K?/a> 2009-04-19 20:49 <a href="http://www.shnenglu.com/Walker/articles/80469.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title> Q{Q经典的位运实?/title><link>http://www.shnenglu.com/Walker/articles/80466.html</link><dc:creator>漫步者?amp;…?K?/dc:creator><author>漫步者?amp;…?K?/author><pubDate>Sun, 19 Apr 2009 12:44:00 GMT</pubDate><guid>http://www.shnenglu.com/Walker/articles/80466.html</guid><wfw:comment>http://www.shnenglu.com/Walker/comments/80466.html</wfw:comment><comments>http://www.shnenglu.com/Walker/articles/80466.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.shnenglu.com/Walker/comments/commentRss/80466.html</wfw:commentRss><trackback:ping>http://www.shnenglu.com/Walker/services/trackbacks/80466.html</trackback:ping><description><![CDATA[<p>1) int型变量@环左Ukơ,即a=a < <k |a>>16-k  (设sizeof(int)=16) <br>(2) int型变量a循环右移kơ,即a=a>>k |a < <16-k  (设sizeof(int)=16) <br>(3)整数的^均?<br>对于两个整数x,yQ如果用 (x+y)/2 求^均|会生溢出,因ؓ x+y 可能会大于INT_MAXQ但是我们知道它们的q_值是肯定不会溢出的,我们用如下算法: <br>int average(int x, int y)  //q回X,Y 的^均?<br>{    <br>    return (x&y)+((x^y)>>1); <br>} <br>(4)判断一个整数是不是2的幂,对于一个数 x >= 0Q判断他是不?的幂 <br>boolean power2(int x) <br>{ <br>    return ((x&(x-1))==0)&&(x!=0)Q?<br>} <br>(5)不用temp交换两个整数 <br>void swap(int x , int y) <br>{ <br>    x ^= y; <br>    y ^= x; <br>    x ^= y; <br>} <br>(6)计算l对?<br>int abs( int x ) <br>{ <br>int y ; <br>y = x >> 31 ; <br>return (x^y)-y ;        //or: (x+y)^y <br>} <br>(7)取模q算转化成位q算 (在不产生溢出的情况下) <br>        a % (2^n) {h(hun)?a & (2^n - 1) <br>(8)乘法q算转化成位q算 (在不产生溢出的情况下) <br>        a * (2^n) {h(hun)?a < < n <br>(9)除法q算转化成位q算 (在不产生溢出的情况下) <br>        a / (2^n) {h(hun)?a>> n <br>        ? 12/8 == 12>>3 <br>(10) a % 2 {h(hun)?a & 1        <br>(11) if (x == a) x= b; <br>            else x= a; <br>        {h(hun)?x= a ^ b ^ x; <br>(12) x ?相反?表示?(~x+1) </p> <p>(13)求从x位(高)到y位(低)间共有多个1 </p> <p>public static int FindChessNum(int x, int y, ushort k) <br>        { <br>            int re = 0; <br>            for (int i = y; i <= x; i++) <br>            { <br>                re += ((k >> (i - 1)) & 1); <br>            } <br>            return re; <br>        } <br>(14)<br>/*?2位数分解??位数处理后再合成32位数q回*/<br>DWORD GetDW(DWORD dw)<br>{<br> DWORD dwRet=0;<br> if (dw!=0)<br> {<br>  BYTE b1=(dw>>24)&0xff,b2=(dw>>16)&0xff,b3=(dw>>8)&0xff,b4=dw&0xff;<br>  //分别处理 b1,b2,b3,b4<br>  dwRet=b1;<br>  dwRet=(dwRet<<8)+b2;<br>  dwRet=(dwRet<<8)+b3;<br>  dwRet=(dwRet<<8)+b4;</p> <p>  return dwRet;<br> }<br> else{<br>  return 0;<br> }<br>}<br><br><br>  一个无W号数是不ؓ2^n-1(^为幂)Q?nbsp;  x&(x+1)   <br>    <br>  最右侧0位改?位:   x   |   (x+1)   <br>    <br>  二进制补码运公式:   <br>  -x   =   ~x   +   1   =   ~(x-1)   <br>  ~x   =   -x-1     <br>  -(~x)   =   x+1   <br>  ~(-x)   =   x-1   <br>  x+y   =   x   -   ~y   -   1   =   (x|y)+(x&y)     <br>  x-y   =   x   +   ~y   +   1   =   (x|~y)-(~x&y)     <br>  x^y   =   (x|y)-(x&y)   <br>  x|y   =   (x&~y)+y   <br>  x&y   =   (~x|y)-~x   <br>    <br>  x==y:         ~(x-y|y-x)   <br>  x!=y:         x-y|y-x   <br>  x<   y:         (x-y)^((x^y)&((x-y)^x))   <br>  x<=y:         (x|~y)&((x^y)|~(y-x))   <br>  x<   y:         (~x&y)|((~x|y)&(x-y))//无符号x,y比较   <br>  x<=y:         (~x|y)&((x^y)|~(y-x))//无符号x,y比较   <br>    <br>    <br>  使用位运的无分支代码:   <br>    <br>  计算l对?nbsp;  <br>  int   abs(   int   x   )     <br>  {   <br>  int   y   ;   <br>  y   =   x   >>   31   ;   <br>  return   (x^y)-y   ;//or:   (x+y)^y   <br>  }   <br>    <br>  W号函数Qsign(x)   =   -1,   x<0;   0,   x   ==   0   ;   1,   x   >   0   <br>  int   sign(int   x)   <br>  {   <br>  return   (x>>31)   |   (unsigned(-x))>>31   ;//x=-2^31时失?^为幂)   <br>  }   <br>    <br>  三值比较:cmp(x,y)   =   -1,   x<y;   0,   x==y;   1,   x   >   y   <br>  int   cmp(   int   x,   int   y   )   <br>  {   <br>  return   (x>y)-(x-y)   ;   <br>  }   <br>    <br>  doz=x-y,   x>=y;   0,   x<y   <br>  int   doz(int   x,   int   y   )   <br>  {   <br>  int   d   ;   <br>  d   =   x-y   ;   <br>  return   d   &   ((~(d^((x^y)&(d^x))))>>31)   ;   <br>  }   <br>    <br>  int   max(int   x,   int   y   )     <br>  {   <br>  int   m   ;   <br>  m   =   (x-y)>>31   ;     <br>  return   y   &   m   |   x   &   ~m   ;   <br>  }   <br>    <br>  不用第三方交换x,y:   <br>  1.x   ^=   y   ;   y   ^=   x   ;   x   ^=   y   ;   <br>  2.x   =   x+y   ;   y   =   x-y   ;   x   =   x-y   ;   <br>  3.x   =   x-y   ;   y   =   y+x   ;   x   =   y-x   ;   <br>  4.x   =   y-x   ;   x   =   y-x   ;   x   =   x+y   ;     <br>    <br>  双g?x   =   a,   x==b;   b,   x==a//常规~码为x   =   x==a   ?   b   :a   ;   <br>  1.x   =   a+b-x   ;   <br>  2.x   =   a^b^x   ;   <br>    <br>  下舍入到2的kơ方的倍数:   <br>  1.x   &   ((-1)<<k)   <br>  2.(((unsigned)x)>>k)<<k   <br>  上舍入:   <br>  1.   t   =   (1<<k)-1   ;   x   =   (x+t)&~t   ;   <br>  2.t   =   (-1)<<k   ;   x   =   (x-t-1)&t   ;   <br>    <br>  位计?l计1位的数量Q?nbsp;  <br>  1.   <br>  int   pop(unsigned   x)   <br>  {   <br>  x   =   x-((x>>1)&0x55555555)   ;   <br>  x   =   (x&0x33333333)   +   ((x>>2)   &   0x33333333   )   ;   <br>  x   =   (x+(x>>4))   &   0x0f0f0f0f   ;   <br>  x   =   x   +   (x>>8)   ;   <br>  x   =   x   +   (x>>16)   ;   <br>  return   x   &   0x0000003f   ;   <br>  }   <br>  2.   <br>  int   pop(unsigned   x)   {   <br>  static   char   table[256]   =   {   0,1,1,2,   1,2,2,3,   ....,   6,7,7,8   }   ;   <br>  return   table[x&0xff]+table[(x>>8)&0xff]+table[(x>>16)&0xff]+table[(x>>24)]   ;   <br>  }   <br>    <br>  奇偶性计?   <br>  x   =   x   ^   (   x>>1   )   ;   <br>  x   =   x   ^   (   x>>2   )   ;   <br>  x   =   x   ^   (   x>>4   )   ;   <br>  x   =   x   ^   (   x>>8   )   ;   <br>  x   =   x   ^   (   x>>16   )   ;   <br>  l果中位于x最低位Q对无符号x,l果的第i位是原数Wi位到最左侧位的奇偶?nbsp;  <br>    <br>    <br>  位反转:   <br>  unsigned   rev(unsigned   x)   <br>  {   <br>  x   =   (x   &   0x55555555)   <<   1   |   (x>>1)   &   0x55555555   ;   <br>  x   =   (x   &   0x33333333)   <<   2   |   (x>>2)   &   0x33333333   ;   <br>  x   =   (x   &   0x0f0f0f0f)   <<   4   |   (x>>4)   &   0x0f0f0f0f   ;   <br>  x   =   (x<<24)   |   ((x&0xff00)<<8)   |   ((x>>8)   &   0xff00)   |   (x>>24)   ;   <br>  return   x   ;   <br>  }   <br>    <br>  递增位反转后的数Q?nbsp;  <br>  unsigned   inc_r(unsigned   x)   <br>  {   <br>  unsigned   m   =   0x80000000   ;   <br>  x   ^=   m   ;   <br>  if(   (int)x   >=   0   )     <br>  do   {   m   >>=   1   ;   x   ^=   m   ;   }   while(   x   <   m   )   ;   <br>  return   x   ;   <br>  }   <br>    <br>  混选位Q?nbsp;  <br>  abcd   efgh   ijkl   mnop   ABCD   EFGH   IJKL   MNOP->aAbB   cCdD   eEfF   gGhH   iIjJ   kKlL   mMnN   oOpP   <br>  unsigned   ps(unsigned   x)   <br>  {   <br>  unsigned   t   ;   <br>  t   =   (x   ^   (x>>8))   &   0x0000ff00;   x   =   x   ^   t   ^   (t<<8)   ;   <br>  t   =   (x   ^   (x>>4))   &   0x00f000f0;   x   =   x   ^   t   ^   (t<<4)   ;   <br>  t   =   (x   ^   (x>>2))   &   0x0c0c0c0c;   x   =   x   ^   t   ^   (t<<2)   ;   <br>  t   =   (x   ^   (x>>1))   &   0x22222222;   x   =   x   ^   t   ^   (t<<1)   ;   <br>  return   x   ;   <br>  }   <br>    <br>  位压~:   <br>  选择q右Udx中对应于掩码m?位的?如:compress(abcdefgh,01010101)=0000bdfh   <br>  compress_left(x,m)操作与此cMQ但l果位在左边:   bdfh0000.   <br>  unsigned   compress(unsigned   x,   unsigned   m)   <br>  {   <br>  unsigned   mk,   mp,   mv,   t   ;   <br>  int   i   ;   <br>    <br>  x   &=   m   ;   <br>  mk   =   ~m   <<   1   ;   <br>  for(   i   =   0   ;   i   <   5   ;   ++i   )   {   <br>  mp   =   mk   ^   (   mk   <<   1)   ;   <br>  mp   ^=   (   mp   <<   2   )   ;   <br>  mp   ^=   (   mp   <<   4   )   ;   <br>  mp   ^=   (   mp   <<   8   )   ;   <br>  mp   ^=   (   mp   <<   16   )   ;   <br>  mv   =   mp   &   m   ;   <br>  m   =   m   ^   mv   |   (mv   >>   (1<<i)   )   ;   <br>  t   =   x   &   mv   ;   <br>  x     =   x   ^   t   |   (   t   >>   (   1<<i)   )   ;   <br>  mk   =   mk   &   ~mp   ;   <br>  }   <br>  return   x   ;   <br>  }   <br>    <br>    <br>  位置换:   <br>  ?2?位数表示从最低位开始的位的目标位置Q结果是一?2*5的位矩阵Q?nbsp;  <br>  该矩阵沿次对角U{|后??2位字p[5]存放?nbsp;  <br>  SAG(x,m)   =   compress_left(x,m)   |   compress(x,~m)   ;   <br>  准备工作Q?nbsp;  <br>  void   init(   unsigned   *p   )   {   <br>  p[1]   =   SAG(   p[1],   p[0]   )   ;   <br>  p[2]   =   SAG(   SAG(   p[2],   p[0]),   p[1]   )   ;   <br>  p[3]   =   SAG(   SAG(   SAG(   p[3],   p[0]   ),   p[1]),   p[2]   )   ;   <br>  p[4]   =   SAG(   SAG(   SAG(   SAG(   p[4],   p[0]   ),   p[1])   ,p[2]),   p[3]   )   ;   <br>  }   <br>  实际|换Q?nbsp;  <br>  int   rep(   unsigned   x   )   {   <br>  x   =   SAG(x,p[0]);   <br>  x   =   SAG(x,p[1]);   <br>  x   =   SAG(x,p[2]);   <br>  x   =   SAG(x,p[3]);   <br>  x   =   SAG(x,p[4]);   <br>  return   x   ;   <br>  }   <br>    <br>  二进制码到GRAY码的转换:   <br>  unsigned   B2G(unsigned   B   )   <br>  {   <br>  return   B   ^   (B>>1)   ;   <br>  }   <br>  GRAY码到二进制码:   <br>  unsigned   G2B(unsigned   G)   <br>  {   <br>  unsigned   B   ;   <br>  B   =   G   ^   (G>>1)   ;   <br>  B   =   G   ^   (G>>2)   ;   <br>  B   =   G   ^   (G>>4)   ;   <br>  B   =   G   ^   (G>>8)   ;   <br>  B   =   G   ^   (G>>16)   ;   <br>  return   B   ;   <br>  }   <br>    <br>  扑և最?字节的位|?   <br>  int   zbytel(   unsigned   x   )   <br>  {   <br>  static   cahr   table[16]   =   {   4,3,2,2,   1,1,1,1,   0,0,0,0,   0,0,0,0   }   ;   <br>  unsigned   y   ;   <br>  y   =   (x&0x7f7f7f7f)   +   0x7f7f7f7f   ;   <br>  y   =   ~(y|x|0x7f7f7f7f)   ;   <br>  return   table[y*0x00204081   >>   28]   ;//乘法可用UM和加完成   <br>  }   <br><br><br></p> <p>C\C++支持比较低阶的位q算Q在是众人皆知的了。每本C\C++的教U书都会说到q部分的内容Q不q都很简略,我想会有很多Z知道位运用在什么地斏V这个帖子就略说说位q算的用处,更进一步的用法要大家自己去体会。而主要说的是操作标志值方面?/p> <p> </p> <p> /****************************************/</p> <p>#define BTI_MSK(bit)    (1 << (bit))<br>#define BIT_SET(x,bit)  ((x) |=  BTI_MSK (bit))<br>#define BIT_CLR(x,bit)  ((x) &= ~BTI_MSK (bit))<br>#define BIT_TST(x,bit)  ((x) &   BTI_MSK (bit))</p> <p> /****************************************/</p> <p> </p> <p>考虑一个事物、一个系l、或者一个程序可能会出现一U或者几U状态。ؓ了在不同的状态下Q作Z同的行ؓQ你可以讄一些标志|再根据标志值来做判断。比如C++的文件流Q你可以设定一些标志|ios::app, ios::ate, ios::binary, ios::in, ios::out, ios::truncQƈ且可以将它用|l合h创徏一个恰当的文g。你可能会将q些标志值定义ؓboolcdQ不q这栯是设|的标志g多,׃很浪费空间?br><br>而假如定义一个整型数|unsigned int flags; 在现在的pȝQflags应该?2? ?,2,3....32位q行~号Q我们可以进行这L判断, 当位1?Ӟ表示用读方式打开文gQ当??Ӟ表示用写方式打开文gQ当??Ӟ用二q制方式打开文g....因ؓflags?2位,可以设|?2个不同的状态|也相当于32个boolcd。这样一斚w省了I间, 另一斚w也多了个好处Q就是如前面所说的Q可以将标志值组合v来?br>//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><br><br>好啦Q上面有点不清不楚的。下面看看到底怎么操作q些标志倹{?br>设想C++的类iosq样定义, 其实没有q个c,只有ios_basicc,typedef basic_ios<char> ios;<br><br>class ios<br>{<br>public:<br>    enum {    app = 0x0001, ate = 0x0002, binary = 0x0004,<br>        in = 0x0008,  out = 0x0010, trunc = 0x0020 };<br>    ....<br>private:<br>    unsigned int flags;<br>};<br><br>注意上面enum语句中,每一个数值只?位是1Q其余是0Q这个很重要Q你可以它化成2q制看看?br><br>现在flags相应的位讄?, 可以q样?nbsp;flags |= app。这个等于flags = flags | app, Z么呢? app只有1位是1Q其余是0Q因? | 1 = 0Q?nbsp;0 | 0 = 0Q?nbsp;q样0对应的位是不变的。? | 1 = 1, 1 | 0 = 1, 1对应的位不论原来是什么状态,都一定ؓ1。如果想要将几个位都讄?Q可以这样做 flags |= (app | ate | binary)。因为每个enum常数各有一位ؓ1, 与运之后就?位ؓ1Q就如上面的分析Q就可以那3位都讄?, 其余位不变。这个就是标志可以组合v来用的原因。也可以?l合hQ原因在?下面的数字是2q制)0001 + 0010 + 0100 = 0111 跟与q算l果一栗不q不提倡用+, 考虑(app | ate | binary)要是我不心写多了个标志|(app | ate | ate | binary)l果q是正确的,如果?的话Q就会生进位,l果׃错误。通常我们不知道原先已l组合了多少个标志gQ用或运会安全?br><br>现在flags对应的位讄?, 可以q样?nbsp;flags &= ~app。相当于 flags = flags & (~app). app取反之后Q只?位是0Q其余是1Q做与运之后,1对应的位q不会改变,0对应的ؓ不管原来??Q都肯定?Q这样就对应的位设|了0。同样同时设|几个标志位可以q样做,flags &= ~(app | ate | binary)?br><br>现在flags对应的位Q如果是1变?Q如果是0变?Q可以这样做 flags ^= app。同时设|几个标志位可以写成 flags ^= (app | ate | binary)。不再做分析了,不然太|嗦了。不q也l大家一个例子,你查查Ascii表,会发现对应的大小写字母是相差倒数W?位,可以用这L函数l一的将大写变成写Q小写变成大写?br>void xchgUppLow(string& letters)<br>{<br>        const unsigned int mask = (1<<5);<br><br>        for (size_t i=0; i<letters.length(); i++)<br>                letters[i] ^= mask;<br>}<br>前提是输入的string一定要全是字母, 而要x操作字母Q可以在原来基础上加个判断?br><br>好啦Q上面已l可以设|flags的对应位gQ要是判断呢Q可以这样写 if (flags & app) q样可以判断对应的位值是否ؓ1, 因ؓC\C++语言中非0q。app只有一位是1Q其余是0Q如? flags的对应位也是0Q在与操作下得到结?Q反之非0Q这样就可以判断标志位了?br><br>//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><br>上面关于标志值的操作׃l完毕。其实在C++中已l有了个bitset了,没有必要去自p行低阶的位运,上面的四个操作在bitset中分别叫做set, reset, flip, test。不q在C中,q样的代码还很常? 反正知道多点也没有坏处?br><br>?nbsp;windows API ~程Q你也经怼到q样的标志|要互相组合,可以用|, 也可以用+(只是用|Q理׃面说?. 它的标志g是这样定义的Q不q用#define<br>#define WS_BORDER    0x0001<br>#define WS_CAPTION    0x0002<br>......<br>当初我就是想不明白ؓ什么可以用|或者用+来组合,现在知道了?br><br>(注:上面出现的数字是我自׃的,到底实际怎么定义其实没有关系Q只要保证只有一位是1Q其余是0可以的? 因ؓ~程的时候用的是帔R|没有Lȝ接用数值的)<br><br>//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><br>其实Q位q算q有很多用处。比如移位相当于乘除2的幂?不过通常~译器也乘?的幂C化成汇编的移位指令,所以没有必要不要这样卖弄了。汇~的UM指o有两l,分别针对有符号和无符L, 我猜惛_C\C++的同一UMq算针对有符h数和无符h数的不同Q会Ҏ(gu)情况~译成不同的汇编UM指oQ不q没有去证实), 其实UM更用得多的地Ҏ(gu)L造一个掩? 比如上面的mask = (1<<5);<br><br>q有&q算Q有时候可以用来求余数。比?nbsp;value & (1<<4 - 1) q相当于value的高位全变成0了,效果{于 value % 8. <br><br>q有值得一提的是^q算Q它有个很特D的性质。比?nbsp;A ^= B, 变成另一个数Q跟着再执行A ^= BQ又变回原来的数了,不信你可以列真D或者化逻辑式看看。就因ؓq个性质Q^有很多用途。比如加密,你将原文看成A, 用同一个B异或一ơ,q当于加密Q跟着在用B异或一ơ,相当于解密。不q这h很容易破解就是了。要是一个B不够Q还可以加个C, 比如A ^= B, A ^= C, A ^= C, A ^= B, 恢复原状?br><br>下面一个小E序Q用异或交换两个数字?br>int x = 3;<br>int y = 4;<br><br>x ^= y;<br>y ^= x;<br>x ^= y;<br><br>其实何止交换数字Q连交换对象也可以的<br>template <typename T><br>void swap(T& obj1, T& obj2)<br>{<br>        const int sizeOfObj = sizeof(T);<br>        char* pt1 = (char*)&obj1;<br>        char* pt2 = (char*)&obj2;<br><br>        for (size_t i=0; i<sizeOfObj; i++)<br>        {<br>                pt1[i] ^= pt2[i];<br>                pt2[i] ^= pt1[i];<br>                pt1[i] ^= pt2[i];<br>        }<br>}<br><br>q有异或操作q可以用在图象的光栅操作。我们知道,颜色也是用二q制来表C的Q对颜色q行不同的位q算Q就可以得到不同的光栅。因为异或的Ҏ(gu)性质Q我们用异或操作的光栅画了副图,跟着再在原来的地方画一ơ,那副囑ְ刷除了。这样可以用来显C动画而不用保存原来的d信息。以前我写过个双人的贪食蛇,q了异或光栅。因景色是白色的Q也是?Q作A ^ 1 = A, 所以用dMơ是M讑֮的颜Ԍ再画一ơ就恢复。最有趣的是两蛇怺的时候,颜色也会作异或叠加,产生一U新的颜色了Q离开的时候也会自动恢复?br>//>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>><br>好啦Q够长了Q就停止吧。在最后再l大家一D代码,是用来看看对象在内存中的位值的。可以看看?br>string bitsOfUChar(unsigned char c)<br>{<br>        const int numOfBitsInUChar = 8;<br>        unsigned int mask = (1<<7);<br>        string result(8, '0');<br><br>        for (size_t i=0; i<numOfBitsInUChar; i++)<br>        {<br>                if ( mask & c)<br>                        result[i] = '1';<br><br>                mask >>= 1;<br>        }<br><br>        return result;<br>}<br><br>template <typename T><br>string bitsInMemory(const T& obj)<br>{<br>        int sizeOfObj = sizeof(obj);<br>        unsigned char* pt = (unsigned char*)&obj;<br>        string result;<br><br>        for (size_t i=0; i<sizeOfObj; i++)<br>        {<br>                result += bitsOfUChar(pt[i]);<br>                result += ' ';<br>        }<br><br>        return result;<br>}<br><br>比如bitsInMemory(12)Q会输出00001100 00000000 00000000 00000000, 我就知道我自q机器是小N序的了?br></p> <img src ="http://www.shnenglu.com/Walker/aggbug/80466.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.shnenglu.com/Walker/" target="_blank">漫步者?…?K?/a> 2009-04-19 20:44 <a href="http://www.shnenglu.com/Walker/articles/80466.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>法链接http://www.shnenglu.com/Walker/articles/80380.html漫步者?amp;…?K?/dc:creator>漫步者?amp;…?K?/author>Sat, 18 Apr 2009 11:35:00 GMThttp://www.shnenglu.com/Walker/articles/80380.htmlhttp://www.shnenglu.com/Walker/comments/80380.htmlhttp://www.shnenglu.com/Walker/articles/80380.html#Feedback0http://www.shnenglu.com/Walker/comments/commentRss/80380.htmlhttp://www.shnenglu.com/Walker/services/trackbacks/80380.htmlhttp://wz.csdn.net/tag/%e7%ae%97%e6%b3%95/2/

]]>
˾þô߽Ʒ| þAV뾫Ʒ| ƷѾþþþùһ| 91Ʒ91þۺ| ˳ɾƷþþþ| ˾þùѹۿƵ| þùƷ͵99| þù׾Ʒҹ| Ʒŷþþþ޹| ƷþþþĻһ| þŮƵ| þþƷ| 鶹AVһþ| պƷþĻ| ҹƷþþþþþþ| vaþþþúݺ| Ʒþþþ| þþƷƷƾ | ձWVһһþ㽶| þavСݲ| 2020˾þþƷ| þˬƬav| þùֱ| Ʒʾþþþ999Ұ| ھƷ˾þþþӰԺ԰| 99þҹҹƷ| þþþAVƬ| ŷһþ| þþþӰԺС| þþžžþƷ| 뾫ƷþɪӰ| þ99Ʒþþþþþò| ֻƬþøպ| þùֱ| þþþþAŷAV| Ʒþþþþ| պþþþƷӰԺҳ| ŷսþþþþþþ | þþžžþƷֱ| 볬鱬Ļþ| ŷۺҹҹþ|