﻿<?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>C++博客-hex108-随笔分类-Algorithm</title><link>http://www.cppblog.com/hex108/category/17229.html</link><description>懂历史 ==&gt; 知未来
</description><language>zh-cn</language><lastBuildDate>Thu, 08 Sep 2011 07:58:50 GMT</lastBuildDate><pubDate>Thu, 08 Sep 2011 07:58:50 GMT</pubDate><ttl>60</ttl><item><title>[找工作]算法小结</title><link>http://www.cppblog.com/hex108/archive/2011/08/24/154248.html</link><dc:creator>hex108</dc:creator><author>hex108</author><pubDate>Wed, 24 Aug 2011 13:39:00 GMT</pubDate><guid>http://www.cppblog.com/hex108/archive/2011/08/24/154248.html</guid><wfw:comment>http://www.cppblog.com/hex108/comments/154248.html</wfw:comment><comments>http://www.cppblog.com/hex108/archive/2011/08/24/154248.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/hex108/comments/commentRss/154248.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/hex108/services/trackbacks/154248.html</trackback:ping><description><![CDATA[<div>为一个问题寻找算法的过程，有点像一个穷举过程：搜索已有知识，并进行重组的过程。所以把常用的算法记住，然后一个一个试用，看是否可行，不失为一个好方法。<div><div>如果这个方法不行呢？不妨写出最直观的解答（即用&#8220;蛮力法&#8221;），然后从中看出可以优化的地方在哪里，进而进行优化。</div></div><br /><br /><div>如何确定该问题可以用哪类方法来解答呢？首先，需要对这些常用的算法的基本思想非常熟悉。<br />常用的算法可以分为以下几类：</div>1. Divide &amp; conquer<br />&nbsp;&nbsp; 分治算法：将问题分为两个1／2规模大小的子问题，然后解决。如merge sort<br /><br />2. Decrease &amp; conquer<br />&nbsp;&nbsp; 减治法 : 将问题规模从 n 变为 n - 1，然后在规模n-1的基础上解决此问题。 如insertion sort&nbsp;&nbsp; <br />&nbsp;&nbsp; 这不是递归么？<br /><br />3. Transform &amp; conquer<br />&nbsp;&nbsp; 变治法 ：变换结构。如heap sort&nbsp; &nbsp;<br /><br />4. Brute force<br />&nbsp;&nbsp; 蛮力算法，可以说是必杀技吧，大部分问题都可以用此方法解决。 如selection sort<br />&nbsp;&nbsp; 使用蛮力法的优点是简单不容易出错，缺点是复杂度有时很高，所以我们可以在穷举法的基础上进行改进，这样能达到一举双得的效果。<br /> &nbsp;&nbsp;&nbsp;<a href="http://en.wikipedia.org/wiki/Backtracking" title="Backtracking">Backtracking</a>(<a title="回溯法" href="http://zh.wikipedia.org/wiki/%E5%9B%9E%E6%BA%AF%E6%B3%95">回溯法</a>) 是 Brute fore搜索算法的一种，它通常用最简单的递归方法来实现，在最坏的情况下，回溯法会导致一次复杂度为指数时间的计算。其比较经典的运用是：N皇后问题。<br /><br />其次，数据结构有时候会决定算法，例 Transform &amp; conquer。</div><br />另外在TopLanguage上看到的一些有用的观点：<br /><a title="1." href="http://groups.google.com/group/pongba/browse_thread/thread /f70e1e9cbbd0ff74/e88ea88461471830?hl=en&amp;lnk=gst&amp;q=%E7%AE%97%E6 %B3%95#e88ea88461471830">1.</a> 算法里面极大一部分内容是如何有效地进行搜索，这里的"有效"可以分为：避免不必要的计算（如A*寻路以及所有的启发式剪枝），缓存重复计算（如所有的动 态规划）。<br /><a title="2." href="http://groups.google.com/group/pongba/browse_thread/thread/46336822b202f36d/88e499b680011bb2?hl=en&amp;lnk=gst&amp;q=%E8%A7%A3%E7%A9%BA%E9%97%B4#88e499b680011bb2">2.</a>本质上，练习并不产生新能力。然而练习最重要的一个作用就是将<a title="外显记忆" href="http://en.wikipedia.org/wiki/Explicit_memory">外显记忆</a>转化为<a title="内隐记忆" href="http://en.wikipedia.org/wiki/Implicit_memory">内隐记忆</a>。用大白话来说就是将平时需要用脑子去想（参与）的东西转化为内在的习惯。譬如我们一开始学骑自行车的时候需要不断提醒自己注意平衡，但随着不断的联系，这种技能就内化成了所谓的<a title="程序式记忆" href="http://en.wikipedia.org/wiki/Procedural_memory">程序式记忆</a> <br />&nbsp;&nbsp; 这就是熟能生巧吧。<img src ="http://www.cppblog.com/hex108/aggbug/154248.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/hex108/" target="_blank">hex108</a> 2011-08-24 21:39 <a href="http://www.cppblog.com/hex108/archive/2011/08/24/154248.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[找工作]动态规划与贪心算法</title><link>http://www.cppblog.com/hex108/archive/2011/08/24/154243.html</link><dc:creator>hex108</dc:creator><author>hex108</author><pubDate>Wed, 24 Aug 2011 12:51:00 GMT</pubDate><guid>http://www.cppblog.com/hex108/archive/2011/08/24/154243.html</guid><wfw:comment>http://www.cppblog.com/hex108/comments/154243.html</wfw:comment><comments>http://www.cppblog.com/hex108/archive/2011/08/24/154243.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/hex108/comments/commentRss/154243.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/hex108/services/trackbacks/154243.html</trackback:ping><description><![CDATA[<div>1. <a title="动态规划" href="http://en.wikipedia.org/wiki/Dynamic_programming">动态规划</a><br />
<div>&nbsp;&nbsp; Dynamic programming, like the divideand-conquer method, solves problems by combinging the solutions to subproblems.</div>
&nbsp;&nbsp; 1) 动态规划适用于优化问题：从很多个解中找到最优解。(Dynamic progrmming is typicall applied to optimization problems.)<br />
<br />
<div>&nbsp;&nbsp; 2) 适合用动态规划解决的问题有两个特征：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; a. optimal substructure(http://en.wikipedia.org/wiki/Optimal_substructure)<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 用一个公式化的式子把它的solution表示出来会更清晰。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; b. overlapping subproblems <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如果不是overlapping subproblems，用分治法就可以解决了。动态规划正是利用了重复子问题这个特性，将子问题的解存起来以便重复利用。</div>
&nbsp;&nbsp; 3) 如何划分子问题<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 以问题 "An activity-selection problem"为例，CLRS划分的方法和我的就不同。<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 注意：如果划分的子问题之间存在依赖，那么该问题就不适合用动态规划解决。（见CLRS 15.3 subtlties小节）<br />
<br />
&nbsp;&nbsp;&nbsp; 4) reconsturcting an optimal solution&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 用动态规划有个问题就是在最后得到最优解时不能知道选择的过程，有如下两种方法可以解决：<br />
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; a. 可以根据我们存下来的信息推导出前一步的选择是什么，如：<a title="diff.java" href="http://introcs.cs.princeton.edu/java/96optimization/Diff.java.html">diff.java</a><br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; b. 记下选择。<br />
&nbsp; &nbsp; &nbsp;&nbsp; 如果选择较少可以采用方法a，否则选择方法2比较好。这是一个时空权衡问题。</div>
<div>&nbsp;&nbsp;&nbsp; 5）运用动态规划有几个需要注意的地方：<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; a.&nbsp; We must ensure that when we search for the correct place to spilt the product, we have considered all possible places so that we are sure of&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; having examined the optimal one.<br />
&nbsp; &nbsp;&nbsp;&nbsp;&nbsp; b.&nbsp; The subproblems are independent.</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; c.&nbsp; 不要形成困定思维: 一想到动态规划，马上联想到LCS，然后觉得动态规划的表结构就是一个二维数组</div>
&nbsp;&nbsp;&nbsp; 6)思考<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 子问题有最优解，那么该问题得到的一定是最优解吗？ 如果不是，那么什么情况下是全局最优解，什么情况是局部最优解?<br />
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 以＜编程之美＞上的一个例子举例说明如下 :(有时间再补上)</div>
<br />
2. 贪心算法&nbsp;&nbsp; <br />
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; A greedy algorithm always makes the choice that looks best at the moment. That is , it makes a locally optimal choce in the hope that chis choce will lead to a globally optimal solution.</div>
<br />
<div>&nbsp;&nbsp;&nbsp;&nbsp; 贪心法能解决的问题，动态规划基本都能解决。（CLRS 16.2 Nevertheless, beneath every greedy algorithm, ther is almost always a more cumbersome dynamic-progrmming solution）。</div>
<div>&nbsp;&nbsp; &nbsp; 但是：For many optimization problems, using dynamic programming to determine the best choices is overkill; Simpler, more effiiect algorithms will do. (eg: greedy algorithm)<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp; 1）适合用贪心法解决的问题 <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 必须要有Greedy-choice property : a globally optiaml solution can be arrivedat by making a locally optimal (greedy) choice.<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如：Huffman编码，最小生成树</div>
&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 2）贪心法的一般步骤&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; a. 将原问题划分为子2个子问题（非overlap的），此时就能用动态规划求解了<br />
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; b. 找到一个划分点，让其中一个子问题变为空，则只剩下一个子问题了，这就是贪心算法</div>
&nbsp;<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 3）使用贪心法时必须保证：
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; We must prove that a greedy choice at each step yields a golbally optimal solution, and this is where cleverness may be required. <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这点也是最难的。所以有个问题<span style="color: red;">&#8220;什么情况下，局部最优最终会产生全局最优的结果？&#8221;</span></div>
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 4）适用贪心算法的问题有 greedy-choice propertty，需要找到一个贪心策略。<br />
<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 5）对于找不到全局最优解的问题（如NP问题），可以考虑贪心算法。<br />
<br />
3. 动态规划与分治法的比较<br />
<br />
&nbsp; &nbsp;&nbsp;&nbsp; 分治法适合于那些能被分解为独立子问题的问题；动态规划更适用于子问题之间不是独立的，而是会share subproblems。动态规划的这个特点得益于它把子问题的结果都保存在一个表中了（动态规划的英文名字是Dynamic Programming，这里的Programming可理解为a tabular method(表格方法)），这样就能少去重复子问题的计算。 所以动态规划可以算作是分治法在overlapping 子问题里的一个优化（这个优化在程序中是常见的优化方法Memoization（http://en.wikipedia.org/wiki/Memoization））<br />
<br />
4. 动态规划与贪心法的比较<br />
&nbsp;&nbsp; 1) 相同点<br />
&nbsp;&nbsp;&nbsp;&nbsp; a. 问题要有optimal substructure&nbsp;
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; A problem exhibits optimalsubstructure if an optimal solution to the problem contains within it optimal solutions to subproblems.&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 这是能用贪心法与动态规划解答的问题的关键因素。<br />
&nbsp;&nbsp;&nbsp;&nbsp; b. 都需要划分子问题，但是划分子问题的方式有些区别，见下面的不同点。<br />
&nbsp; <br />
&nbsp;&nbsp; 2）不同点<br />
&nbsp;&nbsp;&nbsp;&nbsp; a.&nbsp; 划分子问题
<div>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 如果你把划分的子问题有交集(overloapping subproblem)，这就很显然地将你引入了动态规划的思维，以"An activity-selection problem"举例说明：<br />
<div>&nbsp; &nbsp; &nbsp; &nbsp; 对于问题 "An activity-selection problem"，很容易就能想到动态规划的解法<br />
<div style="background-color: #eeeeee; font-size: 13px; border-top-width: 1px; border-right-width: 1px; border-bottom-width: 1px; border-left-width: 1px; border-top-style: solid; border-right-style: solid; border-bottom-style: solid; border-left-style: solid; border-top-color: #cccccc; border-right-color: #cccccc; border-bottom-color: #cccccc; border-left-color: #cccccc; padding-top: 4px; padding-right: 5px; padding-bottom: 4px; padding-left: 4px; width: 98%; "><!--<br />
<br />
Code highlighting produced by Actipro CodeHighlighter (freeware)<br />
http://www.CodeHighlighter.com/<br />
<br />
--><span style="color: #0000FF; "><div><span style="color: #000000; ">int select_activity(int *a, int n, int i)</span></div><div><span style="color: #000000; ">{</span></div><div><span style="color: #000000; ">&nbsp; &nbsp; if(i &gt;=n )</span></div><div><span style="color: #000000; ">&nbsp; &nbsp; &nbsp; &nbsp; return 0;</span></div><div><span style="color: #000000; ">&nbsp; &nbsp; for(j= i + 1; j &lt; n; j ++){</span></div><div><span style="color: #000000; ">&nbsp; &nbsp; &nbsp; &nbsp; if(a[j].start &gt;= a[i].end)</span></div><div><span style="color: #000000; ">&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; break;</span></div><div><span style="color: #000000; ">&nbsp; &nbsp; }</span></div><div><span style="color: #000000; ">&nbsp; &nbsp; int sum1 = select_activity(a, n, j) + 1; &nbsp; //select the ith activity</span></div><div><span style="color: #000000; ">&nbsp; &nbsp; int sum2 = select_activity(a, n, i + 1); &nbsp; //not select the ith activity</span></div><div>&nbsp; &nbsp;&nbsp;</div><div><span style="color: #000000; ">&nbsp; &nbsp; if(sum1 &gt; sum2)</span></div><div><span style="color: #000000; ">&nbsp; &nbsp; &nbsp; &nbsp; return sum1;</span></div><div><span style="color: #000000; ">&nbsp; &nbsp; else</span></div><div><span style="color: #000000; ">&nbsp; &nbsp; &nbsp; &nbsp; return sum2;</span></div><div><span style="color: #000000; ">}</span></div>
</span><span style="color: #000000; "></span></div>
&nbsp;&nbsp;&nbsp; 但是如何将它转化为贪心算法呢？<br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 答案是：由这种方法是不易转化为贪心法的。上面这种划分子问题的方式表明了它更适合于动态规划，就像在CLRS 383页里说到的0-1背包问题：The problem formulated in this way gives rise to many over-lapping subproblems － a hallmark of dynamic programming.</div>
</div>
</div>
&nbsp;<br />
&nbsp;&nbsp;&nbsp; b.&nbsp; 贪心法： make whaterver choice seems best a the moment and then solve the subproblem arising after the choice is made.<br />
<div>&nbsp; &nbsp; &nbsp; &nbsp; 动态规划：make a choice at each step, but the choice usually depends on the solutions to subproblems.<br />
<br />
&nbsp;&nbsp;&nbsp; c.&nbsp; 贪心法：top-down fashinon&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br />
&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 动态规划：bottom-up manner</div>
<br />
&nbsp; &nbsp;<br />
&nbsp;</div><img src ="http://www.cppblog.com/hex108/aggbug/154243.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/hex108/" target="_blank">hex108</a> 2011-08-24 20:51 <a href="http://www.cppblog.com/hex108/archive/2011/08/24/154243.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>[找工作]数据结构小结</title><link>http://www.cppblog.com/hex108/archive/2011/08/24/154241.html</link><dc:creator>hex108</dc:creator><author>hex108</author><pubDate>Wed, 24 Aug 2011 12:15:00 GMT</pubDate><guid>http://www.cppblog.com/hex108/archive/2011/08/24/154241.html</guid><wfw:comment>http://www.cppblog.com/hex108/comments/154241.html</wfw:comment><comments>http://www.cppblog.com/hex108/archive/2011/08/24/154241.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/hex108/comments/commentRss/154241.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/hex108/services/trackbacks/154241.html</trackback:ping><description><![CDATA[&nbsp;要找工作了，终于觉得是时候总结一下数据结构了（ps: 对于数组，链表这样简单常用的结构就不总结了，此文会持续更新），总结有助于更好地思考。<br /><br />1. 位图<br />&nbsp;&nbsp;&nbsp; 位图的威力可以在＜编程珠玑＞的开头就体会到。另外在<a title="Find an integer not among four billion given ones" href="http://stackoverflow.com/questions/7153659/find-an-integer-not-among-four-billion-given-ones">Find an integer not among four billion given ones</a>中的运用也很精彩。<br /><br />2. 堆<br /><div>&nbsp;&nbsp; 在＜编程珠玑＞里重点运用了该结构，直接导致我以后经常想到并使用该结构。<br />&nbsp;&nbsp; 不得不说，它真的很有用，如：找N个数中最大／最小的k个数。<br />&nbsp;&nbsp; 实现优先级队列时也有用。</div><br />3. 树<br /><div>&nbsp;&nbsp;&nbsp;&nbsp; 二叉搜索树：是一个很容易就能想到的结构，只要让一棵二叉树满足以下一个特性就可以了：对于任一结点N，其左子树结点left满足key(x) &lt;= key(N)，其右子树结点right满足key(y) &gt;= key(N)，其优点是操作简单，缺点是插入，删除结点的复杂度高，为O(N)<br />&nbsp;&nbsp;&nbsp;&nbsp; 二叉搜索树复杂度高的原因为：树的高度不确定/不稳定，有可能为n，所以问题的关键是：如何控制树的高度<br />&nbsp;&nbsp;&nbsp;&nbsp; 很多人灵机一动:产生了一系列平衡二叉树，如：AVL树，Red-Black树，<a title="Treap" href="http://en.wikipedia.org/wiki/Treap">Treap</a><br />&nbsp;&nbsp;&nbsp;&nbsp; 也产生了很多平衡二叉树的变种，如：<a title="Weight balanced tree" href="http://en.wikipedia.org/wiki/Weight-balanced_tree">Weight balanced tree</a>，k-neighbor tree等 <br />&nbsp;&nbsp;&nbsp;&nbsp; <a title="Skip List" href="http://en.wikipedia.org/wiki/Skip_list">Skip List</a> 也是平衡二叉树之外的另一种选择<br />&nbsp;&nbsp;&nbsp;&nbsp; <a href="http://en.wikipedia.org/wiki/Trie" title="Trie树">Trie树</a> 用来存储一个字典，然后用来查找某个字符串还是很方便的（A trie can be seen as a deterministic finite automaton.） 另外可以看看<a href="http://en.wikipedia.org/wiki/Suffix_tree" title="Suffix_tree">Suffix_tree</a>后缀树。<br /><br />4. hash<br />&nbsp;&nbsp;&nbsp; hash的两个关键点在于：a. hash桶大小的设定（一般为一个素数） b. 冲突处理机制，如可以用一个链表处理hash值相同的元素。<br />&nbsp;&nbsp;&nbsp; 我很少考虑hash，觉得复杂度不好把握。以后倒是可以考虑用用，如：在问题&#8220;判断两个链表是否相交&#8221;有可以使用hash；&#8220;判断链表有没有环&#8221;用hash也很给力。</div><img src ="http://www.cppblog.com/hex108/aggbug/154241.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/hex108/" target="_blank">hex108</a> 2011-08-24 20:15 <a href="http://www.cppblog.com/hex108/archive/2011/08/24/154241.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>关于算法的一些资料</title><link>http://www.cppblog.com/hex108/archive/2011/07/01/149939.html</link><dc:creator>hex108</dc:creator><author>hex108</author><pubDate>Fri, 01 Jul 2011 12:27:00 GMT</pubDate><guid>http://www.cppblog.com/hex108/archive/2011/07/01/149939.html</guid><wfw:comment>http://www.cppblog.com/hex108/comments/149939.html</wfw:comment><comments>http://www.cppblog.com/hex108/archive/2011/07/01/149939.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/hex108/comments/commentRss/149939.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/hex108/services/trackbacks/149939.html</trackback:ping><description><![CDATA[<span style="font-family: verdana, 'courier new'; font-size: 14px; line-height: 21px; ">算法的过程很详细，美中不足的是</span>最基本最常用的那些算法其实是比较少的，花点时间多想想为什么，知其然还要知其所以然(<a title="1" href="http://mindhacks.cn/2008/07/07/the-importance-of-knowing-why/">1</a>，<a href="http://mindhacks.cn/2010/11/14/the-importance-of-knowing-why-part2/" title="2">2</a>)，这样才能活学活用。<br /><br />1. 书
<br />1.1 <a href="http://book.douban.com/subject/3227098/" title="编程珠玑">编程珠玑</a><br />&nbsp;&nbsp;&nbsp; 言简意赅，回味无穷。本书的网络版在 <a href="http://netlib.bell-labs.com/cm/cs/pearls/" title="http://netlib.bell-labs.com/cm/cs/pearls/">http://netlib.bell-labs.com/cm/cs/pearls/</a> 上，附有源代码。 <a href="http://www.cppblog.com/hex108/archive/2011/07/07/150403.html" title="这里">这里</a>有我的读书总结。 受到此书的影响，我对代码产生了很强的洁癖，坚信代码还可以写得更优美，更艺术。此外面对一个问题时分析的角度更多了。<br /><br />1.2&nbsp;<a title="编程之美" href="http://book.douban.com/subject/3004255/">编程之美</a><br />&nbsp; &nbsp; &nbsp;书上的每个题都会仔细地做，并完成代码。思考的乐趣是无穷的，时常会有乐趣。<br /><br />1.3&nbsp;<a title="算法导论" href="http://book.douban.com/subject/1152912/">算法导论<br /></a>&nbsp; &nbsp;经典但是比较厚，适合系统地学习算法，而后每次遇到不懂的可以再查阅，<div style="display: inline-block; "></div>算法的过程很详细，美中不足的是没有知其所以然的感觉。看此书第一遍时，是按照书的顺序看的，对这些算法大致都有熟悉了。后来会偶尔查阅。现在为了准备算法，会时常查阅此书。<a title="算法导论" href="http://book.douban.com/subject/1152912/"><br /></a><br />2. 文章<br />2.1&nbsp;<a title="Do We Teach the Right Algorithm Design Techniques ?" href="http://www.csc.villanova.edu/~levitin/paper.html">Do We Teach the Right Algorithm Design Techniques ?</a> <br />&nbsp;&nbsp; 把算法按其通用程度提出了4个最基本的算法思想：Brute force ， Divide &amp; conquer ， Decrease &amp; conquer，&nbsp; Transform &amp; conquer。<br />&nbsp;&nbsp; 读完后可以对算法的整体有更好的掌握。<br /><br />3. 网络教程<br />3.1 <a href="http://www.topcoder.com/tc?module=Static&amp;d1=tutorials&amp;d2=alg_index" title="Top Coder的algorithm tutorial">Top Coder的algorithm tutorial</a><img src ="http://www.cppblog.com/hex108/aggbug/149939.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/hex108/" target="_blank">hex108</a> 2011-07-01 20:27 <a href="http://www.cppblog.com/hex108/archive/2011/07/01/149939.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>二分查找 --  来自编程珠玑</title><link>http://www.cppblog.com/hex108/archive/2011/06/18/148907.html</link><dc:creator>hex108</dc:creator><author>hex108</author><pubDate>Sat, 18 Jun 2011 07:02:00 GMT</pubDate><guid>http://www.cppblog.com/hex108/archive/2011/06/18/148907.html</guid><wfw:comment>http://www.cppblog.com/hex108/comments/148907.html</wfw:comment><comments>http://www.cppblog.com/hex108/archive/2011/06/18/148907.html#Feedback</comments><slash:comments>2</slash:comments><wfw:commentRss>http://www.cppblog.com/hex108/comments/commentRss/148907.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/hex108/services/trackbacks/148907.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 二分查找法（<a title="Binary search algorithm" href="http://en.wikipedia.org/wiki/Binary_search_algorithm">Binary search algorithm</a>）是一个很常见的算法，从＜编程珠玑＞里再次看到时又有新的收获。<br />
&nbsp; &nbsp;&nbsp; 直接看代码吧，下面是常见的实现代码：<br />&nbsp;&nbsp;&nbsp;&nbsp; <div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; 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;binary_search(</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">a,&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;num,&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;t)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;start&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">,&nbsp;end&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;num&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">1</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">while</span><span style="color: #000000; ">(end&nbsp;</span><span style="color: #000000; ">&gt;=</span><span style="color: #000000; ">&nbsp;start){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;middle&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;(start&nbsp;</span><span style="color: #000000; ">+</span><span style="color: #000000; ">&nbsp;end)&nbsp;</span><span style="color: #000000; ">/</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">2</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;tmp&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;a[middle];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">(tmp&nbsp;</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">&nbsp;t){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;start&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;middle&nbsp;</span><span style="color: #000000; ">+</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">1</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span><span style="color: #0000FF; ">else</span><span style="color: #000000; ">&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">(tmp&nbsp;</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">&nbsp;t){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;end&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;middle&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">1</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span><span style="color: #0000FF; ">else</span><span style="color: #000000; ">{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;middle;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">1</span><span style="color: #000000; ">;<br />}&nbsp;&nbsp;&nbsp; <br /></span></div><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 优化后的代码为（这个优化的思想也挺好的，不知道有没有一套系统的方法来思考出这个优化思路）：<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<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;binary_search(</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">a,&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;num,&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;t)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;low&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">1</span><span style="color: #000000; ">,&nbsp;high&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;num&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">1</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">while</span><span style="color: #000000; ">(low&nbsp;</span><span style="color: #000000; ">+</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">1</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">!=</span><span style="color: #000000; ">&nbsp;high){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;middle&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;(low&nbsp;</span><span style="color: #000000; ">+</span><span style="color: #000000; ">&nbsp;high)&nbsp;</span><span style="color: #000000; ">/</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">2</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">(a[middle]&nbsp;</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">&nbsp;t){<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;low&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;middle;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span><span style="color: #0000FF; ">else</span><span style="color: #000000; ">{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;high&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;middle;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">(a[high]&nbsp;</span><span style="color: #000000; ">!=</span><span style="color: #000000; ">&nbsp;t)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">1</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">else</span><span style="color: #000000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;high;<br />}<br /></span></div>&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp; 如果直接看这段代码，有可能不知道是怎么回事。但是运用书中提到的&#8220;<span style="color: red;">程序验证</span>&#8221;的方法后，原理就显而易见了，修改后的代码为：<br /><br /><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008080; ">&nbsp;1</span>&nbsp;<span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;binary_search(</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">a,&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;num,&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;t)<br /></span><span style="color: #008080; ">&nbsp;2</span>&nbsp;<span style="color: #000000; ">{<br /></span><span style="color: #008080; ">&nbsp;3</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;low&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">1</span><span style="color: #000000; ">,&nbsp;high&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;num&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">1</span><span style="color: #000000; ">;<br /></span><span style="color: #008080; ">&nbsp;4</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;<br /></span><span style="color: #008080; ">&nbsp;5</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">invariant:&nbsp;low&nbsp;&lt;&nbsp;high&nbsp;&amp;&amp;&nbsp;a[low]&nbsp;&lt;&nbsp;t&nbsp;&amp;&amp;&nbsp;a[high]&nbsp;&gt;=&nbsp;t</span><span style="color: #008000; "><br /></span><span style="color: #008080; ">&nbsp;6</span>&nbsp;<span style="color: #008000; "></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">while</span><span style="color: #000000; ">(low&nbsp;</span><span style="color: #000000; ">+</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">1</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">!=</span><span style="color: #000000; ">&nbsp;high){<br /></span><span style="color: #008080; ">&nbsp;7</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;middle&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;(low&nbsp;</span><span style="color: #000000; ">+</span><span style="color: #000000; ">&nbsp;high)&nbsp;</span><span style="color: #000000; ">/</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">2</span><span style="color: #000000;">;&nbsp; </span><span style="color: red;">＝＝＞</span><span style="color: #000000;">&nbsp; int middle = low + (high - low) / 2;&nbsp;&nbsp; //防止溢出<br /></span><span style="color: #008080; ">&nbsp;8</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">(a[middle]&nbsp;</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">&nbsp;t){<br /></span><span style="color: #008080; ">&nbsp;9</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;low&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;middle;<br /></span><span style="color: #008080; ">10</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}</span><span style="color: #0000FF; ">else</span><span style="color: #000000; ">{<br /></span><span style="color: #008080; ">11</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;high&nbsp;</span><span style="color: #000000; ">=</span><span style="color: #000000; ">&nbsp;middle;<br /></span><span style="color: #008080; ">12</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br /></span><span style="color: #008080; ">13</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;}</span><span style="color: #008080; "></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp; <div><span style="color: #000000;"><span style="color: #008000; ">14&nbsp;&nbsp;&nbsp; //</span><span style="color: #008000; ">assert：　low&nbsp;+1&nbsp;=&nbsp;high&nbsp;&amp;&amp;&nbsp;a[low]&nbsp;&lt;&nbsp;t&nbsp;&amp;&amp;&nbsp;a[high]&nbsp;&gt;=&nbsp;t</span><span style="color: #008000; "><br /></span></span></div></span><span style="color: #008080; ">15</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp; </span><span style="color: #008000; "><br /></span><span style="color: #008080; ">16</span>&nbsp;<span style="color: #008000; "></span><span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">(a[high]&nbsp;</span><span style="color: #000000; ">!=</span><span style="color: #000000; ">&nbsp;t)<br /></span><span style="color: #008080; ">17</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">-</span><span style="color: #000000; ">1</span><span style="color: #000000; ">;<br /></span><span style="color: #008080; ">18</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">else</span><span style="color: #000000; "><br /></span><span style="color: #008080; ">19</span>&nbsp;<span style="color: #000000; ">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;high;<br /></span><span style="color: #008080; ">20</span>&nbsp;<span style="color: #000000; ">}<br /></span><span style="color: #008080; ">21</span>&nbsp;<span style="color: #000000; "></span></div><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; &#8220;程序验证&#8221; 的思想可以简述为：不管是验证一个函数，还是一条语句，一个控制结构（循环，if分支等），都可以采用两个断言（前置条件和后置条件）来达到这个目的。前置条件是在执行该处代码之前就应该成立的条件，后置条件的正确性在执行完该处代码后必须得到保证。（ps: 断言也算是一种验证的手段）<br /><br />　　上面这段代码的原理是给定一段区间 (low, high] ，如果満足 a[low] &lt; t&nbsp; &amp;&amp; a[high] &gt;=t &amp;&amp; high = low + 1，那么有两种情况存在：1. a[high] = t ; 2.与t相等的元素不存在。由于数组a 肯定满足条件a[low] &lt; t&nbsp; &amp;&amp; a[high] &gt;=t，所以该算法要做的就是把区间 (-1, num -1] 缩小到(low, low+1]。 　<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 1. 在执行代码6~17行时，<span>始终保证</span><span style="color: #008000;">low &lt;&nbsp;high&nbsp;&amp;&amp;&nbsp;a[low]&nbsp;&lt;&nbsp;t&nbsp;&amp;&amp;&nbsp;a[high]&nbsp;&gt;=&nbsp;t</span><span style="color: #008000;"> </span><span>成立。</span><span style="color: #008000;"><br />　　</span>2. 在执行完6~17行后，肯定滿足条件a[low] &lt; t&nbsp; &amp;&amp; a[high] &gt;=t &amp;&amp; high = low + 1，因为循环退出的条件是 high = low + 1，而该循环始终保证<span></span>上面第１条。<br />　　经过这样的分析后，我们能对程序的正确性有更好的掌握，同时程序也更易理解。<br /><br />参考：<br />　　１. 基本上摘自＜<a title="编程珠玑" href="http://book.douban.com/subject/3227098/">编程珠玑</a>＞，很不错的一本书，让我对算法有了新的思考，以前只是看看算法导论如何实现的，没有思考该算法是如何想出来的，有没有更简单的算法（思考的过程类似刘未鹏的＜<a href="http://mindhacks.cn/2010/11/14/the-importance-of-knowing-why-part2/" title="知其所以然（续）">知其所以然（续）</a>＞），要坚持这个思考过程需要很多功夫与时间，但效果也很明显，能对算法有更好的掌握。<img src ="http://www.cppblog.com/hex108/aggbug/148907.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/hex108/" target="_blank">hex108</a> 2011-06-18 15:02 <a href="http://www.cppblog.com/hex108/archive/2011/06/18/148907.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>