<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>博客园-清风竹林</title><link>http://www.cnblogs.com/flappy/</link><description>ぷ雪飘绛梅映残红 
&amp;nbsp;&amp;nbsp; ぷ花舞霜飞映苍松 &amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;&amp;nbsp;----- Do more,suffer less</description><language>zh-cn</language><lastBuildDate>Sat, 30 Aug 2008 01:27:26 GMT</lastBuildDate><pubDate>Sat, 30 Aug 2008 01:27:26 GMT</pubDate><ttl>60</ttl><item><title>J2ME中的基础碰撞检测算法</title><link>http://www.cnblogs.com/flappy/archive/2008/07/27/1252415.html</link><dc:creator>李现民</dc:creator><author>李现民</author><pubDate>Sun, 27 Jul 2008 05:48:00 GMT</pubDate><guid>http://www.cnblogs.com/flappy/archive/2008/07/27/1252415.html</guid><wfw:comment>http://www.cnblogs.com/flappy/comments/1252415.html</wfw:comment><comments>http://www.cnblogs.com/flappy/archive/2008/07/27/1252415.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/flappy/comments/commentRss/1252415.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/flappy/services/trackbacks/1252415.html</trackback:ping><description><![CDATA[<p align="center"><span style="font-family: 宋体;">作者：陈跃峰</span></p>
<p align="center"><span style="font-family: 宋体;">出自：</span>http://blog.csdn.net/mailbomb</p>
<p>&nbsp;</p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体;">在游戏中，经常需要进行碰撞检测的实现，例如判断前面是否有障碍以及判断子弹是否击中飞机，都是检测两个物体是否发生碰撞，然后根据检测的结果做出不同的处理。</span></p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体;">进行碰撞检测的物体可能有些的形状和复杂，这些需要进行组合碰撞检测，就是将复杂的物体处理成一个一个的基本形状的组合，然后分别进行不同的检测。</span></p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体;">下面简单介绍一下两种最基本的形状进行碰撞的时候进行的处理。</span></p>
<p><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1</span><span style="font-family: 宋体;">、矩形和矩形进行碰撞</span></p>
<p style="margin: 0cm 0cm 0pt 21pt;"><span>&nbsp;&nbsp; </span><span style="font-family: 宋体;">一般规则的物体碰撞都可以处理成矩形碰撞，实现的原理就是检测两个矩形是否重叠。我们假设矩形</span>1<span style="font-family: 宋体;">的参数是：左上角的坐标是</span>(x1,y1)<span style="font-family: 宋体;">，宽度是</span>w1<span style="font-family: 宋体;">，高度是</span>h1<span style="font-family: 宋体;">；矩形</span>2<span style="font-family: 宋体;">的参数是：左上角的坐标是</span>(x2,y2)<span style="font-family: 宋体;">，宽度是</span>w2<span style="font-family: 宋体;">，高度是</span>h2<span style="font-family: 宋体;">。</span></p>
<p style="margin: 0cm 0cm 0pt 21pt;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体;">在检测时，数学上可以处理成比较中心点的坐标在</span>x<span style="font-family: 宋体;">和</span>y<span style="font-family: 宋体;">方向上的距离和宽度的关系。即两个矩形中心点在</span>x<span style="font-family: 宋体;">方向的距离的绝对值小于等于矩形宽度和的二分之一，同时</span>y<span style="font-family: 宋体;">方向的距离的绝对值小于等于矩形高度和的二分之一。下面是数学表达式：</span></p>
<p style="margin: 0cm 0cm 0pt 21pt; text-indent: 21pt;">x<span style="font-family: 宋体;">方向：</span><span>&nbsp;&nbsp; | (x1 + w1 / 2) &#8211; (x2 + w2/2) | &lt; |(w1 + w2) / 2|</span></p>
<p style="margin: 0cm 0cm 0pt 21pt; text-indent: 21pt;">y<span style="font-family: 宋体;">方向：</span><span>&nbsp;&nbsp; | (y1 + h1 / 2) &#8211; (y2 + h2/2) | &lt; |(h1 + h2) / 2|</span></p>
<p style="margin: 0cm 0cm 0pt 21pt;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体;">在程序中，只需要将上面的条件转换成代码就可以实现了。</span></p>
<p style="margin: 0cm 0cm 0pt 21pt;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体;">但是矩形碰撞只是一种比较粗糙的碰撞检测方法，因为很多实际的物体可能不是一个规则的矩形。</span></p>
<p style="margin: 0cm 0cm 0pt 21pt;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体;">下面介绍一下圆形碰撞。</span></p>
<p style="margin: 0cm 0cm 0pt 21pt;">2<span style="font-family: 宋体;">、圆形和圆形的碰撞</span></p>
<p style="margin: 0cm 0cm 0pt 21pt;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体;">圆形和圆形的碰撞应该说是一种最简单的碰撞，因为在数学上对于两个圆形是否发生重叠，有计算两个圆心之间的距离的公式。那么条件就变为：计算两个圆心之间的距离是否小于两个圆的半径和。</span></p>
<p style="margin: 0cm 0cm 0pt 21pt;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体;">假设圆形</span>1<span style="font-family: 宋体;">的左上角坐标是</span>(x1,y1)<span style="font-family: 宋体;">，半径是</span>r1<span style="font-family: 宋体;">，圆形</span>2<span style="font-family: 宋体;">的左上角的坐标是</span>(x2,y2)<span style="font-family: 宋体;">，半径是</span>r2<span style="font-family: 宋体;">。</span></p>
<p style="margin: 0cm 0cm 0pt 21pt;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体;">因为</span>MIDP1.0<span style="font-family: 宋体;">中没有浮点数，而且浮点数的运算比较慢，所以我们将条件做一个简单的变换：对于条件的两边都进行平方，这样就去掉了开方的运算步骤。</span></p>
<p style="margin: 0cm 0cm 0pt 21pt;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体;">下面是数学表达式：</span></p>
<p style="margin: 0cm 0cm 0pt 21pt;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;(x1 &#8211; x2)</span><sup>2</sup> + (y1 &#8211; y2)<sup>2</sup> &lt; (r1 + r2)<sup>2</sup></p>
<p style="margin: 0cm 0cm 0pt 21pt;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体;">在程序中，只需要将上面的条件转换成代码就可以了。</span></p>
<p style="margin: 0cm 0cm 0pt 21pt;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span></p>
<p style="margin: 0cm 0cm 0pt 21pt;"><span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-family: 宋体;">上面介绍的只是最基本的碰撞检测算法的实现，而实际的编程过程中遇到的碰撞检测问题要比这些复杂很多，还需要其他形式的检测，还需要进行更加深入的学习。</span></p>
<p>&nbsp;</p>
<p style="margin: 0cm 0cm 0pt 21pt;">email:cqucyf@263.net</p><img src ="http://www.cnblogs.com/flappy/aggbug/1252415.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41961/" target="_blank">[新闻]Microsoft F# CTP(2008年9月)</a>]]></description></item><item><title> 告别cpp&amp;h：hpp文件编写心得(转) </title><link>http://www.cnblogs.com/flappy/archive/2008/07/09/1238736.html</link><dc:creator>李现民</dc:creator><author>李现民</author><pubDate>Wed, 09 Jul 2008 03:05:00 GMT</pubDate><guid>http://www.cnblogs.com/flappy/archive/2008/07/09/1238736.html</guid><wfw:comment>http://www.cnblogs.com/flappy/comments/1238736.html</wfw:comment><comments>http://www.cnblogs.com/flappy/archive/2008/07/09/1238736.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/flappy/comments/commentRss/1238736.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/flappy/services/trackbacks/1238736.html</trackback:ping><description><![CDATA[hpp，顾名思义等于.h加上.cpp，在boost、<font size="2">Xerces等开源库中频繁出现，偶在机缘巧合之下，学得一招半式，遂记录如下，以供参考学习。</font>
<div><font size="2">&nbsp;&nbsp;&nbsp;
hpp，其实质就是将.cpp的实现代码混入.h头文件当中，定义与实现都包含在同一文件，则该类的调用者只需要include该hpp文件即可，无需再
将cpp加入到project中进行编译。而实现代码将直接编译到调用者的obj文件中，不再生成单独的obj，采用hpp将大幅度减少调用
project中的cpp文件数与编译次数，也不用再发布烦人的lib与dll，因此非常适合用来编写公用的开源库。</font></div>
<div><font size="2">&nbsp;&nbsp;&nbsp; hpp的优点不少，但是编写中有以下几点要注意：</font></div>
<div><font size="2">&nbsp;&nbsp;&nbsp; </font></div>
<div><font size="2">&nbsp;&nbsp;&nbsp; <strong>1、不可包含全局对象和全局函数。</strong></font></div>
<div><font size="2">&nbsp;&nbsp;&nbsp; 由于hpp本质上是作为.h被调用者include，所以当hpp文件中存在全局对象或者全局函数，而该hpp被多个调用者include时，将在链接时导致符号重定义错误。要避免这种情况，需要去除全局对象，将全局函数封装为类的静态方法。</font></div>
<div>&nbsp;</div>
<div><font size="2">&nbsp;&nbsp;&nbsp; <strong>2、类之间不可循环调用。</strong></font></div>
<div><font size="2">&nbsp;&nbsp;&nbsp; 在.h和.cpp的场景中，当两个类或者多个类之间有循环调用关系时，只要预先在头文件做被调用类的声明即可，如下：</font></div>
<div><font size="2">&nbsp;&nbsp;&nbsp; <font color="#0000ff">class </font>B;</font></div>
<div><font size="2">&nbsp;&nbsp;&nbsp; <font color="#0000ff">class </font>A{</font></div>
<div><font size="2">&nbsp;&nbsp;&nbsp; <font color="#0000ff">public:</font></font></div>
<div><font size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void someMethod(B b);</font></div>
<div><font size="2">&nbsp;&nbsp;&nbsp; };</font></div>
<div><font size="2">&nbsp;&nbsp;&nbsp; <font color="#0000ff">class </font>B{</font></div>
<div><font size="2">&nbsp;&nbsp;&nbsp; <font color="#0000ff">public</font>:</font></div>
<div><font size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void someMethod(A a);</font></div>
<div><font size="2">&nbsp;&nbsp;&nbsp; };</font></div>
<div>&nbsp;&nbsp;&nbsp;
在hpp场景中，由于定义与实现都已经存在于一个文件，调用者必需明确知道被调用者的所有定义，而不能等到cpp中去编译。因此hpp中必须整理类之间调
用关系，不可产生循环调用。同理，对于当两个类A和B分别定义在各自的hpp文件中，形如以下的循环调用也将导致编译错误：</div>
<div>&nbsp;&nbsp;&nbsp; <font color="#008000">//a.hpp</font></div>
<div>&nbsp;&nbsp;&nbsp; <font color="#0000ff">#include "b.hpp"</font></div>
<div>&nbsp;&nbsp;&nbsp; <font color="#0000ff">class </font>A{</div>
<div>&nbsp;&nbsp;&nbsp; <font color="#0000ff">public</font>:</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void someMethod(B b);</div>
<div>&nbsp;&nbsp;&nbsp; };</div>
<div>&nbsp;</div>
<div>
<div>&nbsp;&nbsp;&nbsp; <font color="#008000">//b.hpp</font></div>
<div>&nbsp;&nbsp;&nbsp; <font color="#0000ff">#include "a.hpp"</font></div>
<div>&nbsp;&nbsp;&nbsp; <font color="#0000ff">class </font>B{</div>
<div>&nbsp;&nbsp;&nbsp; <font color="#0000ff">public</font>:</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; void someMethod(A a);</div>
<div>&nbsp;&nbsp;&nbsp; };</div>
</div>
<div>&nbsp;</div>
<div><font size="2">&nbsp;&nbsp;&nbsp; <strong>3、不可使用静态成员。</strong></font></div>
<div><font size="2">&nbsp;&nbsp;&nbsp; 静态成员的使用限制在于如果类含有静态成员，则在hpp中必需加入静态成员初始化代码，当该hpp被多个文档include时，将产生符号重定义错误。唯一的例外是const static整型成员，因为在vs2003中，该类型允许在定义时初始化，如：</font></div>
<div><font size="2">&nbsp;&nbsp;&nbsp; class A{</font></div>
<div><font size="2">&nbsp;&nbsp;&nbsp;&nbsp;public:</font></div>
<div><font size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; const static int intValue = 123;</font></div>
<div><font size="2">&nbsp;&nbsp;&nbsp;&nbsp;};</font></div>
<div><font size="2">&nbsp;&nbsp;&nbsp; 由于静态成员的使用是很常见的场景，无法强制清除，因此可以考虑以下几种方式（以下示例均为同一类中方法）</font></div>
<div><font size="2">&nbsp;&nbsp;&nbsp; 1.类中仅有一个静态成员时，且仅有一个调用者时，可以通过局域静态变量模拟</font></div>
<div><font size="2">&nbsp;&nbsp;&nbsp; <font color="#008000">//方法模拟获取静态成员</font></font></div>
<div><font size="2">&nbsp;&nbsp;&nbsp; <font color="#0000ff">someType </font>getMember()</font></div>
<div><font size="2">&nbsp;&nbsp;&nbsp; {</font></div>
<div><font size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static <font color="#0000ff">someType </font>value(xxx);<font color="#008000">//作用域内静态变量</font></font></div>
<div><font size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color="#0000ff">return </font>value;</font></div>
<div><font size="2">&nbsp;&nbsp;&nbsp; }</font></div>
<div>&nbsp;&nbsp;&nbsp; 2.类中有多个方法需要调用静态成员，而且可能存在多个静态成员时，可以将每个静态成员封装一个模拟方法，供其他方法调用。</div>
<div>
<div><font size="2">&nbsp;
<div><font size="2">&nbsp;&nbsp;&nbsp; <font color="#0000ff">someType </font>getMemberA()</font></div>
<div><font size="2">&nbsp;&nbsp;&nbsp; {</font></div>
<div><font size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static <font color="#0000ff">someType </font>value(xxx);<font color="#008000">//作用域内静态变量</font></font></div>
<div><font size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color="#0000ff">return </font>value;</font></div>
<div><font size="2">&nbsp;&nbsp;&nbsp; }</font></div>
<div>&nbsp;&nbsp;&nbsp; <font color="#0000ff">someType </font>getMemberB()
<div><font size="2">&nbsp;&nbsp;&nbsp; {</font></div>
<div><font size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; static <font color="#0000ff">someType </font>value(xxx);<font color="#008000">//作用域内静态变量</font></font></div>
<div><font size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color="#0000ff">return </font>value;</font></div>
<div><font size="2">&nbsp;&nbsp;&nbsp; }</font></div>
<div>&nbsp;&nbsp; <font color="#0000ff">void </font>accessMemberA()</div>
</div>
</font></div>
<div><font size="2">&nbsp;&nbsp;&nbsp; {</font></div>
<div><font size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color="#0000ff">someType </font>member = getMemberA();<font color="#008000">//获取静态成员</font></font></div>
<div><font size="2">&nbsp;&nbsp;&nbsp;&nbsp;};</font></div>
<div><font size="2" color="#008000">&nbsp;&nbsp;&nbsp; //获取两个静态成员</font></div>
<div>
<div><font size="2">&nbsp;&nbsp;&nbsp; <font color="#0000ff">void </font>accessStaticMember()</font></div>
<div><font size="2">&nbsp;&nbsp;&nbsp; {</font></div>
<div><font size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color="#0000ff">someType a</font>&nbsp;= getMemberA();<font color="#008000">//获取静态成员</font></font></div>
<div><font size="2" color="#008000">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color="#0000ff">someType b </font><font color="#000000">= getMemberB();</font></font></div>
<div><font size="2">&nbsp;&nbsp;&nbsp;&nbsp;};</font></div>
<div>&nbsp;</div>
<div><font size="2">&nbsp;&nbsp;&nbsp; 3.第二种方法对于大部分情况是通用的，但是当所需的静态成员过多时，编写封装方法的工作量将非常巨大，在此种情况下，建议使用Singleton模式，将被调用类定义成普通类，然后使用Singleton将其变为全局唯一的对象进行调用。</font></div>
<div><font size="2">&nbsp;&nbsp;&nbsp;&nbsp;如原h+cpp下的定义如下：</font></div>
<div><font size="2">&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">class </font>A{</font></div>
<div><font size="2">&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">public</font>:</font></div>
<div><font size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color="#0000ff">type </font>getMember(){</font></div>
<div><font size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return member;</font></div>
<div><font size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</font></div>
<div><font size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color="#0000ff">static type</font> member;<font color="#008000">//静态成员</font></font></div>
<div><font size="2">&nbsp;&nbsp;&nbsp; }</font></div>
<div>&nbsp;</div>
<div><font size="2">&nbsp;&nbsp;&nbsp; 采用singleton方式，实现代码可能如下（singleton实现请自行查阅相关文档）</font></div>
<div><font size="2" color="#008000">&nbsp;&nbsp;&nbsp; //实际实现类</font></div>
<div>
<div><font size="2">&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">class </font>Aprovider{</font></div>
<div><font size="2">&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">public</font>:</font></div>
<div><font size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color="#0000ff">type </font>getMember(){</font></div>
<div><font size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return member;</font></div>
<div><font size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</font></div>
<div><font size="2"><font color="#0000ff">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &nbsp;type</font> member;<font color="#008000">//变为普通成员</font></font></div>
<div><font size="2">&nbsp;&nbsp;&nbsp; }</font></div>
<div>&nbsp;</div>
<div><font size="2" color="#008000">&nbsp;&nbsp;&nbsp; //提供给调用者的接口类</font></div>
<div>
<div><font size="2">&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">class </font>A{</font></div>
<div><font size="2">&nbsp;&nbsp;&nbsp;&nbsp;<font color="#0000ff">public</font>:</font></div>
<div><font size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <font color="#0000ff">type </font>getMember(){</font></div>
<div><font size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return&nbsp;Singleton&lt;<font color="#0000ff">AProvider</font>&gt;::getInstance()-&gt;getMember();</font></div>
<div><font size="2">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }</font></div>
<div><font size="2">&nbsp;&nbsp;&nbsp; }</font></div>
</div>
</div>
</div>
</div>
<img src ="http://www.cnblogs.com/flappy/aggbug/1238736.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41960/" target="_blank">[新闻]微软4.86亿美元收购Greenfield</a>]]></description></item><item><title>平台无关性多线程库－C++ Boost Thread 编程指南(转)</title><link>http://www.cnblogs.com/flappy/archive/2008/07/08/1237977.html</link><dc:creator>李现民</dc:creator><author>李现民</author><pubDate>Tue, 08 Jul 2008 02:14:00 GMT</pubDate><guid>http://www.cnblogs.com/flappy/archive/2008/07/08/1237977.html</guid><wfw:comment>http://www.cnblogs.com/flappy/comments/1237977.html</wfw:comment><comments>http://www.cnblogs.com/flappy/archive/2008/07/08/1237977.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/flappy/comments/commentRss/1237977.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/flappy/services/trackbacks/1237977.html</trackback:ping><description><![CDATA[<span id="Post.ascx_ViewPost_PreviousAndNextEntriesUp">
<h3><a href="http://blog.csdn.net/Feisy/archive/2008/04/11/2282925.aspx">新一篇:&nbsp;平台无关性程序的构造</a></h3>
</span>
<script>function StorePage(){d=document;t=d.selection?(d.selection.type!='None'?d.selection.createRange().text:''):(d.getSelection?d.getSelection():'');void(keyit=window.open('http://www.365key.com/storeit.aspx?t='+escape(d.title)+'&u='+escape(d.location.href)+'&c='+escape(t),'keyit','scrollbars=no,width=475,height=575,left=75,top=20,status=no,resizable=yes'));keyit.focus();}</script>
<h3><a style="width: 20px; height: 20px; text-indent: 20px; background-repeat: no-repeat; background-image: url(/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif);" name="0 前言"></a>0 前言 </h3>
标准C++线程即将到来。CUJ预言它将衍生自Boost线程库，现在就由Bill带领我们探索一下Boost线程库。
<p>&nbsp;</p>
<p>就在几年前，用多线程执行程序还是一件非比寻常的事。然而今天互联网应用服务程序普遍使用多线程来提高与多客户链接时的效率；为了达到最大的吞吐
量，事务服务器在单独的线程上运行服务程序；GUI应用程序将那些费时，复杂的处理以线程的形式单独运行，以此来保证用户界面能够及时响应用户的操作。这
样使用多线程的例子还有很多。 </p>
<p>&nbsp;</p>
<p>但是C++标准并没有涉及到多线程，这让程序员们开始怀疑是否可能写出多线程的C++程序。尽管不可能写出符合标准的多线程程序，但是程序员们还是
会使用支持多线程的操作系统提供的多线程库来写出多线程C++程序。但是这样做至少有两个问题：这些库大部分都是用C语言完成的，如果在C++程序中要使
用这些库就必须十分小心；还有，每一个操作系统都有自己的一套支持多线程的类库。因此，这样写出来得代码是没有标准可循的，也不是到处都适用的（non-
portable)。Boost线程库就是为了解决所有这些问题而设计的。 </p>
<p>Boost是由C++标准委员会类库工作组成员发起，致力于为C++开发新的类库的组织。现在它已经有近2000名成员。许多库都可以在Boost源码的发布版本中找到。为了使这些类库是线程安全的（thread-safe)，Boost线程库被创建了。 </p>
<p>许多C++专家都投身于Boost线程库的开发中。所有接口的设计都是从0开始的，并不是C线程API的简单封装。许多C++特性（比如构造函数和
析构函数，函数对象（function
object)和模板）都被使用在其中以使接口更加灵活。现在的版本可以在POSIX,Win32和Macintosh Carbon平台下工作。 </p>
<h3><a style="width: 20px; height: 20px; text-indent: 20px; background-repeat: no-repeat; background-image: url(/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif);" name="1 创建线程"></a>1 创建线程 </h3>
就像std::fstream类就代表一个文件一样，boost::thread类就代表一个可执行的线程。缺省构造函数创建一个代表当前执行线程的实
例。一个重载的构造函数以一个不需任何参数的函数对象作为参数，并且没有返回值。这个构造函数创建一个新的可执行线程，它调用了那个函数对象。
<p>&nbsp;</p>
<p>起先，大家认为传统C创建线程的方法似乎比这样的设计更有用，因为C创建线程的时候会传入一个void*指针，通过这种方法就可以传入数据。然而，
由于Boost线程库是使用函数对象来代替函数指针，那么函数对象本身就可以携带线程所需的数据。这种方法更具灵活性，也是类型安全（type-
safe)的。当和Boost.Bind这样的功能库一起使用时，这样的方法就可以让你传递任意数量的数据给新建的线程。 </p>
<p>&nbsp;</p>
<p>目前，由Boost线程库创建的线程对象功能还不是很强大。事实上它只能做两项操作。线程对象可以方便使用==和!=进行比较来确定它们是否是代表
同一个线程；你还可以调用boost::thread::join来等待线程执行完毕。其他一些线程库可以让你对线程做一些其他操作（比如设置优先级，甚
至是取消线程）。然而，由于要在普遍适用（portable）的接口中加入这些操作不是简单的事，目前仍在讨论如何将这些操组加入到Boost线程库中。
</p>
<p>&nbsp;</p>
<p>Listing1展示了boost::thread类的一个最简单的用法。 新建的线程只是简单的在std::out上打印&#8220;hello,world&#8221;，main函数在它执行完毕之后结束。 </p>
<p><br />
例1： </p>
<div class="BeautifierPlugin">
<div class="fragment">
<pre style="padding-bottom: 0px;">
<pre style="padding-bottom: 0px;"><font color="#000080">#include</font> &lt;boost/thread/thread.hpp&gt;<br />
<font color="#000080">#include</font> &lt;iostream&gt;<br />
<br />
<font color="#a52a2a">void</font> hello()<br />
{<br />
std::cout &lt;&lt;<br />
"<font color="#0000ff">Hello world, I'm a thread!</font>"<br />
&lt;&lt; std::endl;<br />
}<br />
<br />
<font color="#a52a2a">int</font> main(<font color="#a52a2a">int</font> argc, <font color="#a52a2a">char</font>* argv[])<br />
{<br />
boost::thread thrd(&amp;hello);<br />
thrd.join();<br />
<font color="#a52a2a">return</font> 0;<br />
}</pre>
<br />
</pre>
</div>
</div>
<h3><a style="width: 20px; height: 20px; text-indent: 20px; background-repeat: no-repeat; background-image: url(/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif);" name="2 互斥体"></a>2 互斥体 </h3>
任何写过多线程程序的人都知道避免不同线程同时访问共享区域的重要性。如果一个
线程要改变共享区域中某个数据，而与此同时另一线程正在读这个数据，那么结果将是未定义的。为了避免这种情况的发生就要使用一些特殊的原始类型和操作。其
中最基本的就是互斥体（mutex，mutual
exclusion的缩写）。一个互斥体一次只允许一个线程访问共享区。当一个线程想要访问共享区时，首先要做的就是锁住（lock）互斥体。如果其他的
线程已经锁住了互斥体，那么就必须先等那个线程将互斥体解锁，这样就保证了同一时刻只有一个线程能访问共享区域。
<p>&nbsp;</p>
<p>互斥体的概念有不少变种。Boost线程库支持两大类互斥体，包括简单互斥体（simple mutex)和递归互斥体（recursive
mutex)。如果同一个线程对互斥体上了两次锁，就会发生死锁（deadlock），也就是说所有的等待解锁的线程将一直等下去。有了递归互斥体，单个
线程就可以对互斥体多次上锁，当然也必须解锁同样次数来保证其他线程可以对这个互斥体上锁。 </p>
<p>&nbsp;</p>
<p>在这两大类互斥体中，对于线程如何上锁还有多个变种。一个线程可以有三种方法来对一个互斥体加锁： </p>
<ol>
    <li>一直等到没有其他线程对互斥体加锁。 </li>
    <li>如果有其他互斥体已经对互斥体加锁就立即返回。 </li>
    <li>一直等到没有其他线程互斥体加锁，直到超时。 </li>
</ol>
<p>似乎最佳的互斥体类型是递归互斥体，它可以使用所有三种上锁形式。然而每一个变种都是有代价的。所以Boost线程库允许你根据不同的需要使用最有效率的互斥体类型。Boost线程库提供了6中互斥体类型，下面是按照效率进行排序： </p>
<p>&nbsp;</p>
<div class="BeautifierPlugin">
<div class="fragment">
<pre style="padding-bottom: 0px;">
<pre style="padding-bottom: 0px;">boost::mutex,<br />
boost::try_mutex, <br />
boost::timed_mutex, <br />
boost::recursive_mutex, <br />
boost::recursive_try_mutex,  <br />
boost::recursive_timed_mutex </pre>
<br />
</pre>
</div>
</div>
如果互斥体上锁之后没有解锁就会发生死锁。这是一个很普遍的错误，Boost线程库就是要将其变成不可能（至少时很困难）。直接对互斥体上锁和解锁对于
Boost线程库的用户来说是不可能的。mutex类通过teypdef定义在RAII中实现的类型来实现互斥体的上锁和解锁。这也就是大家知道的
Scope
Lock模式。为了构造这些类型，要传入一个互斥体的引用。构造函数对互斥体加锁，析构函数对互斥体解锁。C++保证了析构函数一定会被调用，所以即使是
有异常抛出，互斥体也总是会被正确的解锁。
<p>这种方法保证正确的使用互斥体。然而，有一点必须注意：尽管Scope
Lock模式可以保证互斥体被解锁，但是它并没有保证在异常抛出之后贡献资源仍是可用的。所以就像执行单线程程序一样，必须保证异常不会导致程序状态异
常。另外，这个已经上锁的对象不能传递给另一个线程，因为它们维护的状态并没有禁止这样做。 </p>
<p>&nbsp;</p>
<p>List2给出了一个使用boost::mutex的最简单的例子。例子中共创建了两个新的线程，每个线程都有10次循环，在std::cout上
打印出线程id和当前循环的次数，而main函数等待这两个线程执行完才结束。std::cout就是共享资源，所以每一个线程都使用一个全局互斥体来保
证同时只有一个线程能向它写入。 </p>
<p>&nbsp;</p>
<p>许多读者可能已经注意到List2中传递数据给线程还必须的手工写一个函数。尽管这个例子很简单，如果每一次都要写这样的代码实在是让人厌烦的事。
别急，有一种简单的解决办法。函数库允许你通过将另一个函数绑定，并传入调用时需要的数据来创建一个新的函数。
List3向你展示了如何使用Boost.Bind库来简化List2中的代码，这样就不必手工写这些函数对象了。 </p>
<p>例2： </p>
<div class="BeautifierPlugin">
<div class="fragment">
<pre style="padding-bottom: 0px;">
<pre style="padding-bottom: 0px;"><font color="#000080">#include</font> &lt;boost/thread/thread.hpp&gt;<br />
<font color="#000080">#include</font> &lt;boost/thread/mutex.hpp&gt;<br />
<font color="#000080">#include</font> &lt;iostream&gt;<br />
<br />
boost::mutex io_mutex;<br />
<br />
<font color="#a52a2a">struct</font> count<br />
{<br />
count(<font color="#a52a2a">int</font> id) : id(id) { }<br />
<br />
<font color="#a52a2a">void</font> <font color="#a52a2a">operator</font>()()<br />
{<br />
<font color="#a52a2a">for</font> (<font color="#a52a2a">int</font> i = 0; i &lt; 10; ++i)<br />
{<br />
boost::mutex::scoped_lock<br />
lock(io_mutex);<br />
std::cout &lt;&lt; id &lt;&lt; "<font color="#0000ff">: </font>"<br />
&lt;&lt; i &lt;&lt; std::endl;<br />
}<br />
}<br />
<br />
<font color="#a52a2a">int</font> id;<br />
};<br />
<br />
<font color="#a52a2a">int</font> main(<font color="#a52a2a">int</font> argc, <font color="#a52a2a">char</font>* argv[])<br />
{<br />
boost::thread thrd1(count(1));<br />
boost::thread thrd2(count(2));<br />
thrd1.join();<br />
thrd2.join();<br />
<font color="#a52a2a">return</font> 0;<br />
}</pre>
<br />
</pre>
</div>
</div>
<p>例3： // 这个例子和例2一样，除了使用Boost.Bind来简化创建线程携带数据，避免使用函数对象 </p>
<div class="BeautifierPlugin">
<div class="fragment">
<pre style="padding-bottom: 0px;">
<pre style="padding-bottom: 0px;"><font color="#000080">#include</font> &lt;boost/thread/thread.hpp&gt;<br />
<font color="#000080">#include</font> &lt;boost/thread/mutex.hpp&gt;<br />
<font color="#000080">#include</font> &lt;boost/bind.hpp&gt;<br />
<font color="#000080">#include</font> &lt;iostream&gt;<br />
<br />
boost::mutex io_mutex;<br />
<br />
<font color="#a52a2a">void</font> count(<font color="#a52a2a">int</font> id)<br />
{<br />
<font color="#a52a2a">for</font> (<font color="#a52a2a">int</font> i = 0; i &lt; 10; ++i)<br />
{<br />
boost::mutex::scoped_lock<br />
lock(io_mutex);<br />
std::cout &lt;&lt; id &lt;&lt; "<font color="#0000ff">: </font>" &lt;&lt;<br />
i &lt;&lt; std::endl;<br />
}<br />
}<br />
<br />
<font color="#a52a2a">int</font> main(<font color="#a52a2a">int</font> argc, <font color="#a52a2a">char</font>* argv[])<br />
{<br />
boost::thread thrd1(<br />
boost::bind(&amp;count, 1));<br />
boost::thread thrd2(<br />
boost::bind(&amp;count, 2));<br />
thrd1.join();<br />
thrd2.join();<br />
<font color="#a52a2a">return</font> 0;<br />
}</pre>
<br />
</pre>
</div>
</div>
<h3><a style="width: 20px; height: 20px; text-indent: 20px; background-repeat: no-repeat; background-image: url(/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif);" name="3 条件变量"></a>3 条件变量 </h3>
有的时候仅仅依靠锁住共享资源来使用它是不够的。有时候共享资源只有某些状态的时候才能够使用。比方说，某个线程如果要从堆栈中读取数据，那么如果栈中没
有数据就必须等待数据被压栈。这种情况下的同步使用互斥体是不够的。另一种同步的方式－－条件变量，就可以使用在这种情况下。
<p>&nbsp;</p>
<p>条件变量的使用总是和互斥体及共享资源联系在一起的。线程首先锁住互斥体，然后检验共享资源的状态是否处于可使用的状态。如果不是，那么线程就要等
待条件变量。要指向这样的操作就必须在等待的时候将互斥体解锁，以便其他线程可以访问共享资源并改变其状态。它还得保证从等到得线程返回时互斥体是被上锁
得。当另一个线程改变了共享资源的状态时，它就要通知正在等待条件变量得线程，并将之返回等待的线程。 </p>
<p>&nbsp;</p>
<p>List4是一个使用了boost::condition的简单例子。有一个实现了有界缓存区的类和一个固定大小的先进先出的容器。由于使用了互斥
体boost::mutex，这个缓存区是线程安全的。put和get使用条件变量来保证线程等待完成操作所必须的状态。有两个线程被创建，一个在
buffer中放入100个整数，另一个将它们从buffer中取出。这个有界的缓存一次只能存放10个整数，所以这两个线程必须周期性的等待另一个线
程。为了验证这一点，put和get在std::cout中输出诊断语句。最后，当两个线程结束后，main函数也就执行完毕了。 </p>
<p>&nbsp;</p>
<div class="BeautifierPlugin">
<div class="fragment">
<pre style="padding-bottom: 0px;">
<pre style="padding-bottom: 0px;"><font color="#000080">#include</font> &lt;boost/thread/thread.hpp&gt;<br />
<font color="#000080">#include</font> &lt;boost/thread/mutex.hpp&gt;<br />
<font color="#000080">#include</font> &lt;boost/thread/condition.hpp&gt;<br />
<font color="#000080">#include</font> &lt;iostream&gt;<br />
<br />
<font color="#a52a2a">const</font> <font color="#a52a2a">int</font> BUF_SIZE = 10;<br />
<font color="#a52a2a">const</font> <font color="#a52a2a">int</font> ITERS = 100;<br />
<br />
boost::mutex io_mutex;<br />
<br />
<font color="#a52a2a">class</font> buffer<br />
{<br />
<font color="#a52a2a">public</font>:<br />
<font color="#a52a2a">typedef</font> boost::mutex::scoped_lock<br />
scoped_lock;<br />
<br />
buffer()<br />
: p(0), c(0), full(0)<br />
{<br />
}<br />
<br />
<font color="#a52a2a">void</font> put(<font color="#a52a2a">int</font> m)<br />
{<br />
scoped_lock lock(mutex);<br />
<font color="#a52a2a">if</font> (full == BUF_SIZE)<br />
{<br />
{<br />
boost::mutex::scoped_lock<br />
lock(io_mutex);<br />
std::cout &lt;&lt;<br />
"<font color="#0000ff">Buffer is full. Waiting...</font>"<br />
&lt;&lt; std::endl;<br />
}<br />
<font color="#a52a2a">while</font> (full == BUF_SIZE)<br />
cond.wait(lock);<br />
}<br />
buf[p] = m;<br />
p = (p+1) % BUF_SIZE;<br />
++full;<br />
cond.notify_one();<br />
}<br />
<br />
<font color="#a52a2a">int</font> get()<br />
{<br />
scoped_lock lk(mutex);<br />
<font color="#a52a2a">if</font> (full == 0)<br />
{<br />
{<br />
boost::mutex::scoped_lock<br />
lock(io_mutex);<br />
std::cout &lt;&lt;<br />
"<font color="#0000ff">Buffer is empty. Waiting...</font>"<br />
&lt;&lt; std::endl;<br />
}<br />
<font color="#a52a2a">while</font> (full == 0)<br />
cond.wait(lk);<br />
}<br />
<font color="#a52a2a">int</font> i = buf[c];<br />
c = (c+1) % BUF_SIZE;<br />
--full;<br />
cond.notify_one();<br />
<font color="#a52a2a">return</font> i;<br />
}<br />
<br />
<font color="#a52a2a">private</font>:<br />
boost::mutex mutex;<br />
boost::condition cond;<br />
<font color="#a52a2a">unsigned</font> <font color="#a52a2a">int</font> p, c, full;<br />
<font color="#a52a2a">int</font> buf[BUF_SIZE];<br />
};<br />
<br />
buffer buf;<br />
<br />
<font color="#a52a2a">void</font> writer()<br />
{<br />
<font color="#a52a2a">for</font> (<font color="#a52a2a">int</font> n = 0; n &lt; ITERS; ++n)<br />
{<br />
{<br />
boost::mutex::scoped_lock<br />
lock(io_mutex);<br />
std::cout &lt;&lt; "<font color="#0000ff">sending: </font>"<br />
&lt;&lt; n &lt;&lt; std::endl;<br />
}<br />
buf.put(n);<br />
}<br />
}<br />
<br />
<font color="#a52a2a">void</font> reader()<br />
{<br />
<font color="#a52a2a">for</font> (<font color="#a52a2a">int</font> x = 0; x &lt; ITERS; ++x)<br />
{<br />
<font color="#a52a2a">int</font> n = buf.get();<br />
{<br />
boost::mutex::scoped_lock<br />
lock(io_mutex);<br />
std::cout &lt;&lt; "<font color="#0000ff">received: </font>"<br />
&lt;&lt; n &lt;&lt; std::endl;<br />
}<br />
}<br />
}<br />
<br />
<font color="#a52a2a">int</font> main(<font color="#a52a2a">int</font> argc, <font color="#a52a2a">char</font>* argv[])<br />
{<br />
boost::thread thrd1(&amp;reader);<br />
boost::thread thrd2(&amp;writer);<br />
thrd1.join();<br />
thrd2.join();<br />
<font color="#a52a2a">return</font> 0;<br />
}</pre>
<br />
</pre>
</div>
</div>
<p>&nbsp;</p>
<h3><a style="width: 20px; height: 20px; text-indent: 20px; background-repeat: no-repeat; background-image: url(/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif);" name="4 线程局部存储"></a>4 线程局部存储 </h3>
大多数函数都不是可重入的。这也就是说在某一个线程已经调用了一个函数时，如果你再调用同一个函数，那么这样是不安全的。一个不可重入的函数通过连续的调
用来保存静态变量或者是返回一个指向静态数据的指针。
举例来说，std::strtok就是不可重入的，因为它使用静态变量来保存要被分割成符号的字符串。
<p>&nbsp;</p>
<p>有两种方法可以让不可重用的函数变成可重用的函数。第一种方法就是改变接口，用指针或引用代替原先使用静态数据的地方。比方说，POSIX定义了
strok_r，std::strtok中的一个可重入的变量，它用一个额外的char**参数来代替静态数据。这种方法很简单，而且提供了可能的最佳效
果。但是这样必须改变公共接口，也就意味着必须改代码。另一种方法不用改变公有接口，而是用本地存储线程（thread local
storage）来代替静态数据（有时也被成为特殊线程存储，thread-specific storage）。 </p>
<p>&nbsp;</p>
<p>Boost线程库提供了智能指针boost::thread_specific_ptr来访问本地存储线程。每一个线程第一次使用这个智能指针的实
例时，它的初值是NULL，所以必须要先检查这个它的只是否为空，并且为它赋值。Boost线程库保证本地存储线程中保存的数据会在线程结束后被清除。
</p>
<p>&nbsp;</p>
<p>List5是一个使用boost::thread_specific_ptr的简单例子。其中创建了两个线程来初始化本地存储线程，并有10次循
环，每一次都会增加智能指针指向的值，并将其输出到std::cout上（由于std::cout是一个共享资源，所以通过互斥体进行同步）。main线
程等待这两个线程结束后就退出。从这个例子输出可以明白的看出每个线程都处理属于自己的数据实例，尽管它们都是使用同一个
boost::thread_specific_ptr。 </p>
<p>&nbsp;</p>
<p>例5： </p>
<div class="BeautifierPlugin">
<div class="fragment">
<pre style="padding-bottom: 0px;">
<pre style="padding-bottom: 0px;"><font color="#000080">#include</font> &lt;boost/thread/thread.hpp&gt;<br />
<font color="#000080">#include</font> &lt;boost/thread/mutex.hpp&gt;<br />
<font color="#000080">#include</font> &lt;boost/thread/tss.hpp&gt;<br />
<font color="#000080">#include</font> &lt;iostream&gt;<br />
<br />
boost::mutex io_mutex;<br />
boost::thread_specific_ptr&lt;<font color="#a52a2a">int</font>&gt; ptr;<br />
<br />
<font color="#a52a2a">struct</font> count<br />
{<br />
count(<font color="#a52a2a">int</font> id) : id(id) { }<br />
<br />
<font color="#a52a2a">void</font> <font color="#a52a2a">operator</font>()()<br />
{<br />
<font color="#a52a2a">if</font> (ptr.get() == 0)<br />
ptr.reset(<font color="#a52a2a">new</font> <font color="#a52a2a">int</font>(0));<br />
<br />
<font color="#a52a2a">for</font> (<font color="#a52a2a">int</font> i = 0; i &lt; 10; ++i)<br />
{<br />
(*ptr)++;<br />
boost::mutex::scoped_lock<br />
lock(io_mutex);<br />
std::cout &lt;&lt; id &lt;&lt; "<font color="#0000ff">: </font>"<br />
&lt;&lt; *ptr &lt;&lt; std::endl;<br />
}<br />
}<br />
<br />
<font color="#a52a2a">int</font> id;<br />
};<br />
<br />
<font color="#a52a2a">int</font> main(<font color="#a52a2a">int</font> argc, <font color="#a52a2a">char</font>* argv[])<br />
{<br />
boost::thread thrd1(count(1));<br />
boost::thread thrd2(count(2));<br />
thrd1.join();<br />
thrd2.join();<br />
<font color="#a52a2a">return</font> 0;<br />
}</pre>
<br />
</pre>
</div>
</div>
<h3><a style="width: 20px; height: 20px; text-indent: 20px; background-repeat: no-repeat; background-image: url(/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif);" name="5 仅运行一次的例程"></a>5 仅运行一次的例程 </h3>
还有一个问题没有解决：如何使得初始化工作（比如说构造函数）也是线程安全的。比方说，如果一个引用程序要产生唯一的全局的对象，由于实例化顺序的问题，
某个函数会被调用来返回一个静态的对象，它必须保证第一次被调用时就产生这个静态的对象。这里的问题就是如果多个线程同时调用了这个函数，那么这个静态对
象的构造函数就会被调用多次，这样错误产生了。
<p>&nbsp;</p>
<p>解决这个问题的方法就是所谓的&#8220;一次实现&#8221;（once
routine）。&#8220;一次实现&#8221;在一个应用程序只能执行一次。如果多个线程想同时执行这个操作，那么真正执行的只有一个，而其他线程必须等这个操作结束。
为了保证它只被执行一次，这个routine由另一个函数间接的调用，而这个函数传给它一个指针以及一个标志着这个routine是否已经被调用的特殊标
志。这个标志是以静态的方式初始化的，这也就保证了它在编译期间就被初始化而不是运行时。因此也就没有多个线程同时将它初始化的问题了。Boost线程库
提供了boost::call_once来支持&#8220;一次实现&#8221;，并且定义了一个标志boost::once_flag及一个初始化这个标志的宏
BOOST_ONCE_INIT。 </p>
<p>&nbsp;</p>
<p>List6是一个使用了boost::call_once的例子。其中定义了一个静态的全局整数，初始值为0；还有一个由
BOOST_ONCE_INIT初始化的静态boost::once_flag实例。main函数创建了两个线程，它们都想通过传入一个函数调用
boost::call_once来初始化这个全局的整数，这个函数是将它加1。main函数等待着两个线程结束，并将最后的结果输出的到
std::cout。由最后的结果可以看出这个操作确实只被执行了一次，因为它的值是1。 </p>
<p>&nbsp;</p>
<div class="BeautifierPlugin">
<div class="fragment">
<pre style="padding-bottom: 0px;">
<pre style="padding-bottom: 0px;"><font color="#000080">#include</font> &lt;boost/thread/thread.hpp&gt;<br />
<font color="#000080">#include</font> &lt;boost/thread/once.hpp&gt;<br />
<font color="#000080">#include</font> &lt;iostream&gt;<br />
<br />
<font color="#a52a2a">int</font> i = 0;<br />
boost::once_flag flag =<br />
BOOST_ONCE_INIT;<br />
<br />
<font color="#a52a2a">void</font> init()<br />
{<br />
++i;<br />
}<br />
<br />
<font color="#a52a2a">void</font> thread()<br />
{<br />
boost::call_once(&amp;init, flag);<br />
}<br />
<br />
<font color="#a52a2a">int</font> main(<font color="#a52a2a">int</font> argc, <font color="#a52a2a">char</font>* argv[])<br />
{<br />
boost::thread thrd1(&amp;thread);<br />
boost::thread thrd2(&amp;thread);<br />
thrd1.join();<br />
thrd2.join();<br />
std::cout &lt;&lt; i &lt;&lt; std::endl;<br />
<font color="#a52a2a">return</font> 0;<br />
}</pre>
<br />
</pre>
</div>
</div>
<h3><a style="width: 20px; height: 20px; text-indent: 20px; background-repeat: no-repeat; background-image: url(/CuteSoft_Client/CuteEditor/Load.ashx?type=image&amp;file=anchor.gif);" name="6 Boost线程库的未来"></a>6 Boost线程库的未来 </h3>
Boost线程库正在计划加入一些新特性。其中包括boost::read_write_mutex，它可以让多个线程同时从共享区中读取数据，但是一次
只可能有一个线程向共享区写入数据；boost::thread_barrier，它使得一组线程处于等待状态，知道所有得线程都都进入了屏障
区；boost::thread_pool,他允许执行一些小的routine而不必每一都要创建或是销毁一个线程。
<p>&nbsp;</p>
<p>Boost线程库已经作为标准中的类库技术报告中的附件提交给C++标准委员会，它的出现也为下一版C++标准吹响了第一声号角。委员会成员对
Boost线程库的初稿给予了很高的评价,当然他们还会考虑其他的多线程库。他们对在C++标准中加入对多线程的支持非常感兴趣。从这一点上也可以看出，
多线程在C++中的前途一片光明。 </p>
<img src ="http://www.cnblogs.com/flappy/aggbug/1237977.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41959/" target="_blank">[新闻]苹果已然取代微软地位成行业众矢之的</a>]]></description></item><item><title>BitBlt()双缓冲解决图象闪烁(转)</title><link>http://www.cnblogs.com/flappy/archive/2008/07/03/1234935.html</link><dc:creator>李现民</dc:creator><author>李现民</author><pubDate>Thu, 03 Jul 2008 09:11:00 GMT</pubDate><guid>http://www.cnblogs.com/flappy/archive/2008/07/03/1234935.html</guid><wfw:comment>http://www.cnblogs.com/flappy/comments/1234935.html</wfw:comment><comments>http://www.cnblogs.com/flappy/archive/2008/07/03/1234935.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/flappy/comments/commentRss/1234935.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/flappy/services/trackbacks/1234935.html</trackback:ping><description><![CDATA[<font face="宋体">显示图形如何避免闪烁，如何提高显示效率是问得比较多的问题。而且多数人认为MFC的绘图函数效率很低，总是想寻求其它的解决方案。<br />
MFC的绘图效率的确不高但也不差，而且它的绘图函数使用非常简单，只要使用方法得当，再加上一些技巧，用MFC可以得到效率很高的绘图程序。<br />
我想就我长期（呵呵当然也只有2年多）使用MFC绘图的经验谈谈我的一些观点。<br />
<br />
1、显示的图形为什么会闪烁？<br />
&nbsp;&nbsp;&nbsp;我
们的绘图过程大多放在OnDraw或者OnPaint函数中，OnDraw在进行屏幕显示时是由OnPaint进行调用的。当窗口由于任何原因需要重绘
时，总是先用背景色将显示区清除，然后才调用OnPaint，而背景色往往与绘图内容反差很大，这样在短时间内背景色与显示图形的交替出现，使得显示窗口
看起来在闪。如果将背景刷设置成NULL，这样无论怎样重绘图形都不会闪了。当然，这样做会使得窗口的显示乱成一团，因为重绘时没有背景色对原来绘制的图
形进行清除，而又叠加上了新的图形。有的人会说，闪烁是因为绘图的速度太慢或者显示的图形太复杂造成的，其实这样说并不对，绘图的显示速度对闪烁的影响不
是根本性的。例如在OnDraw(CDC *pDC)中这样写：<br />
pDC-&gt;MoveTo(0,0);<br />
pDC-&gt;LineTo(100,100);<br />
这
个绘图过程应该是非常简单、非常快了吧，但是拉动窗口变化时还是会看见闪烁。其实从道理上讲，画图的过程越复杂越慢闪烁应该越少，因为绘图用的时间与用背
景清除屏幕所花的时间的比例越大人对闪烁的感觉会越不明显。比如：清楚屏幕时间为1s绘图时间也是为1s，这样在10s内的连续重画中就要闪烁5次；如果
清楚屏幕时间为1s不变，而绘图时间为9s，这样10s内的连续重画只会闪烁一次。这个也可以试验，在OnDraw(CDC *pDC)中这样写：<br />
for(int i=0;i&lt;100000;i++)<br />
{<br />
pDC-&gt;MoveTo(0,i);<br />
pDC-&gt;LineTo(1000,i);<br />
}<br />
呵呵，程序有点变态，但是能说明问题。<br />
&nbsp;&nbsp;&nbsp;说
到这里可能又有人要说了，为什么一个简单图形看起来没有复杂图形那么闪呢？这是因为复杂图形占的面积大，重画时造成的反差比较大，所以感觉上要闪得厉害一
些，但是闪烁频率要低。那为什么动画的重画频率高，而看起来却不闪？这里，我就要再次强调了，闪烁是什么？闪烁就是反差，反差越大，闪烁越厉害。因为动画
的连续两个帧之间的差异很小所以看起来不闪。如果不信，可以在动画的每一帧中间加一张纯白的帧，不闪才怪呢。<br />
<br />
<br />
2、如何避免闪烁<br />
&nbsp;&nbsp;&nbsp;在知道图形显示闪烁的原因之后，对症下药就好办了。首先当然是去掉MFC提供的背景绘制过程了。实现的方法很多，<br />
* 可以在窗口形成时给窗口的注册类的背景刷付NULL<br />
* 也可以在形成以后修改背景<br />
&nbsp;&nbsp;&nbsp;static CBrush brush(#ff0000);<br />
&nbsp;&nbsp;&nbsp;SetClassLong(this-&gt;m_hWnd,GCL_HBRBACKGROUND,(LONG)(HBRUSH)brush);<br />
* 要简单也可以重载OnEraseBkgnd(CDC* pDC)直接返回TRUE<br />
&nbsp;&nbsp;&nbsp;这
样背景没有了，结果图形显示的确不闪了，但是显示也象前面所说的一样，变得一团乱。怎么办？这就要用到双缓存的方法了。双缓冲就是除了在屏幕上有图形进行
显示以外，在内存中也有图形在绘制。我们可以把要显示的图形先在内存中绘制好，然后再一次性的将内存中的图形按照一个点一个点地覆盖到屏幕上去（这个过程
非常快，因为是非常规整的内存拷贝）。这样在内存中绘图时，随便用什么反差大的背景色进行清除都不会闪，因为看不见。当贴到屏幕上时，因为内存中最终的图
形与屏幕显示图形差别很小（如果没有运动，当然就没有差别），这样看起来就不会闪。<br />
<br />
<br />
3、如何实现双缓冲<br />
&nbsp;&nbsp;&nbsp;首先给出实现的程序，然后再解释，同样是在OnDraw(CDC *pDC)中：<br />
<br />
CDC MemDC; //首先定义一个显示设备对象<br />
CBitmap MemBitmap;//定义一个位图对象<br />
<br />
//随后建立与屏幕显示兼容的内存显示设备<br />
MemDC.CreateCompatibleDC(NULL);<br />
//这时还不能绘图，因为没有地方画 ^_^<br />
//下面建立一个与屏幕显示兼容的位图，至于位图的大小嘛，可以用窗口的大小<br />
MemBitmap.CreateCompatibleBitmap(pDC,nWidth,nHeight);<br />
<br />
//将位图选入到内存显示设备中<br />
//只有选入了位图的内存显示设备才有地方绘图，画到指定的位图上<br />
CBitmap *pOldBit=MemDC.SelectObject(&amp;MemBitmap);<br />
<br />
//先用背景色将位图清除干净，这里我用的是白色作为背景<br />
//你也可以用自己应该用的颜色<br />
MemDC.FillSolidRect(0,0,nWidth,nHeight,#ffffff);<br />
<br />
//绘图<br />
MemDC.MoveTo(&#8230;&#8230;);<br />
MemDC.LineTo(&#8230;&#8230;);<br />
<br />
//将内存中的图拷贝到屏幕上进行显示<br />
pDC-&gt;BitBlt(0,0,nWidth,nHeight,&amp;MemDC,0,0,SRCCOPY);<br />
<br />
//绘图完成后的清理<br />
MemBitmap.DeleteObject();<br />
MemDC.DeleteDC();<br />
<br />
上面的注释应该很详尽了，废话就不多说了。<br />
<br />
<br />
4、如何提高绘图的效率<br />
&nbsp;&nbsp;&nbsp;我
主要做的是电力系统的网络图形的CAD软件，在一个窗口中往往要显示成千上万个电力元件，而每个元件又是由点、线、圆等基本图形构成。如果真要在一次重绘
过程重画这么多元件，可想而知这个过程是非常漫长的。如果加上了图形的浏览功能，鼠标拖动图形滚动时需要进行大量的重绘，速度会慢得让用户将无法忍受。怎
么办？只有再研究研究MFC的绘图过程了。<br />
&nbsp;&nbsp;&nbsp;实际上，在OnDraw(CDC
*pDC)中绘制的图并不是所有都显示了的，例如：你在OnDraw中画了两个矩形，在一次重绘中虽然两个矩形的绘制函数都有执行，但是很有可能只有一个
显示了，这是因为MFC本身为了提高重绘的效率设置了裁剪区。裁剪区的作用就是：只有在这个区内的绘图过程才会真正有效，在区外的是无效的，即使在区外执
行了绘图函数也是不会显示的。因为多数情况下窗口重绘的产生大多是因为窗口部分被遮挡或者窗口有滚动发生，改变的区域并不是整个图形而只有一小部分，这一
部分需要改变的就是pDC中的裁剪区了。因为显示（往内存或者显存都叫显示）比绘图过程的计算要费时得多，有了裁剪区后显示的就只是应该显示的部分，大大
提高了显示效率。但是这个裁剪区是MFC设置的，它已经为我们提高了显示效率，在进行复杂图形的绘制时如何进一步提高效率呢？那就只有去掉在裁剪区外的绘
图过程了。可以先用pDC-&gt;GetClipBox()得到裁剪区，然后在绘图时判断你的图形是否在这个区内，如果在就画，不在就不画。<br />
如果你的绘图过程不复杂，这样做可能对你的绘图效率不会有提高。 </font>
<img src ="http://www.cnblogs.com/flappy/aggbug/1234935.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41958/" target="_blank">[新闻]Intel 收购 Poky Linux ,为 MID 注入新的动力</a>]]></description></item><item><title>后缀数组(转)</title><link>http://www.cnblogs.com/flappy/archive/2007/10/14/924030.html</link><dc:creator>李现民</dc:creator><author>李现民</author><pubDate>Sun, 14 Oct 2007 13:44:00 GMT</pubDate><guid>http://www.cnblogs.com/flappy/archive/2007/10/14/924030.html</guid><wfw:comment>http://www.cnblogs.com/flappy/comments/924030.html</wfw:comment><comments>http://www.cnblogs.com/flappy/archive/2007/10/14/924030.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/flappy/comments/commentRss/924030.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/flappy/services/trackbacks/924030.html</trackback:ping><description><![CDATA[<span style="color: #000000; font-family: Verdana;"><span style="font-family: Lucida Sans;">在
字符串处理当中，后缀树和后缀数组都是非常有力的工具，其中后缀树大家了解得比较多，关于后缀数组则很少见于国内的资料。其实后缀数组是后缀树的一个非常
精巧的替代品，它比后缀树容易编程实现，能够实现后缀树的很多功能而时间复杂度也不太逊色，并且，它比后缀树所占用的空间小很多。可以说，在信息学竞赛中
后缀数组比后缀树要更为实用。因此在本文中笔者想介绍一下后缀数组的基本概念、构造方法，以及配合后缀数组的最长公共前缀数组的构造方法，最后结合一些例
子谈谈后缀数组的应用。 <br />
<br />
<br />
基本概念 <br />
<br />
首先明确一些必要的定义： <br />
<br />
字符集 一个字符集∑是一个建立了全序关系的集合，也就是说，∑中的任意两个不同的元素&#945;和&#946;都可以比较大小，要么&#945;&lt;&#946;，要么&#946;&lt;&#945;（也就是&#945;&gt;&#946;）。字符集∑中的元素称为字符。 <br />
字符串 一个字符串S是将n个字符顺次排列形成的数组，n称为S的长度，表示为len(S)。S的第i个字符表示为S[i]。 <br />
子串 字符串S的子串S[i..j]，i&#8804;j，表示S串中从i到j这一段，也就是顺次排列S[i],S[i+1],...,S[j]形成的字符串。 <br />
后缀 后缀是指从某个位置i开始到整个串末尾结束的一个特殊子串。字符串S的从i开头的后缀表示为Suffix(S,i)，也就是Suffix(S,i)=S[i..len(S)]。 <br />
<br />
关
于字符串的大小比较，是指通常所说的&#8220;字典顺序&#8221;比较，也就是对于两个字符串u、v，令i从1开始顺次比较u[i]和v[i]，如果相等则令i加1，否则
若u[i]&lt;v[i]则认为u&lt;v，u[i]&gt;v[i]则认为u&gt;v（也就是v&lt;u），比较结束。如果i&gt;len
(u)或者i&gt;len(v)仍未比较出结果，那么若len(u)&lt;len(v)则认为u&lt;v，若len(u)=len(v)则认为u=
v，若len(u)&gt;len(v)则u&gt;v。 <br />
从字符串的大小比较的定义来看，S的两个开头位置不同的后缀u和v进行比较的结果不可能是相等，因为u=v的必要条件len(u)=len(v)在这里不可能满足。 <br />
<br />
下
面我们约定一个字符集∑和一个字符串S，设len(S)=n，且S[n]='$'，也就是说S以一个特殊字符'$'结尾，并且'$'小于∑中的任何一个字
符。除了S[n]之外，S中的其他字符都属于∑。对于约定的字符串S，从位置i开头的后缀直接写成Suffix(i)，省去参数S。 <br />
<br />
后
缀数组 后缀数组SA是一个一维数组，它保存1..n的某个排列SA[1],SA[2],...SA[n]，并且保证
Suffix(SA[i])&lt;Suffix(SA[i+1]),1&#8804;i&lt;n。也就是将S的n个后缀从小到大进行排序之后把排好序的后缀的开头
位置顺次放入SA中。 <br />
名次数组 名次数组Rank=SA-1，也就是说若SA[i]=j，则Rank[j]=i，不难看出Rank[i]保存的是Suffix(i)在所有后缀中从小到大排列的&#8220;名次&#8221;。 <br />
<br />
<br />
构造方法 <br />
如何构造后缀数组呢？最直接最简单的方法当然是把S的后缀都看作一些普通的字符串，按照一般字符串排序的方法对它们从小到大进行排序。 <br />
不难看出，这种做法是很笨拙的，因为它没有利用到各个后缀之间的有机联系，所以它的效率不可能很高。即使采用字符串排序中比较高效的Multi-key Quick Sort，最坏情况的时间复杂度仍然是O(n2)的，不能满足我们的需要。 <br />
下面介绍倍增算法(Doubling Algorithm)，它正是充分利用了各个后缀之间的联系，将构造后缀数组的最坏时间复杂度成功降至O(nlogn)。 <br />
<br />
对一个字符串u，我们定义u的k-前缀 <br />
<br />
定义k-前缀比较关系&lt;k、=k和&#8804;k： <br />
设两个字符串u和v， <br />
u&lt;kv 当且仅当 uk&lt;vk <br />
u=kv 当且仅当 uk=vk <br />
u&#8804;kv 当且仅当 uk&#8804;vk <br />
<br />
直观地看这些加了一个下标k的比较符号的意义就是对两个字符串的前k个字符进行字典序比较，特别的一点就是在作大于和小于的比较时如果某个字符串的长度不到k也没有关系，只要能够在k个字符比较结束之前得到第一个字符串大于或者小于第二个字符串就可以了。 <br />
根据前缀比较符的性质我们可以得到以下的非常重要的性质： <br />
性质1.1 对k&#8805;n，Suffix(i)&lt;kSuffix(j) 等价于 Suffix(i)&lt;Suffix(j)。 <br />
性质1.2 Suffix(i)=2kSuffix(j)等价于 <br />
Suffix(i)=kSuffix(j) 且 Suffix(i+k)=kSuffix(j+k)。 <br />
性质1.3 Suffix(i)&lt;2kSuffix(j) 等价于 <br />
Suffix(i)&lt;kS(j) 或 (Suffix(i)=kSuffix(j) 且 Suffix(i+k)&lt;kSuffix(j+k))。 <br />
这
里有一个问题，当i+k&gt;n或者j+k&gt;n的时候Suffix(i+k)或Suffix(j+k)是无明确定义的表达式，但实际上不需要考虑
这个问题，因为此时Suffix(i)或者Suffix(j)的长度不超过k，也就是说它们的k-前缀以'$'结尾，于是k-前缀比较的结果不可能相等，
也就是说前k个字符已经能够比出大小，后面的表达式自然可以忽略，这也就看出我们规定S以'$'结尾的特殊用处了。 <br />
<br />
定义k-后缀数组
SAk保存1..n的某个排列SAk[1],SAk[2],&#8230;SAk[n]使得Suffix(SAk[i])
&#8804;kSuffix(SAk[i+1]),1&#8804;i&lt;n。也就是说对所有的后缀在k-前缀比较关系下从小到大排序，并且把排序后的后缀的开头位置顺次放
入数组SAk中。 <br />
定义k-名次数组Rankk，Rankk[i]代表Suffix(i)在k-前缀关系下从小到大的&#8220;名次&#8221;，也就是1加上满足Suffix(j)&lt;kSuffix(i)的j的个数。通过SAk很容易在O(n)的时间内求出Rankk。 <br />
假
设我们已经求出了SAk和Rankk，那么我们可以很方便地求出SA2k和Rank2k，因为根据性质1.2和1.3，2k-前缀比较关系可以由常数个k
-前缀比较关系组合起来等价地表达，而Rankk数组实际上给出了在常数时间内进行&lt;k和=k比较的方法，即： <br />
Suffix(i)&lt;kSuffix(j) 当且仅当 Rankk[i]&lt;Rankk[j] <br />
Suffix(i)=kSuffix(j) 当且仅当 Rankk[i]=Rankk[j] <br />
因
此，比较Suffix(i)和Suffix(j)在k-前缀比较关系下的大小可以在常数时间内完成，于是对所有的后缀在&#8804;k关系下进行排序也就和一般的排
序没有什么区别了，它实际上就相当于每个Suffix(i)有一个主关键字Rankk[i]和一个次关键字Rankk[i+k]。如果采用快速排序之类O
(nlogn)的排序，那么从SAk和Rankk构造出SA2k的复杂度就是O(nlogn)。更聪明的方法是采用基数排序，复杂度为O(n)。 <br />
求出SA2k之后就可以在O(n)的时间内根据SA2k构造出Rank2k。因此，从SAk和Rankk推出SA2k和Rank2k可以在O(n)时间内完成。 <br />
下
面只有一个问题需要解决：如何构造出SA1和Rank1。这个问题非常简单：因为&lt;1，=1和&#8804;1这些运算符实际上就是对字符串的第一个字符进行比
较，所以只要把每个后缀按照它的第一个字符进行排序就可以求出SA1，不妨就采用快速排序，复杂度为O(nlogn)。 <br />
于是，可以在O(nlogn)的时间内求出SA1和Rank1。 <br />
求出了SA1和Rank1，我们可以在O(n)的时间内求出SA2和Rank2，同样，我们可以再用O(n)的时间求出SA4和Rank4，这样，我们依次求出： <br />
SA2和Rank2，SA4和Rank4，SA8和Rank8，&#8230;&#8230;直到SAm和Rankm，其中m=2k且m&#8805;n。而根据性质1.1，SAm和SA是等价的。这样一共需要进行logn次O(n)的过程，因此 <br />
可以在O(nlogn)的时间内计算出后缀数组SA和名次数组Rank。 <br />
<br />
最长公共前缀 <br />
现
在一个字符串S的后缀数组SA可以在O(nlogn)的时间内计算出来。利用SA我们已经可以做很多事情，比如在O(mlogn)的时间内进行模式匹配，
其中m,n分别为模式串和待匹配串的长度。但是要想更充分地发挥后缀数组的威力，我们还需要计算一个辅助的工具——最长公共前缀（Longest
Common Prefix）。 <br />
对两个字符串u,v定义函数lcp(u,v)=max{i|u=iv}，也就是从头开始顺次比较u和v的对应字符，对应字符持续相等的最大位置，称为这两个字符串的最长公共前缀。 <br />
对正整数i,j定义LCP(i,j)=lcp(Suffix(SA[i]),Suffix(SA[j])，其中i,j均为1至n的整数。LCP(i,j)也就是后缀数组中第i个和第j个后缀的最长公共前缀的长度。 <br />
关于LCP有两个显而易见的性质： <br />
性质2.1 LCP(i,j)=LCP(j,i) <br />
性质2.2 LCP(i,i)=len(Suffix(SA[i]))=n-SA[i]+1 <br />
这两个性质的用处在于，我们计算LCP(i,j)时只需要考虑i&lt;j的情况，因为i&gt;j时可交换i,j，i=j时可以直接输出结果n-SA[i]+1。 <br />
<br />
直接根据定义，用顺次比较对应字符的方法来计算LCP(i,j)显然是很低效的，时间复杂度为O(n)，所以我们必须进行适当的预处理以降低每次计算LCP的复杂度。 <br />
经过仔细分析，我们发现LCP函数有一个非常好的性质： <br />
设i&lt;j，则LCP(i,j)=min{LCP(k-1,k)|i+1&#8804;k&#8804;j} （LCP Theorem） <br />
<br />
要证明LCP Theorem，首先证明LCP Lemma: <br />
对任意1&#8804;i&lt;j&lt;k&#8804;n，LCP(i,k)=min{LCP(i,j),LCP(j,k)} <br />
证明：设p=min{LCP(i,j),LCP(j,k)}，则有LCP(i,j)&#8805;p,LCP(j,k)&#8805;p。 <br />
设Suffix(SA[i])=u,Suffix(SA[j])=v,Suffix(SA[k])=w。 <br />
由u=LCP(i,j)v得u=pv；同理v=pw。 <br />
于是Suffix(SA[i])=pSuffix(SA[k])，即LCP(i,k)&#8805;p。 (1) <br />
<br />
又设LCP(i,k)=q&gt;p，则 <br />
u[1]=w[1],u[2]=w[2],...u[q]=w[q]。 <br />
而min{LCP(i,j),LCP(j,k)}=p说明u[p+1]&#8800;v[p+1]或v[p+1]&#8800;w[q+1]， <br />
设u[p+1]=x,v[p+1]=y,w[p+1]=z，显然有x&#8804;y&#8804;z，又由p&lt;q得p+1&#8804;q，应该有x=z，也就是x=y=z，这与u[p+1]&#8800;v[p+1]或v[p+1]&#8800;w[q+1]矛盾。 <br />
于是，q&gt;p不成立，即LCP(i,k)&#8804;p。 (2) <br />
综合(1),(2)知 LCP(i,k)=p=min{LCP(i,j),LCP(j,k)}，LCP Lemma得证。 <br />
<br />
于是LCP Theorem可以证明如下： <br />
当j-i=1和j-i=2时，显然成立。 <br />
设j-i=m时LCP Theorem成立，当j-i=m+1时， <br />
由LCP Lemma知LCP(i,j)=min{LCP(i,i+1),LCP(i+1,j)}， <br />
因j-(i+1)&#8804;m，LCP(i+1,j)=min{LCP(k-1,k)|i+2&#8804;k&#8804;j}，故当j-i=m+1时，仍有 <br />
LCP(i,j)=min{LCP(i,i+1),min{LCP(k-1,k)|i+2&#8804;k&#8804;j}}=min{LCP(k-1,k}|i+1&#8804;k&#8804;j) <br />
根据数学归纳法，LCP Theorem成立。 <br />
<br />
根据LCP Theorem得出必然的一个推论： <br />
LCP Corollary 对i&#8804;j&lt;k，LCP(j,k)&#8805;LCP(i,k)。 <br />
<br />
定义一维数组height，令height[i]=LCP(i-1,i)，1&lt;i&#8804;n，并设height[1]=0。 <br />
由LCP
Theorem，LCP(i,j)=min{height[k]|i+1&#8804;k&#8804;j}，也就是说，计算LCP(i,j)等同于询问一维数组height中下
标在i+1到j范围内的所有元素的最小值。如果height数组是固定的，这就是非常经典的RMQ（Range Minimum Query）问题。 <br />
RMQ问题可以用线段树或静态排序树在O(nlogn)时间内进行预处理，之后每次询问花费时间O(logn)，更好的方法是RMQ标准算法，可以在O(n)时间内进行预处理，每次询问可以在常数时间内完成。 <br />
对于一个固定的字符串S，其height数组显然是固定的，只要我们能高效地求出height数组，那么运用RMQ方法进行预处理之后，每次计算LCP(i,j)的时间复杂度就是常数级了。于是只有一个问题——如何尽量高效地算出height数组。 <br />
根据计算后缀数组的经验，我们不应该把n个后缀看作互不相关的普通字符串，而应该尽量利用它们之间的联系，下面证明一个非常有用的性质： <br />
为了描述方便，设h[i]=height[Rank[i]]，即height[i]=h[SA[i]]。h数组满足一个性质： <br />
性质3 对于i&gt;1且Rank[i]&gt;1，一定有h[i]&#8805;h[i-1]-1。 <br />
为了证明性质3，我们有必要明确两个事实： <br />
<br />
设i&lt;n,j&lt;n，Suffix(i)和Suffix(j)满足lcp(Suffix(i),Suffix(j)&gt;1，则成立以下两点： <br />
Fact 1 Suffix(i)&lt;Suffix(j) 等价于 Suffix(i+1)&lt;Suffix(j+1)。 <br />
Fact 2 一定有lcp(Suffix(i+1),Suffix(j+1))=lcp(Suffix(i),Suffix(j))-1。 <br />
看
起来很神奇，但其实很自然：lcp(Suffix(i),Suffix(j))&gt;1说明Suffix(i)和Suffix(j)的第一个字符是相同
的，设它为&#945;，则Suffix(i)相当于&#945;后连接Suffix(i+1)，Suffix(j)相当于&#945;后连接Suffix(j+1)。比较Suffix
(i)和Suffix(j)时，第一个字符&#945;是一定相等的，于是后面就等价于比较Suffix(i)和Suffix(j)，因此Fact
1成立。Fact 2可类似证明。 <br />
<br />
于是可以证明性质3： <br />
当h[i-1]&#8804;1时，结论显然成立，因h[i]&#8805;0&#8805;h[i-1]-1。 <br />
当h[i-1]&gt;1时，也即height[Rank[i-1]]&gt;1，可见Rank[i-1]&gt;1，因height[1]=0。 <br />
令j=i-1,k=SA[Rank[j]-1]。显然有Suffix(k)&lt;Suffix(j)。 <br />
根据h[i-1]=lcp(Suffix(k),Suffix(j))&gt;1和Suffix(k)&lt;Suffix(j)： <br />
由Fact 2知lcp(Suffix(k+1),Suffix(i))=h[i-1]-1。 <br />
由Fact 1知Rank[k+1]&lt;Rank[i]，也就是Rank[k+1]&#8804;Rank[i]-1。 <br />
于是根据LCP Corollary，有 <br />
LCP(Rank[i]-1,Rank[i])&#8805;LCP(Rank[k+1],Rank[i]) <br />
=lcp(Suffix(k+1),Suffix(i)) <br />
=h[i-1]-1 <br />
由于h[i]=height[Rank[i]]=LCP(Rank[i]-1,Rank[i])，最终得到 h[i]&#8805;h[i-1]-1。 <br />
<br />
根据性质3，可以令i从1循环到n按照如下方法依次算出h[i]： <br />
若Rank[i]=1，则h[i]=0。字符比较次数为0。 <br />
若i=1或者h[i-1]&#8804;1，则直接将Suffix(i)和Suffix(Rank[i]-1)从第一个字符开始依次比较直到有字符不相同，由此计算出h[i]。字符比较次数为h[i]+1，不超过h[i]-h[i-1]+2。 <br />
否
则，说明i&gt;1，Rank[i]&gt;1，h[i-1]&gt;1，根据性质3，Suffix(i)和Suffix(Rank[i]-1)至少有
前h[i-1]-1个字符是相同的，于是字符比较可以从h[i-1]开始，直到某个字符不相同，由此计算出h[i]。字符比较次数为h[i]-h[i-
1]+2。 <br />
<br />
设SA[1]=p，那么不难看出总的字符比较次数不超过 <br />
<br />
也就是说，整个算法的复杂度为O(n)。 <br />
求出了h数组，根据关系式height[i]=h[SA[i]]可以在O(n)时间内求出height数组，于是 <br />
可以在O(n)时间内求出height数组。 <br />
<br />
结合RMQ方法，在O(n)时间和空间进行预处理之后就能做到在常数时间内计算出对任意(i,j)计算出LCP(i,j)。 <br />
因为lcp(Suffix(i),Suffix(j))=LCP(Rank[i],Rank[j])，所以我们也就可以在常数时间内求出S的任何两个后缀之间的最长公共前缀。这正是后缀数组能强有力地处理很多字符串问题的重要原因之一。<br />
后缀数组的应用<br />
下面结合两个例子谈谈如何运用后缀数组.<br />
<br />
</span></span>例一 多模式串的模式匹配问题<br />
给定一个固定待匹配串S,长度为n,然后每次输入一个模式串P,长度为m,要求返回P在S中的一个匹配或者返回匹配失败.所谓匹配指某个位置i满足1&#8804;i&#8804;n-m+1使得S[i..(i+m-1)]=P,也即Suffix(i)=mP.<br />
我们知道,如果只有一个模式串,最好的算法就是KMP算法,时间复杂度为O(n+m),但是如果有多个模式串,我们就要考虑做适当的预处理使得对每个模式串进行匹配所花的时间小一些.最简单的预处理莫过于建立S的后缀数组(先在S的后面添加'$'),然后每次寻找匹配转化为用二分查找法在SA中找到和P的公共前缀最长的一个后缀,判断这个最长的公共前缀是否等于m.这样,每次比较P和一个后缀的复杂度为O(m),因为最坏情况下可能比较了m个字符.二分查找需要调用比较的次数为O(logn),因此总复杂度为O(mlogn),于是每次匹配的复杂度从O(n+m)变为O(mlogn),可以说改进了不少.可是这样仍然不能令我们满足.前面提到LCP可以增加后缀数组的威力,<br />
<br />
我们来试试用在这个问题上.<br />
我们分析原始的二分查找算法,大体有以下几步:<br />
Step 1 令left=1,right=n,max_match=0.<br />
Step 2 令mid=(left+right)/2(这里"/"表示取整除法).<br />
Step 3 顺次比较Suffix(SA[mid])和P的对应字符,找到两者的最长公共<br />
前缀r,并判断出它们的大小关系.若r&gt;max_match则令max_match=r,ans=mid.<br />
Step 4 若Suffix(SA[mid])P则令<br />
right=mid-1,若Suffix(SA[mid])=P则转至Step 6.<br />
Step 5 若left<br />
Step 6 若max_match=m则输出ans,否则输出"无匹配".<br />
注意力很快集中在Step 3,如果能够避免每次都从头开始比较Suffix(SA[mid])和P的对应字符,也许复杂度就可以进一步降低.类似于前面求height数组,我们考虑利用以前求得的最长公共前缀作为比较的"基础",避免冗余的字符比较.<br />
<br />
在比较Suffix(SA[mid])和P之前,我们先用常数时间计算LCP(mid,ans),然后比较LCP(mid,ans)和max_match:情况一:LCP(mid,ans)k+1,T[i-r'..i-1]和T[i+1..i+r']也不可能关于T[i]对称了,所以r最大只能到k.我们把r递增的过程称为向两边扩展,扩展一次就可以把以T[i]为中心的奇回文子串的长度加2.最后r扩展到的最大值决定了以T[i]为中心的奇回文子串中的最长者的长度(为2r+1).设len(T)=m,如果用依次比较对应字符的方法来求向两边扩展的最大值,则最多可能比较m-1个字符.由于要枚举每个位置作为中心向两边扩展,所以最坏情况下总的复杂度可以达到O(m2),不很理想.<br />
下面优化算法的核心部分<br />
——以一个位置为中心求向两边扩展的最大值.<br />
在T串的末尾添加一个特殊字符'#',规定它不等于T的任何一个字符,然后把T串颠倒,接在'#'后,在T'串后再添加特殊字符'$',规定它小于前面的任何一个字符,拼接后形成的串称为S串.不难看出T串中任何一个字符都可在T'中对称地找到一个相同的字符.如果都用S里的字符来表示,S[1..m]是T串,S[m+2..2m+1]是T'串,则每个S[i](1&#8804;i&#8804;m)关于'#'对称的字符是S[2m-i+2].这样原先T串里面的一个子串S[i..j](1&#8804;i&#8804;j&#8804;m)关于'#'也可以对称地找到一个反射相等的子串S[2m-j+2..2m-i+2].<br />
现在我们定下T串的某个位置S[i]为中心,假设向两边扩展到了i-r和i+r,那么S[i-r..i-1]和S[i+1..i+r]是反射相等的,S[i]可以在T'中找到对称的字符S[2m-i+2],设i'=2m-i+2,则S[i-r..i-1]也可以在T'中找到对称的子串S[i'+1..i'+r],<br />
banana#ananab$<br />
TT'<br />
ii'=2m-i+2<br />
那么S[i+1..i+r]和S[i'+1..i'+r]同时与S[i-r..i-1]反射相等,也就是说,S[i+1..i+r]=S[i'+1..i'+r].又因为S[i]=S[i'],故S[i..i+r]=S[i'..i'+r].也就是说,Suffix(i)=r+1Suffix(i').现在要求r尽量大,也就是求max{r|Suffix(i)=r+1Suffix(i')},不难看出,这里r=LCP(i,i')-1.上面的推理还存在一个问题,即求出的LCP(i,i')-1还只能看作r的一个上界,还不能当成r的最大值,因为还需要证明给出Suffix(i)和Suffix(i')的最长公共前缀,一定可以反过来在T串中找到相应的以i为中心的回文串,这个证明与前面的推理类似,只是需要注意一点:这里利用到了'#'这个特殊字符避免了潜在的LCP(i,i')超过实际的r最大值的危险.这个证明留给读者自行完成.总之,我们已经确定求以T[i]为中心向两边扩展的最大值等价于求LCP(i,i'),根据前面后缀数组和LCP的相关内容这一步操作可以在常数时间内完成,只要我们预先花费O(nlogn)的复杂度计算后缀数组,height数组和进行预处理.其中n=len(S)=2m+2.<br />
现在每次求以一个位置T[i]为中心的回文子串中的最长者的长度可以在常数时间内完成,我们枚举i从1到m,依次求出所有的这些最长者,记录其中最大的一个的长度,就是所要求的最长奇回文子串的长度.由于对每个中心花费时间为常数,所以总的复杂度为O(m).因此整个算法的复杂度是O(nlogn+m)=O(2mlog(2m)+m)=O(mlogm),是非常优秀的算法,比之前的平方级算法大为改进.<br />
<br />
后缀数组与后缀树的比较<br />
通过上面的两个例子相信读者已经对后缀数组的强大功能有所了解,另一种数据结构——后缀树,也可以用在这些问题中,那么后缀数组和后缀树有什么区别和联系呢 我们来比较一下:<br />
首先,后缀数组比较容易理解,也易于编程实现,而且不像后缀树那样需要涉及到指针操作,所以调试起来比较方便.第二,后缀数组占用的空间比后缀树要小,刚才分析中我们并没有提到空间复杂度的问题,这里简单说一下:后缀数组SA和名词数组Rank都只需要n个整数的空间,而在由Rankk计算出SA2k的过程中需要用两个一维数组来辅助完成,各占n个整数的空间,滚动地进行操作,整个算法只需要这四个一维数组和常数个辅助变量,因此总的空间占用为4n个整数.而后缀树通常有2n个以上节点,通常每个节点要两个整数(即使采用一些技巧,至少还是要保存一个整数),每个节点要有两个指针(假设采用儿子-兄弟表示方法),因此总共的空间占用至少是4n个指针和2n个整数(至少是n个整数).如果采用其他方法表示树状结构,需要的空间更大.可以看出后缀数组的空间需求比后缀树小.<br />
最后比较它们的复杂度:<br />
首先按照字符总数|∑|把字符集∑分为三种类型:<br />
若|∑|是一个常数,则称∑为Constant Alphabet,<br />
若|∑|的大小是关于S的长度n的多项式函数,则称∑为Integer Alphabet,<br />
若|∑|没有大小上的限制,则称∑为General Alphabet.<br />
<br />
显然Constant Alphbet属于Integer Alphabet的一种,而Integer Alphabet是General Alphabet的一种.构造后缀数组的复杂度与字符集无关,因为它是直接针对General Alphabet的算法.对于普通方法构造后缀树,如果用儿子-兄弟方式表达树状结构,时间复杂度达到O(n*|∑|),显然对于Integer Alphabet 和 General Alphabet都很低效,对|∑|较大的Constant Alphabet也不适用.解决的方法是用平衡二叉树来保存指向儿子的指针,这样复杂度变为O(n*log|∑|).可见后缀树在某些情况下相对后缀数组有速度上的优势,但是并不明显.对于|∑|很小的字符串,后缀树相比后缀数组的速度优势还是比较可观的.尤其是对于很常见的0-1串.<br />
后缀数组实际上可以看作后缀树的所有叶结点按照从左到右的次序排列放入数组中形成的,所以后缀数组的用途不可能超出后缀树的范围.甚至可以说,如果不配合LCP,后缀数组的应用范围是很狭窄的.但是LCP函数配合下的后缀数组就非常强大,可以完成大多数后缀树所能完成的任务,因为LCP函数实际上给出了任意两个叶子结点的最近公共祖先,这方面的内容大家可以自行研<br />
究.后缀树和后缀数组都是字符串处理中非常优秀的数据结构,不能说一个肯定优于另一个,对于不同场合,不同条件的问题,我们应该灵活应用,精心选择地选择其中较为适合的一个.算法和数据结构都是死的,而运用它们的人,才是真正的主角,对经典的算法和数据结构熟练掌握并适当地运用以发挥它们最大的力量,这才是信息学研究和竞赛中最大的智慧,也是信息学竞赛的魅力<br />
所在.<br />
<img src ="http://www.cnblogs.com/flappy/aggbug/924030.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41957/" target="_blank">[新闻]雅虎将关闭社交网站Mash</a>]]></description></item><item><title>2006百度笔试题</title><link>http://www.cnblogs.com/flappy/archive/2007/10/14/923850.html</link><dc:creator>李现民</dc:creator><author>李现民</author><pubDate>Sun, 14 Oct 2007 08:52:00 GMT</pubDate><guid>http://www.cnblogs.com/flappy/archive/2007/10/14/923850.html</guid><wfw:comment>http://www.cnblogs.com/flappy/comments/923850.html</wfw:comment><comments>http://www.cnblogs.com/flappy/archive/2007/10/14/923850.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/flappy/comments/commentRss/923850.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/flappy/services/trackbacks/923850.html</trackback:ping><description><![CDATA[一、选择题：15分 共10题<br />
1.一个含有n个顶点和e条边的简单无向图，在其邻接矩阵存储结构中共有____个零元素。<br />
A．e　　　 B．2e　　　 C．n2-e　　 D．n2-2e<br />
2.____是面向对象程序设计语言中的一种机制。这种机制实现了方法的定义与具体的对象无关，而对方法的调用则可以关联于具体的对象。<br />
A．继承（Inhertance） B．模板（Template）<br />
C．对象的自身引用（Self-Reference） D．动态绑定（Dynamic Binding）<br />
3.应用层DNS协议主要用于实现 网络服务功能.<br />
A. IP地址到网络设备名字的映射 B. IP地址到网络硬件地址的映射<br />
C. 网络设备名字到IP地址的映射 D. 网络硬件地址到IP地址的映射<br />
4.linux默认情况下，一个进程最多能打开多少文件？<br />
A.64 B. 128 C. 512 D. 1024<br />
5.下面结构体<br />
struct s1 {<br />
char ch, *ptr;<br />
union {<br />
short a, b;<br />
unsigned int c:2, d:1;<br />
}<br />
struct s1 *next;<br />
};<br />
的大小是_____：<br />
A. 12字节 B.16字节 C.20字节 D. 24字节<br />
6.任何一个基于"比较"的内部排序的算法，若对6个元素进行排序，则在最坏情况下所需的比较次数至少为____。<br />
A．10 B．11 C．21 D．36<br />
7.以下不是进程间通讯的是___<br />
A 共享内存 B 信号量 C线程局部存储 D 消息队列<br />
8.下面程序，求count的值<br />
int func(x)<br />
{<br />
int count= 0;<br />
x=9999;<br />
while(x)<br />
{<br />
Count ++;<br />
x = x&amp;(x-1);<br />
}<br />
return count;<br />
}<br />
A 8； B 10； C 5； D 11<br />
9.使用malloc系统调用分配的内存是在____ 上分配的？<br />
A 栈； B bss； C 物理内存； D 堆<br />
10.最坏情况下，合并两个大小为n的已排序数组所需要的比较次数_____<br />
A.2n B.2n-1 C.2n+1 D.2n-2<br />
二、简答题：20分，共3题<br />
1.（5分）下面这段代码是把中英文混合字符串(汉字用两个字节表示，特点是第一个字节的最高位为1)中的大写字母转化为小写字母，请找出其中的bug，注意各种异常情况。<br />
for (char *piterator = szWord; *piterator != 0; piterator++)<br />
{<br />
if (*piterator &amp; 0x80 != 0)<br />
{<br />
piterator++;<br />
}<br />
else if (*piterator &gt;= 'A' &amp;&amp; *piterator &lt;= 'Z')<br />
*piterator += 32;<br />
}<br />
2.（5分）对给定的上亿条无序的url，请按照domain、site以及path分别排序，并请指出排序过程中可能会遇到的哪些问题？如何提高效率？<br />
例如：http://www.baidu.com/path/about.html，domain、site以及path的定义分别如下：<br />
Domain:baidu.com<br />
Site:www.baidu.com<br />
Path: www.baidu.com/path<br />
3.（10分）某型CPU的一级数据缓存大小为16K字节，cache块大小为64字节；二级缓存大小为256K字节，cache块大小为4K字节，采用二路组相联。经测试，下面两段代码运行时效率差别很大，请分析哪段代码更好，以及可能的原因。<br />
为了进一步提高效率，你还可以采取什么办法？<br />
A段代码<br />
int matrix[1023][15];<br />
const char *str = "this is a str";<br />
int i, j, tmp, sum = 0;<br />
tmp = strlen(str);<br />
for(i = 0; i &lt; 1023; i++) {<br />
for(j = 0; j &lt; 15; j++) {<br />
sum += matrix[i][j] + tmp;<br />
}<br />
}<br />
B段代码<br />
int matrix[1025][17];<br />
const char *str = "this is a str";<br />
int i, j, sum = 0;<br />
for(i = 0; i &lt; 17; i++) {<br />
for(j = 0; j &lt; 1025; j++) {<br />
sum += matrix[j][i] + strlen(str);<br />
}<br />
}<br />
三、编程题：30分 共1题<br />
注意：要求尽可能提供完整代码，如果可以编译运行酌情加分。<br />
1.内存中有一个长数组，条目数为10万，数组单元为结构体struct array，sizeof(struct array)为512字节。结构有一int型成员变量weight。现需要取得按weight值从大到小排序的前500个数组单元，请实现算法，要求效率尽可能高。<br />
－－－－－可以尝试两种方法：一种使用qsort变种直接找到第500大小的数，一种使用priority_queue调出前面的500个来<br />
一是可以用<br />
四、设计题：35分 共1题<br />
注意：请尽可能详细描述你的数据结构、系统架构、设计思路等，建议多写一些伪代码或者流程说明。<br />
1.请设计一个字典。以字符串为索引，存储用户定义的定长结构。要求有增、删、查、改的功能。已经给定一个函数，可以由字符串映射到一个签名，每个签名由两个unsigned int类型组成。假设每一个字符串能够对应唯一的一个签名，完全没有重复（或者重复的概率可以忽略），并且签名分布足够均匀。<br />
请描述你的数据结构？内存如何申请？增、删、查、改的功能如何实现？如果操作很频繁，该如何优化？
<img src ="http://www.cnblogs.com/flappy/aggbug/923850.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41957/" target="_blank">[新闻]雅虎将关闭社交网站Mash</a>]]></description></item><item><title>百度笔试题</title><link>http://www.cnblogs.com/flappy/archive/2007/10/14/923830.html</link><dc:creator>李现民</dc:creator><author>李现民</author><pubDate>Sun, 14 Oct 2007 08:31:00 GMT</pubDate><guid>http://www.cnblogs.com/flappy/archive/2007/10/14/923830.html</guid><wfw:comment>http://www.cnblogs.com/flappy/comments/923830.html</wfw:comment><comments>http://www.cnblogs.com/flappy/archive/2007/10/14/923830.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/flappy/comments/commentRss/923830.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/flappy/services/trackbacks/923830.html</trackback:ping><description><![CDATA[&nbsp; 1）此题10分&nbsp; <br />
&nbsp; 对任意输入的正整数N，编写C程序求N!的尾部连续0的个数，并指出计算复杂度。如：18！＝6402373705728000，尾部连续0的个数是3。&nbsp; <br />
&nbsp; （不用考虑数值超出计算机整数界限的问题）&nbsp; <br />
&nbsp;&nbsp; <br />
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; background-color: #eeeeee; font-size: 13px; width: 98%;"><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;countFactorialZero(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;n)<br />
{<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;count</span><span style="color: #000000;">=</span><span style="color: #000000;">0</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">for</span><span style="color: #000000;">(</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;i</span><span style="color: #000000;">=</span><span style="color: #000000;">5</span><span style="color: #000000;">;i</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">n;i</span><span style="color: #000000;">+=</span><span style="color: #000000;">5</span><span style="color: #000000;">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;j</span><span style="color: #000000;">=</span><span style="color: #000000;">i;</span><span style="color: #008000;">//</span><span style="color: #008000;">注意不要直接用i</span><span style="color: #008000;"><br />
</span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">while</span><span style="color: #000000;">(j</span><span style="color: #000000;">%</span><span style="color: #000000;">5</span><span style="color: #000000;">==</span><span style="color: #000000;">0</span><span style="color: #000000;">)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;j</span><span style="color: #000000;">/=</span><span style="color: #000000;">5</span><span style="color: #000000;">;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;count</span><span style="color: #000000;">++</span><span style="color: #000000;">;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;}<br />
&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;count;<br />
}</span></div>
&nbsp; 2）此题10分&nbsp; <br />
&nbsp; 编写一个C语言函数，要求输入一个url，输出该url是首页、目录页或者其他url&nbsp; <br />
&nbsp; 如下形式叫做首页：&nbsp; <br />
&nbsp; militia.info/&nbsp; <br />
&nbsp; www.apcnc.com.cn/&nbsp; <br />
&nbsp; http://www.cyjzs.comwww.greena888.com/&nbsp; <br />
&nbsp; www.800cool.net/&nbsp; <br />
&nbsp; http://hgh-products.my-age.net/&nbsp; <br />
&nbsp; 如下形式叫做目录页：&nbsp; <br />
&nbsp; thursdaythree.net/greenhouses--gas-global-green-house-warming/&nbsp; <br />
&nbsp; http://www.mw.net.tw/user/tgk5ar1r/profile/&nbsp; <br />
&nbsp; http://www.szeasy.com/food/yszt/chunjie/&nbsp; <br />
&nbsp; www.fuckingjapanese.com/Reality/&nbsp; <br />
&nbsp;&nbsp; <br />
&nbsp; 请注意：&nbsp; <br />
&nbsp; a） url有可能带http头也有可能不带&nbsp; <br />
&nbsp; b）动态url（即含有"？"的url）的一律不算目录页，如：&nbsp; <br />
&nbsp; www.buddhismcity.net/utility/mailit.php?l=/activity/details/3135/&nbsp; <br />
&nbsp; www.buddhismcity.net/utility/mailit.php?l=/activity/details/2449/&nbsp; <br />
&nbsp;&nbsp; <br />
&nbsp; 另：如果你会linux，请用linux下的grep命令实现第2题的功能（附加5分）。&nbsp; <br />
&nbsp; --------这个可以从后向前扫描<br />
&nbsp; 3）此题40分&nbsp; <br />
&nbsp; 如果必须从网页中区分出一部分"重要网页"（例如在10亿中选8亿），比其他网页更值得展现给用户，请提出一种方案。&nbsp; <br />
&nbsp;&nbsp; －－－－－－－－<br />
//这个就是排序算法.Google的专利PageRank....<br />
//PageRank,Google宣称有50万个参数....以下这些应该是比较主要的.<br />
<br />
排序算法部分参考指标：<br />
<br />
指标&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 加分&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 减分<br />
网站硬件指标&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 网站网络好，系统稳定&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 网站系统不稳定，网络不好<br />
网站包含网页数&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 总网页数目多&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 总网页数目少<br />
网页大小&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 网页大小适中&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 网页多大或过小<br />
其他网页链到本网页&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 数目多&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 数目少<br />
网页内URL数&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 数目适中&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 过多或过少<br />
网页相关性&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; URL连接网页是相关内容&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; URL连接网页不是相关内容<br />
网页更新/生成日期&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 日期近的&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 日期远的<br />
网页类型&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 静态网页&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 动态网页<br />
网页内样式&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 网页设计样式中等&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 网页设计样式过于复杂或简单<br />
网页具体内容&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 分词后，各个词权重总和高&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 分词后，各个词权重总和低<br />
用户访问行为&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 点击多的网页&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 点击少的网页<br />
&nbsp; 4）此题40分&nbsp; <br />
&nbsp; 假设有10亿网页已经被我们存下来，并提供如下信息：网页全文（即网页的源码）、全文长度、网页正文（即网页中提取的主体文字）、&nbsp; <br />
&nbsp; 正文长度，以及其他网页提取物等，现在希望去掉其中的重复网页，请提出可行的方案，计算出每个网页对应的重复度，你可以自己&nbsp; <br />
&nbsp; 对网页重复下定义，也可以提出需要哪些更多的网页提取物来实现更好的去重复方案&nbsp; <br />
--------------可以使用余弦定理来给每个网页建立一个有意义的hash，参考&#8220; <a href="http://www.googlechinablog.com/2006/07/12.html">余弦定理和新闻的分类</a>&#8221;。进一步可参考数组的唯一性问题来处理，这个复杂度大概是NlogN的，但网页重复度应该怎么定义呢？<br />
<img src ="http://www.cnblogs.com/flappy/aggbug/923830.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41957/" target="_blank">[新闻]雅虎将关闭社交网站Mash</a>]]></description></item><item><title>Exponent:开源的数学表达式库</title><link>http://www.cnblogs.com/flappy/archive/2007/06/20/790323.html</link><dc:creator>李现民</dc:creator><author>李现民</author><pubDate>Wed, 20 Jun 2007 05:45:00 GMT</pubDate><guid>http://www.cnblogs.com/flappy/archive/2007/06/20/790323.html</guid><wfw:comment>http://www.cnblogs.com/flappy/comments/790323.html</wfw:comment><comments>http://www.cnblogs.com/flappy/archive/2007/06/20/790323.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/flappy/comments/commentRss/790323.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/flappy/services/trackbacks/790323.html</trackback:ping><description><![CDATA[<p><a  href="http://yegong1985.googlepages.com/" target="_blank">夜弓</a>写了一
个C++的数学表达式库。这个库还是满有创意的，使用它构造了一个函数对象之后，你就可以随时传给它适当的参数求得函数的值。因而你的代码几乎就可以像数
学表达式那样简洁，并且具有可读性。我在Gcc3.3和Vc2005的编译器上编译通过，没有问题。如果你在更多的编译器上编译通过，请留言让大家知道
啊。</p>
<p>我偷个懒，下面的介绍摘自作者写的文档。</p>
<p>1.你不用声明并实现一个函数就可以得到和它功能相同的函数对象。例如，你需要<br>
得到一个计算平面两点&#8217;(x1,y1)&#8217; and &#8216;(x2,y2)&#8217;距离的函数。以前你需要这样做：<br>
&nbsp;&nbsp; float Euclid_Distance(float dx, float dy)<br>
&nbsp;&nbsp; {<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;return sqrt(dx*dx+dy*dy);<br>
&nbsp;&nbsp; }</p>
<p>新办法是：<br>
&nbsp;&nbsp;&nbsp;//&#8230;any where of your program<br>
&nbsp;&nbsp;&nbsp;Variable x(1),y(2);<br>
&nbsp;&nbsp;&nbsp;Function fx = sqrt(x*x+y*y); //或者 sqrt((x^2.0f)+(y^2.0f);</p>
<p>2.对于分段函数，本库提供一种一目了然的表达：<br>
&nbsp;&nbsp;&nbsp; fx += WHEN(x&gt;99.0f) | lg(x),<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WHEN(x&gt;9.99f) | 10.0f-x,<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; WHEN(x&gt;0.0f)&nbsp; | sin(x),<br>
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; sin(cos(x));<br>
如你所见，这种办法要比使用&#8221;switch&#8221;或者&#8221;if-else&#8221;语句清晰多了。</p>
<p>3.几乎所有函数，都可以求得它的偏导数。<br>
&nbsp;&nbsp; fx = -cos(x);<br>
&nbsp;&nbsp; gx = fx.difference();<br>
假如你修过微积分的课程，那么你现在已经知道&#8221;gx = sin(x)&#8221;.</p>
<p>4.动态创建函数对象。虽然我没有特意在这个方面作研究，但是我相信这个库确实<br>
可以向这个方面发展。例如你打算写一个分析数学表达式的程序，这个库（或者其改<br>
进版本）将会非常有用。如果有人对这方面的利用抱有兴趣，请联系作者。</p>
<p>5.任何你能找到的用处&#8230;</p>
<p>也许你心动了，这么好的东西到哪里可以找到？很简单，点<a  href="http://www.joyloft.net/doc/exponent.zip">这里</a>就可以得到源码了，里面不但包含了所有的历史版本，还有作者写的几个sample。如果你有好的点子，要和作者联系，请写信到：yegong1985@鸡妹儿到炕</p>
<p><a  href="http://www.joyloft.net/?p=391">原文链接</a><br>
</p><img src ="http://www.cnblogs.com/flappy/aggbug/790323.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41956/" target="_blank">[新闻]中国互联网战争局势图</a>]]></description></item><item><title>ASCII码对照表</title><link>http://www.cnblogs.com/flappy/archive/2007/06/12/780079.html</link><dc:creator>李现民</dc:creator><author>李现民</author><pubDate>Tue, 12 Jun 2007 02:01:00 GMT</pubDate><guid>http://www.cnblogs.com/flappy/archive/2007/06/12/780079.html</guid><wfw:comment>http://www.cnblogs.com/flappy/comments/780079.html</wfw:comment><comments>http://www.cnblogs.com/flappy/archive/2007/06/12/780079.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/flappy/comments/commentRss/780079.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/flappy/services/trackbacks/780079.html</trackback:ping><description><![CDATA[<table class="tableBorder" align="center" cellpadding="0" cellspacing="0" width="90%">
    <caption>ASCII码表<br>
    <p>信息在计算机上是用二进制表示的，这种表示法让人理解就很困难。因此计算机上都配有输入和输出设备，这些设备的主要目的就是，以一种人类可阅读的形
    式将信息在这些设备上显示出来供人阅读理解。为保证人类和设备，设备和计算机之间能进行正确的信息交换，人们编制的统一的信息交换代码，这就是ASCII
    码表，它的全称是&#8220;美国信息交换标准代码&#8221;。</p>
    </caption>
    <tbody>
        <tr>
            <th width="10%">八进制</th>
            <th width="11%">十六进制</th>
            <th width="13%">十进制</th>
            <th width="8%">字符</th>
            <th width="13%">八进制</th>
            <th width="17%">十六进制</th>
            <th width="13%">十进制</th>
            <th width="15%">字符</th>
        </tr>
        <tr>
            <td>00</td>
            <td>00</td>
            <td>0</td>
            <td>nul</td>
            <td>100</td>
            <td>40</td>
            <td>64</td>
            <td>@</td>
        </tr>
        <tr>
            <td>01</td>
            <td>01</td>
            <td>1</td>
            <td>soh</td>
            <td>101</td>
            <td>41</td>
            <td>65</td>
            <td>A</td>
        </tr>
        <tr>
            <td>02</td>
            <td>02</td>
            <td>2</td>
            <td>stx</td>
            <td>102</td>
            <td>42</td>
            <td>66</td>
            <td>B</td>
        </tr>
        <tr>
            <td>03</td>
            <td>03</td>
            <td>3</td>
            <td>etx</td>
            <td>103</td>
            <td>43</td>
            <td>67</td>
            <td>C</td>
        </tr>
        <tr>
            <td>04</td>
            <td>04</td>
            <td>4</td>
            <td>eot</td>
            <td>104</td>
            <td>44</td>
            <td>68</td>
            <td>D</td>
        </tr>
        <tr>
            <td>05</td>
            <td>05</td>
            <td>5</td>
            <td>enq</td>
            <td>105</td>
            <td>45</td>
            <td>69</td>
            <td>E</td>
        </tr>
        <tr>
            <td>06</td>
            <td>06</td>
            <td>6</td>
            <td>ack</td>
            <td>106</td>
            <td>46</td>
            <td>70</td>
            <td>F</td>
        </tr>
        <tr>
            <td>07</td>
            <td>07</td>
            <td>7</td>
            <td>bel</td>
            <td>107</td>
            <td>47</td>
            <td>71</td>
            <td>G</td>
        </tr>
        <tr>
            <td>10</td>
            <td>08</td>
            <td>8</td>
            <td>bs</td>
            <td>110</td>
            <td>48</td>
            <td>72</td>
            <td>H</td>
        </tr>
        <tr>
            <td>11</td>
            <td>09</td>
            <td>9</td>
            <td>ht</td>
            <td>111</td>
            <td>49</td>
            <td>73</td>
            <td>I</td>
        </tr>
        <tr>
            <td>12</td>
            <td>0a</td>
            <td>10</td>
            <td>nl</td>
            <td>112</td>
            <td>4a</td>
            <td>74</td>
            <td>J</td>
        </tr>
        <tr>
            <td>13</td>
            <td>0b</td>
            <td>11</td>
            <td>vt</td>
            <td>113</td>
            <td>4b</td>
            <td>75</td>
            <td>K</td>
        </tr>
        <tr>
            <td>14</td>
            <td>0c</td>
            <td>12</td>
            <td>ff</td>
            <td>114</td>
            <td>4c</td>
            <td>76</td>
            <td>L</td>
        </tr>
        <tr>
            <td>15</td>
            <td>0d</td>
            <td>13</td>
            <td>er</td>
            <td>115</td>
            <td>4d</td>
            <td>77</td>
            <td>M</td>
        </tr>
        <tr>
            <td>16</td>
            <td>0e</td>
            <td>14</td>
            <td>so</td>
            <td>116</td>
            <td>4e</td>
            <td>78</td>
            <td>N</td>
        </tr>
        <tr>
            <td>17</td>
            <td>0f</td>
            <td>15</td>
            <td>si</td>
            <td>117</td>
            <td>4f</td>
            <td>79</td>
            <td>O</td>
        </tr>
        <tr>
            <td>20</td>
            <td>10</td>
            <td>16</td>
            <td>dle</td>
            <td>120</td>
            <td>50</td>
            <td>80</td>
            <td>P</td>
        </tr>
        <tr>
            <td>21</td>
            <td>11</td>
            <td>17</td>
            <td>dc1</td>
            <td>121</td>
            <td>51</td>
            <td>81</td>
            <td>Q</td>
        </tr>
        <tr>
            <td>22</td>
            <td>12</td>
            <td>18</td>
            <td>dc2</td>
            <td>122</td>
            <td>52</td>
            <td>82</td>
            <td>R</td>
        </tr>
        <tr>
            <td>23</td>
            <td>13</td>
            <td>19</td>
            <td>dc3</td>
            <td>123</td>
            <td>53</td>
            <td>83</td>
            <td>S</td>
        </tr>
        <tr>
            <td>24</td>
            <td>14</td>
            <td>20</td>
            <td>dc4</td>
            <td>124</td>
            <td>54</td>
            <td>84</td>
            <td>T</td>
        </tr>
        <tr>
            <td>25</td>
            <td>15</td>
            <td>21</td>
            <td>nak</td>
            <td>125</td>
            <td>55</td>
            <td>85</td>
            <td>U</td>
        </tr>
        <tr>
            <td>26</td>
            <td>16</td>
            <td>22</td>
            <td>syn</td>
            <td>126</td>
            <td>56</td>
            <td>86</td>
            <td>V</td>
        </tr>
        <tr>
            <td>27</td>
            <td>17</td>
            <td>23</td>
            <td>etb</td>
            <td>127</td>
            <td>57</td>
            <td>87</td>
            <td>W</td>
        </tr>
        <tr>
            <td>30</td>
            <td>18</td>
            <td>24</td>
            <td>can</td>
            <td>130</td>
            <td>58</td>
            <td>88</td>
            <td>X</td>
        </tr>
        <tr>
            <td>31</td>
            <td>19</td>
            <td>25</td>
            <td>em</td>
            <td>131</td>
            <td>59</td>
            <td>89</td>
            <td>Y</td>
        </tr>
        <tr>
            <td>32</td>
            <td>1a</td>
            <td>26</td>
            <td>sub</td>
            <td>132</td>
            <td>5a</td>
            <td>90</td>
            <td>Z</td>
        </tr>
        <tr>
            <td>33</td>
            <td>1b</td>
            <td>27</td>
            <td>esc</td>
            <td>133</td>
            <td>5b</td>
            <td>91</td>
            <td>[</td>
        </tr>
        <tr>
            <td>34</td>
            <td>1c</td>
            <td>28</td>
            <td>fs</td>
            <td>134</td>
            <td>5c</td>
            <td>92</td>
            <td>\</td>
        </tr>
        <tr>
            <td>35</td>
            <td>1d</td>
            <td>29</td>
            <td>gs</td>
            <td>135</td>
            <td>5d</td>
            <td>93</td>
            <td>]</td>
        </tr>
        <tr>
            <td>36</td>
            <td>1e</td>
            <td>30</td>
            <td>re</td>
            <td>136</td>
            <td>5e</td>
            <td>94</td>
            <td>^</td>
        </tr>
        <tr>
            <td>37</td>
            <td>1f</td>
            <td>31</td>
            <td>us</td>
            <td>137</td>
            <td>5f</td>
            <td>95</td>
            <td>_</td>
        </tr>
        <tr>
            <td>40</td>
            <td>20</td>
            <td>32</td>
            <td>sp</td>
            <td>140</td>
            <td>60</td>
            <td>96</td>
            <td>'</td>
        </tr>
        <tr>
            <td>41</td>
            <td>21</td>
            <td>33</td>
            <td>!</td>
            <td>141</td>
            <td>61</td>
            <td>97</td>
            <td>a</td>
        </tr>
        <tr>
            <td>42</td>
            <td>22</td>
            <td>34</td>
            <td>"</td>
            <td>142</td>
            <td>62</td>
            <td>98</td>
            <td>b</td>
        </tr>
        <tr>
            <td>43</td>
            <td>23</td>
            <td>35</td>
            <td>#</td>
            <td>143</td>
            <td>63</td>
            <td>99</td>
            <td>c</td>
        </tr>
        <tr>
            <td>44</td>
            <td>24</td>
            <td>36</td>
            <td>$</td>
            <td>144</td>
            <td>64</td>
            <td>100</td>
            <td>d</td>
        </tr>
        <tr>
            <td>45</td>
            <td>25</td>
            <td>37</td>
            <td>%</td>
            <td>145</td>
            <td>65</td>
            <td>101</td>
            <td>e</td>
        </tr>
        <tr>
            <td>46</td>
            <td>26</td>
            <td>38</td>
            <td>&amp;</td>
            <td>146</td>
            <td>66</td>
            <td>102</td>
            <td>f</td>
        </tr>
        <tr>
            <td>47</td>
            <td>27</td>
            <td>39</td>
            <td>`</td>
            <td>147</td>
            <td>67</td>
            <td>103</td>
            <td>g</td>
        </tr>
        <tr>
            <td>50</td>
            <td>28</td>
            <td>40</td>
            <td>(</td>
            <td>150</td>
            <td>68</td>
            <td>104</td>
            <td>h</td>
        </tr>
        <tr>
            <td>51</td>
            <td>29</td>
            <td>41</td>
            <td>)</td>
            <td>151</td>
            <td>69</td>
            <td>105</td>
            <td>i</td>
        </tr>
        <tr>
            <td>52</td>
            <td>2a</td>
            <td>42</td>
            <td>*</td>
            <td>152</td>
            <td>6a</td>
            <td>106</td>
            <td>j</td>
        </tr>
        <tr>
            <td>53</td>
            <td>2b</td>
            <td>43</td>
            <td>+</td>
            <td>153</td>
            <td>6b</td>
            <td>107</td>
            <td>k</td>
        </tr>
        <tr>
            <td>54</td>
            <td>2c</td>
            <td>44</td>
            <td>,</td>
            <td>154</td>
            <td>6c</td>
            <td>108</td>
            <td>l</td>
        </tr>
        <tr>
            <td>55</td>
            <td>2d</td>
            <td>45</td>
            <td>-</td>
            <td>155</td>
            <td>6d</td>
            <td>109</td>
            <td>m</td>
        </tr>
        <tr>
            <td>56</td>
            <td>2e</td>
            <td>46</td>
            <td>.</td>
            <td>156</td>
            <td>6e</td>
            <td>110</td>
            <td>n</td>
        </tr>
        <tr>
            <td>57</td>
            <td>2f</td>
            <td>47</td>
            <td>/</td>
            <td>157</td>
            <td>6f</td>
            <td>111</td>
            <td>o</td>
        </tr>
        <tr>
            <td>60</td>
            <td>30</td>
            <td>48</td>
            <td>0</td>
            <td>160</td>
            <td>70</td>
            <td>112</td>
            <td>p</td>
        </tr>
        <tr>
            <td>61</td>
            <td>31</td>
            <td>49</td>
            <td>1</td>
            <td>161</td>
            <td>71</td>
            <td>113</td>
            <td>q</td>
        </tr>
        <tr>
            <td>62</td>
            <td>32</td>
            <td>50</td>
            <td>2</td>
            <td>162</td>
            <td>72</td>
            <td>114</td>
            <td>r</td>
        </tr>
        <tr>
            <td>63</td>
            <td>33</td>
            <td>51</td>
            <td>3</td>
            <td>163</td>
            <td>73</td>
            <td>115</td>
            <td>s</td>
        </tr>
        <tr>
            <td>64</td>
            <td>34</td>
            <td>52</td>
            <td>4</td>
            <td>164</td>
            <td>74</td>
            <td>116</td>
            <td>t</td>
        </tr>
        <tr>
            <td>65</td>
            <td>35</td>
            <td>53</td>
            <td>5</td>
            <td>165</td>
            <td>75</td>
            <td>117</td>
            <td>u</td>
        </tr>
        <tr>
            <td>66</td>
            <td>36</td>
            <td>54</td>
            <td>6</td>
            <td>166</td>
            <td>76</td>
            <td>118</td>
            <td>v</td>
        </tr>
        <tr>
            <td>67</td>
            <td>37</td>
            <td>55</td>
            <td>7</td>
            <td>167</td>
            <td>77</td>
            <td>119</td>
            <td>w</td>
        </tr>
        <tr>
            <td>70</td>
            <td>38</td>
            <td>56</td>
            <td>8</td>
            <td>170</td>
            <td>78</td>
            <td>120</td>
            <td>x</td>
        </tr>
        <tr>
            <td>71</td>
            <td>39</td>
            <td>57</td>
            <td>9</td>
            <td>171</td>
            <td>79</td>
            <td>121</td>
            <td>y</td>
        </tr>
        <tr>
            <td>72</td>
            <td>3a</td>
            <td>58</td>
            <td>:</td>
            <td>172</td>
            <td>7a</td>
            <td>122</td>
            <td>z</td>
        </tr>
        <tr>
            <td>73</td>
            <td>3b</td>
            <td>59</td>
            <td>;</td>
            <td>173</td>
            <td>7b</td>
            <td>123</td>
            <td>{</td>
        </tr>
        <tr>
            <td>74</td>
            <td>3c</td>
            <td>60</td>
            <td>&lt;</td>
            <td>174</td>
            <td>7c</td>
            <td>124</td>
            <td>|</td>
        </tr>
        <tr>
            <td>75</td>
            <td>3d</td>
            <td>61</td>
            <td>=</td>
            <td>175</td>
            <td>7d</td>
            <td>125</td>
            <td>}</td>
        </tr>
        <tr>
            <td>76</td>
            <td>3e</td>
            <td>62</td>
            <td>&gt;</td>
            <td>176</td>
            <td>7e</td>
            <td>126</td>
            <td>~</td>
        </tr>
        <tr>
            <td>77</td>
            <td>3f</td>
            <td>63</td>
            <td>?</td>
            <td>177</td>
            <td>7f</td>
            <td>127</td>
            <td>del</td>
        </tr>
    </tbody>
</table><img src ="http://www.cnblogs.com/flappy/aggbug/780079.html?type=1" width = "1" height = "1" /><br><br><a href="http://news.cnblogs.com/n/41955/" target="_blank">[新闻]开源多点触摸技术试运行</a>]]></description></item><item><title>别人收集的资源</title><link>http://www.cnblogs.com/flappy/archive/2007/06/08/776186.html</link><dc:creator>李现民</dc:creator><author>李现民</author><pubDate>Fri, 08 Jun 2007 02:17:00 GMT</pubDate><guid>http://www.cnblogs.com/flappy/archive/2007/06/08/776186.html</guid><wfw:comment>http://www.cnblogs.com/flappy/comments/776186.html</wfw:comment><comments>http://www.cnblogs.com/flappy/archive/2007/06/08/776186.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cnblogs.com/flappy/comments/commentRss/776186.html</wfw:commentRss><trackback:ping>http://www.cnblogs.com/flappy/services/trackbacks/776186.html</trackback:ping><description><![CDATA[<p>tcl/tk 语言<br><a href="http://www.arsdigita.com/books/tcl/" target="_blank">http://www.arsdigita.com/books/tcl/</a> tutor zhandian<br><a href="http://www.sco.com/Technology/tcl/Tcl.html?" target="_blank">http://www.sco.com/Technology/tcl/Tcl.html&nbsp;</a>;&nbsp;TCL WWW
Info<br><br>VTK:<br><a href="http://www.kitware.com/" target="_blank">http://www.kitware.com</a> VTK主战；<br><a href="http://public.kitware.com/Insight/Web/index.htm?" target="_blank">http://public.kitware.com/Insight/Web/index.htm&nbsp;</a>;&nbsp;ITK a
toolkit for visible human project registration and segmentation, open source
under developing<br><a href="http://users.info.unicaen.fr/~karczma/docs/vtkhtml/Examples.html?" target="_blank">http://users.info.unicaen.fr/~karczma/docs/vtkhtml/Examples.html&nbsp;</a>;&nbsp;VTK
Examples sorted by Object<br><a href="http://www.cc.nih.gov/cip/software/etdips/?" target="_blank">http://www.cc.nih.gov/cip/software/etdips/&nbsp;</a>;&nbsp;Source Code<br><a href="http://www.image-registration.com/?" target="_blank">http://www.image-registration.com/&nbsp;</a>;&nbsp;VTK CISG Registration
Toolkit&nbsp;&nbsp;Too Cool!!!!!!!!!!!!!! voxel-based affine registration using Normalized
Mutual Information (NMI) voxel-based non-rigid registration (free form
deformation) on the basis of B-spline interpolation using Normalized Mutual
Information (NMI<br><a href="http://public.kitware.com/cgi-bin/vtkfaq" target="_blank">http://public.kitware.com/cgi-bin/vtkfaq</a>
VTK的FAQ，因为重要才单独写出来<br><a href="http://mailarchivers.ncsa.uiuc.edu/cgi-bin/mailarchivers/mainscreen.pl?archive=VTKUSERS?" target="_blank">http://mailarchivers.ncsa.uiuc.edu/cgi-bin/mailarchivers/mainscreen.pl?archive=VTKUSERS&nbsp;</a>;&nbsp;The
VTK Discussion Place,<br><a href="http://mailarchivers.ncsa.uiuc.edu/?" target="_blank">http://mailarchivers.ncsa.uiuc.edu/&nbsp;</a>;&nbsp;自己看吧<br><a href="http://www.barre.nom.fr/medical/index.html" target="_blank">http://www.barre.nom.fr/medical/index.html</a> 比较好的VTK个人站点<br><a href="http://www.esat.kuleuven.ac.be/~vtkedit/cgi-bin/download.pl?" target="_blank">http://www.esat.kuleuven.ac.be/~vtkedit/cgi-bin/download.pl&nbsp;</a>;&nbsp;
vtkEdit<br><a href="http://rrvtk.free.fr/vtk/perfs/" target="_blank">http://rrvtk.free.fr/vtk/perfs/</a> VTK Bench Marks 测试<br><a href="http://www.slicer.org/?" target="_blank">http://www.slicer.org&nbsp;</a>;&nbsp;MIT的VTK医学扩展要注册才能得到免费的和开放源码的程序的说。COOL<br><a href="http://www.crd.ge.com/~lorensen/seg12/" target="_blank">http://www.crd.ge.com/~lorensen/seg12/</a>＃introduction&nbsp;&nbsp;一个VTK的很好的例子<br><a href="http://www.lumens.com/vtk/index.html?" target="_blank">http://www.lumens.com/vtk/index.html&nbsp;</a>;&nbsp;The best VTK
instruction Site I have ever seen<br><a href="http://solvedeath.stanford.edu/~spicer/svr_html/svr.html?" target="_blank">http://solvedeath.stanford.edu/~spicer/svr_html/svr.html&nbsp;</a>;&nbsp;Open
source Sean&#8217;s Volume Rendering Library, on SGI Onyx2<br><a href="http://www.principiamathematica.com/?" target="_blank">http://www.principiamathematica.com/&nbsp;</a>;&nbsp;VizStudio, encapsulates
VTK<br><a href="http://mayavi.sourceforge.net/?" target="_blank">http://mayavi.sourceforge.net/&nbsp;</a>;&nbsp;a VTK Application<br><a href="http://www.atamai.com/?" target="_blank">http://www.atamai.com/&nbsp;</a>;&nbsp; an
VTK application<br><a href="http://www.crd.ge.com/esl/cgsp/?" target="_blank">http://www.crd.ge.com/esl/cgsp/&nbsp;</a>;&nbsp; GE The Computer Graphics
and Systems Program!!!<br><a href="http://cens.ioc.ee/projects/pyvtk/?" target="_blank">http://cens.ioc.ee/projects/pyvtk/&nbsp;</a>;&nbsp; PYVTK Project<br><a href="http://www.cineca.it/download/devel/vtkClasses.html" target="_blank">http://www.cineca.it/download/devel/vtkClasses.html</a> A Great
Deve Team for VTK<br><a href="http://www.colorado-research.com/~gourlay/software/Graphics/Ogle/?" target="_blank">http://www.colorado-research.com/~gourlay/software/Graphics/Ogle/&nbsp;</a>;&nbsp;very
excellent site!!<br><a href="http://www.medres.ch/~jstifter/vtkandqt/index.html?" target="_blank">http://www.medres.ch/~jstifter/vtkandqt/index.html&nbsp;</a>;&nbsp;VTK and
QT<br><a href="http://stsc.hill.af.mil/crosstalk/1997/dec/visualization.asp?" target="_blank">http://stsc.hill.af.mil/crosstalk/1997/dec/visualization.asp&nbsp;</a>;&nbsp;
visualization and measurement of source code<br><a href="http://newton.rex.dmu.ac.uk/~ronaldo/new/vtk.html?" target="_blank">http://newton.rex.dmu.ac.uk/~ronaldo/new/vtk.html&nbsp;</a>;&nbsp;A personal
website, not too bad<br><a href="http://ltswww.epfl.ch/~cuisenai/vtk/?" target="_blank">http://ltswww.epfl.ch/~cuisenai/vtk/&nbsp;</a>;&nbsp;A PostDoc Who writes
some vtk New Classes<br><a href="http://www.aero.iitm.ernet.in/~prabhu/software/vtk/index.html?" target="_blank">http://www.aero.iitm.ernet.in/~prabhu/software/vtk/index.html&nbsp;</a>;&nbsp;
VTK and Linux<br><br>可视化:<br><a href="http://www.j3d.org/tutorials/quick_fix/volume.html?" target="_blank">http://www.j3d.org/tutorials/quick_fix/volume.html&nbsp;</a>;&nbsp; Java 3D
volume rendering open source<br><a href="http://www.hpl.hp.com/ultravis/?" target="_blank">http://www.hpl.hp.com/ultravis/&nbsp;</a>;&nbsp; UltraVis is a free software
system for fast and versatile volume rendering on standard PCs. <br><a href="http://www.nas.nasa.gov/Groups/VisTech/visWeblets.html?" target="_blank">http://www.nas.nasa.gov/Groups/VisTech/visWeblets.html&nbsp;</a>;&nbsp;NASA的常用可视化连接<br><a href="http://www.opendx.org/" target="_blank">http://www.opendx.org</a>
IBM的开放源码的可视化开发工具，可惜对Windows支持很差的说，所以被开放的说<br><a href="http://www.avs.com/?" target="_blank">http://www.avs.com/&nbsp;</a>;&nbsp;Advanced Visualization System<br><a href="http://www.visualsky.com/?" target="_blank">http://www.visualsky.com/&nbsp;</a>;&nbsp;AVS的国内代理<br><a href="http://www.iavsc.org/?" target="_blank">http://www.iavsc.org/&nbsp;</a>;&nbsp;International AVS Center! Cool<br><a href="http://www.mayo.edu/bir/?" target="_blank">http://www.mayo.edu/bir/&nbsp;</a>;&nbsp;Mayo的，Analyzer非常有名<br><a href="http://www.vni.com/index.html" target="_blank">http://www.vni.com/index.html</a> PV－WAVE： Understanding Your
Data<br><a href="http://www.sci.utah.edu/pse/?" target="_blank">http://www.sci.utah.edu/pse/&nbsp;</a>;&nbsp;Scientific Computing and
Imaging<br><a href="http://raphael.mit.edu/pv3/pv3.html" target="_blank">http://raphael.mit.edu/pv3/pv3.html</a> co-processing
visualization of data generated in a distributed and parallel compute arenas
DOWNLOADING NEEDED<br><a href="http://www.nag.com/Welcome_IEC.html?" target="_blank">http://www.nag.com/Welcome_IEC.html&nbsp;</a>;&nbsp;IRIS Explorer<br><a href="http://seesar.lbl.gov/anag/?" target="_blank">http://seesar.lbl.gov/anag/&nbsp;</a>;&nbsp;Lawrence Berkeley National
Laboratory Applied Numerical Algorithms Group<br><a href="http://www.newcyber3d.com/?" target="_blank">http://www.newcyber3d.com&nbsp;</a>;&nbsp;Computer Graphics, not too
bad.<br><a href="http://solvedeath.stanford.edu/~spicer/svr_html/svr.html" target="_blank">http://solvedeath.stanford.edu/~spicer/svr_html/svr.html</a>
volumer extention<br><a href="http://www.vaytek.com/VoxBlast.html?" target="_blank">http://www.vaytek.com/VoxBlast.html&nbsp;</a>;&nbsp;3d measurement,
visualization and rendering<br><a href="http://ovt.irfu.se/?" target="_blank">http://ovt.irfu.se/&nbsp;</a>;&nbsp;Orbit Visualization tool for cluster,
Planet Visualization<br><a href="http://www.csee.umbc.edu/~rheingan/691V/?" target="_blank">http://www.csee.umbc.edu/~rheingan/691V/&nbsp;</a>;&nbsp;A good
visualization teching site<br><a href="http://www.princeton-tech.com/?" target="_blank">http://www.princeton-tech.com&nbsp;</a>;&nbsp; Visualization and Imaging
Tool<br><a href="http://www.esat.kuleuven.ac.be/~vtkedit/?" target="_blank">http://www.esat.kuleuven.ac.be/~vtkedit/&nbsp;</a>;&nbsp; VTK Edit<br><a href="http://www.terarecon.com/index.shtml?" target="_blank">http://www.terarecon.com/index.shtml&nbsp;</a>;&nbsp;Volumepro 的站点<br><a href="http://wwwvis.informatik.uni-stuttgart.de/~engel/?" target="_blank">http://wwwvis.informatik.uni-stuttgart.de/~engel/&nbsp;</a>;&nbsp;
非常好的个人Volume Rendering站点<br><a href="http://wwwvis.informatik.uni-stuttgart.de/eng/research/" target="_blank">http://wwwvis.informatik.uni-stuttgart.de/eng/research/</a>
同上<br><a href="http://www.j3d.org/tutorials/quick_fix/volume.html?" target="_blank">http://www.j3d.org/tutorials/quick_fix/volume.html&nbsp;</a>;&nbsp;Java 3D
Volume Rendering<br><a href="http://capderec.udg.es:81/ebt-bin/nph-dweb/dynaweb/SGI_Developer/VolumizerPG" target="_blank">http://capderec.udg.es:81/ebt-bin/nph-dweb/dynaweb/SGI_Developer/VolumizerPG</a>
SGI Volumier Program Guide<br><a href="http://www.ssec.wisc.edu/~billh/visad.html?" target="_blank">http://www.ssec.wisc.edu/~billh/visad.html&nbsp;</a>;&nbsp;Numerical
Visualization<br><a href="http://www.avl.iu.edu/projects/3DIVE/index.shtml?" target="_blank">http://www.avl.iu.edu/projects/3DIVE/index.shtml&nbsp;</a>;&nbsp;3D
Interactive Volume Environment for SGI<br><a href="http://graphics.stanford.edu/projects/volume/?" target="_blank">http://graphics.stanford.edu/projects/volume/&nbsp;</a>;&nbsp;Stanford
Volume Rendering Site<br><a href="http://www.vaytek.com/VoxBlast.html?" target="_blank">http://www.vaytek.com/VoxBlast.html&nbsp;</a>;&nbsp;VoxBlast<br><br>常用编程：<br><a href="http://crackpltools.prv.pl/?" target="_blank">http://crackpltools.prv.pl/&nbsp;</a>;&nbsp; Reverse Engineering Site<br><a href="http://www.man.ac.uk/MVC/?" target="_blank">http://www.man.ac.uk/MVC/&nbsp;</a>;&nbsp;Manchester Visualization Center-
lot of links and research based on AVS<br><a href="http://www.codeproject.com/" target="_blank">http://www.codeproject.com</a><br><a href="http://www.codeguru.com/" target="_blank">http://www.codeguru.com</a><br><a href="http://www.vchelp.net/" target="_blank">http://www.vchelp.net</a>
一个国内最好个人编程网站<br><a href="http://www.csdn.net/?" target="_blank">http://www.csdn.net&nbsp;</a>;&nbsp;程序员大本营， 有变好的趋势<br><a href="http://www.asfocus.com/?" target="_blank">http://www.asfocus.com&nbsp;</a>;&nbsp;中华技术网<br><a href="http://www.cetus-links.org/software.html" target="_blank">http://www.cetus-links.org/software.html</a> 我见过最好的编程网址链接<br><a href="http://www.cuj.com/link/index1.htm" target="_blank">http://www.cuj.com/link/index1.htm</a> 也是我见过最好的编程网址链接<br><a href="http://www.oradb.net/" target="_blank">http://www.oradb.net</a>
国内最好的介ORACLE开发的网站<br><a href="http://www.nease.net/~inetsoft/?" target="_blank">http://www.nease.net/~inetsoft/&nbsp;</a>;&nbsp;Programming Source Code,
very good<br><a href="http://www.wotsit.org/" target="_blank">http://www.wotsit.org/</a> 文件格式大全，感谢黄峰的推荐，虽然我从来没有用过<br><a href="http://www.twain.org/" target="_blank">http://www.twain.org</a>
扫描仪的公共接口开发<br><a href="http://www.geuz.org/gl2ps/?" target="_blank">http://www.geuz.org/gl2ps/&nbsp;</a>;&nbsp;OpenGL to PostScript
Library<br><a href="http://www.lvr.com/usb.htm" target="_blank">http://www.lvr.com/usb.htm</a> USB开发站点<br><a href="http://www.programmersheaven.com/" target="_blank">http://www.programmersheaven.com/</a> 网址链接，但我不常用<br><a href="http://www.widgetware.com/" target="_blank">http://www.widgetware.com/</a>
ATL编程的培训网站，有本书我买了<br><a href="http://www.componentsource.com/" target="_blank">http://www.componentsource.com/</a> 不用也要看看，呵呵<br><a href="http://www.worldofatl.com/" target="_blank">http://www.worldofatl.com/</a>
ATL世界<br><a href="http://www.active-x.com/" target="_blank">http://www.active-x.com/</a> <br><a href="http://developer.intel.com/software/products/perflib/index.htm" target="_blank">http://developer.intel.com/software/products/perflib/index.htm</a>
Intel Performance Suite， 不说了<br><a href="http://msdn.microsoft.com/default.asp?" target="_blank">http://msdn.microsoft.com/default.asp&nbsp;</a>;&nbsp;Microsoft MSDN<br><a href="http://www.freshsky.net/?" target="_blank">http://www.freshsky.net/&nbsp;</a>;&nbsp;Codeguru 国内镜像 <br><a href="http://www.atlworld.com/" target="_blank">www.atlworld.com</a>&nbsp;&nbsp;Coming
soon?<br><a href="http://www.bcgsoft.com/?" target="_blank">http://www.bcgsoft.com/&nbsp;</a>;&nbsp;Business Component Gallery, now
cooler than CJLibrary,&nbsp;&nbsp;that is XtremeKit now.<br><a href="http://www.wndtabs.com/" target="_blank">http://www.wndtabs.com/</a> <br><a href="http://www.cuj.com/link/subject61.htm?topic=link?" target="_blank">http://www.cuj.com/link/subject61.htm?topic=link&nbsp;</a>;&nbsp;&nbsp;&nbsp;Advanced
Solutions for C++ Programmers<br><a href="http://mfcfaq.stingray.com/?" target="_blank">http://mfcfaq.stingray.com/&nbsp;</a>;&nbsp;MFC FAQ, sponsored by Stringray
Software<br><a href="http://devcentral.iftech.com/?" target="_blank">http://devcentral.iftech.com/&nbsp;</a>;&nbsp;provide tutorials, articles,
code, and the ITCLib MFC Extension library - all free of charge<br><a href="http://www.cvshome.org/?" target="_blank">http://www.cvshome.org/&nbsp;</a>;&nbsp;Open
Source Version Control Software<br><a href="http://www.stingray.com/?" target="_blank">http://www.stingray.com/&nbsp;</a>;&nbsp;one of the most recommended site by
international developers, but I do not know why<br><a href="http://joyjava.dhs.org/?" target="_blank">http://joyjava.dhs.org/&nbsp;</a>;&nbsp;Joy
Java<br><a href="http://www.sysinternals.com/?" target="_blank">http://www.sysinternals.com/&nbsp;</a>;&nbsp;The Sysinternals web site
provides you with advanced utilities, technical information, and source code
related to Windows 9x, Windows Me, and Windows NT/2000 internals that you won\'t
find anywhere else<br><a href="http://www.hstart.com/?" target="_blank">http://www.hstart.com/&nbsp;</a>;&nbsp;MFC Extention<br><a href="http://www.thefreecountry.com/?" target="_blank">http://www.thefreecountry.com&nbsp;</a>;&nbsp;free Programmer&#8217;s resources,
free Webmaster&#8217;s resources, free&nbsp;&nbsp;internet software, free online documention
,Good!<br><a href="http://iihm.imag.fr/fberard/tclTkMans/tcltk8.0/contents.htm?" target="_blank">http://iihm.imag.fr/fberard/tclTkMans/tcltk8.0/contents.htm&nbsp;</a>;&nbsp;
Tcl/Tk Reference<br><a href="http://www.driverdevelop.com/?" target="_blank">http://www.driverdevelop.com/&nbsp;</a>;&nbsp; 硬件开发<br><a href="http://dev.scriptics.com/?" target="_blank">http://dev.scriptics.com/&nbsp;</a>;&nbsp;TCL World<br><br>Open
Source开发站