﻿<?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++博客-beautykingdom-随笔分类-Algorithm</title><link>http://www.cppblog.com/beautykingdom/category/7545.html</link><description /><language>zh-cn</language><lastBuildDate>Wed, 04 Jul 2012 05:24:42 GMT</lastBuildDate><pubDate>Wed, 04 Jul 2012 05:24:42 GMT</pubDate><ttl>60</ttl><item><title>从B 树、B+ 树、B* 树谈到R 树《转》</title><link>http://www.cppblog.com/beautykingdom/archive/2012/06/30/180893.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Sat, 30 Jun 2012 09:15:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2012/06/30/180893.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/180893.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2012/06/30/180893.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/180893.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/180893.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: &nbsp;&nbsp;作者：July、weedge、Frankie。编程艺术室出品。说明：本文从B树开始谈起，然后论述B+树、B*树，最后谈到R&nbsp;树。其中B树、B+树及B*树部分由weedge完成，R&nbsp;树部分由Frankie完成，全文最终由July统稿修订完成。出处：http://blog.csdn.net/v_JULY_v&nbsp;。&nbsp;第...&nbsp;&nbsp;<a href='http://www.cppblog.com/beautykingdom/archive/2012/06/30/180893.html'>阅读全文</a><img src ="http://www.cppblog.com/beautykingdom/aggbug/180893.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2012-06-30 17:15 <a href="http://www.cppblog.com/beautykingdom/archive/2012/06/30/180893.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Which is asymptotically larger: lg(lg* n) or lg*(lg n)$? &lt;&lt;convert&gt;&gt;</title><link>http://www.cppblog.com/beautykingdom/archive/2012/04/15/171537.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Sun, 15 Apr 2012 12:12:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2012/04/15/171537.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/171537.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2012/04/15/171537.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/171537.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/171537.html</trackback:ping><description><![CDATA[from:<br /><br /><a href="http://math.stackexchange.com/questions/55720/which-is-asymptotically-larger-lglg-n-or-lglg-n">http://math.stackexchange.com/questions/55720/which-is-asymptotically-larger-lglg-n-or-lglg-n</a><img border="0" alt="" src="http://www.cppblog.com/images/cppblog_com/beautykingdom/2.jpg" width="675" height="273" /><br /><br /><img border="0" alt="" src="http://www.cppblog.com/images/cppblog_com/beautykingdom/1.JPG" width="663" height="498" /><br /><br /><br /><img border="0" alt="" src="http://www.cppblog.com/images/cppblog_com/beautykingdom/3.jpg" width="676" height="124" /><br /><br /><img src ="http://www.cppblog.com/beautykingdom/aggbug/171537.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2012-04-15 20:12 <a href="http://www.cppblog.com/beautykingdom/archive/2012/04/15/171537.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Doubly-linked list</title><link>http://www.cppblog.com/beautykingdom/archive/2011/01/02/137879.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Sun, 02 Jan 2011 04:04:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2011/01/02/137879.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/137879.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2011/01/02/137879.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/137879.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/137879.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: basic doubly linked list algorithm&nbsp;&nbsp;<a href='http://www.cppblog.com/beautykingdom/archive/2011/01/02/137879.html'>阅读全文</a><img src ="http://www.cppblog.com/beautykingdom/aggbug/137879.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2011-01-02 12:04 <a href="http://www.cppblog.com/beautykingdom/archive/2011/01/02/137879.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>利用斯特林公式求解n！</title><link>http://www.cppblog.com/beautykingdom/archive/2010/09/16/126792.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Thu, 16 Sep 2010 11:24:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2010/09/16/126792.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/126792.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2010/09/16/126792.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/126792.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/126792.html</trackback:ping><description><![CDATA[
<h2 style="font-family: verdana, arial, sans-serif; color: rgb(204, 204, 204); text-transform: uppercase; font-weight: bold; font-size: 0.8em; margin-top: 8px; line-height: 19px; "><span style="color: rgb(0, 0, 0); font-weight: normal; text-transform: none; "><strong>&nbsp;&nbsp;&nbsp;<img src="http://www.cppblog.com/images/cppblog_com/lapcca/13342/o_stirling.gif"></strong></span></h2><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font-size: 13px; color: rgb(204, 204, 204); font-family: verdana, arial, sans-serif; line-height: 19px; "><span style="color: rgb(255, 0, 0); "><font color="#000000"><strong>from:</strong></font></span></p><p style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; font-size: 13px; color: rgb(204, 204, 204); font-family: verdana, arial, sans-serif; line-height: 19px; "><span style="color: rgb(255, 0, 0); "><font color="#000000"><strong></strong></font></span></p><h2 style="padding-right: 0px; padding-left: 0px; font-weight: bold; font-size: 0.8em; padding-bottom: 0px; margin-top: 8px; margin-right: 0px; margin-bottom: 8px; margin-left: 0px; text-transform: uppercase; color: rgb(204, 204, 204); padding-top: 0px; border-bottom-color: rgb(221, 221, 221); border-bottom-width: 1px; border-bottom-style: solid; font-family: verdana, arial, sans-serif; line-height: 19px; "><font color="#000000"><strong><a id="viewpost1_TitleUrl" href="http://www.cppblog.com/lapcca/archive/2010/09/13/126499.html" style="color: rgb(204, 204, 204); text-decoration: underline; background-color: rgb(245, 245, 245); font-weight: bold; font-size: 14px; ">http://www.cppblog.com/lapcca/archive/2010/09/13/126499.html</a></strong></font></h2><p>&#160;</p>
<img src ="http://www.cppblog.com/beautykingdom/aggbug/126792.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2010-09-16 19:24 <a href="http://www.cppblog.com/beautykingdom/archive/2010/09/16/126792.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>radix sort</title><link>http://www.cppblog.com/beautykingdom/archive/2010/08/03/122107.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Tue, 03 Aug 2010 13:43:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2010/08/03/122107.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/122107.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2010/08/03/122107.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/122107.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/122107.html</trackback:ping><description><![CDATA[<p class=para></p>
<p class=para>
<p class=first-para><strong class=bold><em class=emphasis>Radix sort</em></strong> is the algorithm used by the card-sorting machines you now find only in computer museums. The cards are organized into 80 columns, and in each column a hole can be punched in one of 12 places. The sorter can be mechanically "programmed" to examine a given column of each card in a deck and distribute the <a name=539></a><a name=IDX-171></a>card into one of 12 bins depending on which place has been punched. An operator can then gather the cards bin by bin, so that cards with the first place punched are on top of cards with the second place punched, and so on.</p>
<p class=para>For decimal digits, only 10 places are used in each column. (The other two places are used for encoding nonnumeric characters.) A <em class=emphasis>d</em>-digit number would then occupy a field of <em class=emphasis>d</em> columns. Since the card sorter can look at only one column at a time, the problem of sorting <em class=emphasis>n</em> cards on a <em class=emphasis>d</em>-digit number requires a sorting algorithm.</p>
<p class=para>Intuitively, one might want to sort numbers on their <em class=emphasis>most significant</em> digit, sort each of the resulting bins recursively, and then combine the decks in order. Unfortunately, since the cards in 9 of the 10 bins must be put aside to sort each of the bins, this procedure generates many intermediate piles of cards that must be kept track of. (See <a class=internaljump href="">Exercise 8.3-5</a>.)</p>
<p class=para>Radix sort solves the problem of card sorting counterintuitively by sorting on the <em class=emphasis>least significant</em> digit first. The cards are then combined into a single deck, with the cards in the 0 bin preceding the cards in the 1 bin preceding the cards in the 2 bin, and so on. Then the entire deck is sorted again on the second-least significant digit and recombined in a like manner. The process continues until the cards have been sorted on all <em class=emphasis>d</em> digits. Remarkably, at that point the cards are fully sorted on the <em class=emphasis>d</em>-digit number. Thus, only <em class=emphasis>d</em> passes through the deck are required to sort. <a class=internaljump href="">Figure 8.3</a> shows how radix sort operates on a "deck" of seven 3-digit numbers.</p>
<div class=figure>&nbsp;<br style="LINE-HEIGHT: 1"><span class=figure-title><span class=figure-titlelabel><img border=0 alt="" src="http://www.cppblog.com/images/cppblog_com/beautykingdom/untitled.JPG" width=325 height=155><br>Figure 8.3: </span>The operation of radix sort on a list of seven 3-digit numbers. The leftmost column is the input. The remaining columns show the list after successive sorts on increasingly significant digit positions. Shading indicates the digit position sorted on to produce each list from the previous one.</span> </div>
<p class=para>It is essential that the digit sorts in this algorithm be stable. The sort performed by a card sorter is stable, but the operator has to be wary about not changing the order of the cards as they come out of a bin, even though all the cards in a bin have the same digit in the chosen column.</p>
<p class=para>In a typical computer, which is a sequential random-access machine, radix sort is sometimes used to sort records of information that are keyed by multiple fields. For example, we might wish to sort dates by three keys: year, month, and day. We could run a sorting algorithm with a comparison function that, given two dates, compares years, and if there is a tie, compares months, and if another tie occurs, <a name=541></a><a name=IDX-172></a>compares days. Alternatively, we could sort the information three times with a stable sort: first on day, next on month, and finally on year.</p>
<p class=para>The code for radix sort is straightforward. The following procedure assumes that each element in the <em class=emphasis>n</em>-element array <em class=emphasis>A</em> has <em class=emphasis>d</em> digits, where digit 1 is the lowest-order digit and digit <em class=emphasis>d</em> is the highest-order digit.</p>
<div class=informalexample>
<pre class=literallayout-normal>RADIX-SORT(<em class=emphasis>A</em>, <em class=emphasis>d</em>)
1  <strong class=bold>for</strong> <em class=emphasis>i</em> <span class=unicode>&#8592;</span> 1 <strong class=bold>to</strong> <em class=emphasis>d</em>
2     <strong class=bold>do</strong> use a stable sort to sort array <em class=emphasis>A</em> on digit <em class=emphasis>i</em>
</pre>
</div>
<div class=example><span class=example-title><span class=example-titlelabel>Lemma 8.3</span></span>
<div class=formalbody>
<table class=BlueLine border=0 cellSpacing=0 cellPadding=0 width="100%">
    <tbody>
        <tr>
            <td class=bluecell bgColor=#000080><font color=#010100 size=2 face=Arial><strong><img border=0 alt="Start example" src="" width=" src_cetemp=" height=2 ?></strong></font></td>
        </tr>
    </tbody>
</table>
<p class=first-para>Given <em class=emphasis>n d</em>-digit numbers in which each digit can take on up to <em class=emphasis>k</em> possible values, RADIX-SORT correctly sorts these numbers in <span class=unicode>&#920;</span>(<em class=emphasis>d</em>(<em class=emphasis>n</em> + <em class=emphasis>k</em>)) time.</p>
<p class=last-para><strong class=bold><em class=emphasis>Proof</em></strong> The correctness of radix sort follows by induction on the column being sorted (see <a class=internaljump href="">Exercise 8.3-3</a>). The analysis of the running time depends on the stable sort used as the intermediate sorting algorithm. When each digit is in the range 0 to <em class=emphasis>k</em>-1 (so that it can take on <em class=emphasis>k</em> possible values), and <em class=emphasis>k</em> is not too large, counting sort is the obvious choice. Each pass over <em class=emphasis>n d</em>-digit numbers then takes time <span class=unicode>&#920;</span>(<em class=emphasis>n</em> + <em class=emphasis>k</em>). There are <em class=emphasis>d</em> passes, so the total time for radix sort is <span class=unicode>&#920;</span>(<em class=emphasis>d</em>(<em class=emphasis>n</em> + <em class=emphasis>k</em>)).</p>
<table class=BlueLine border=0 cellSpacing=0 cellPadding=0 width="100%">
    <tbody>
        <tr>
            <td class=bluecell bgColor=#000080><font color=#010100 size=2 face=Arial><strong><img border=0 alt="End example" src="" width=" src_cetemp=" height=2 ?></strong></font></td>
        </tr>
    </tbody>
</table>
<table class=BlankSpace border=0 cellSpacing=0 cellPadding=0 width="100%">
    <tbody>
        <tr>
            <td height=16></td>
        </tr>
    </tbody>
</table>
</div>
</div>
<p class=para>When <em class=emphasis>d</em> is constant and <em class=emphasis>k</em> = <em class=emphasis>O</em>(<em class=emphasis>n</em>), radix sort runs in linear time. More generally, we have some flexibility in how to break each key into digits.</p>
<div class=example><span class=example-title><span class=example-titlelabel>Lemma 8.4</span></span>
<div class=formalbody>
<table class=BlueLine border=0 cellSpacing=0 cellPadding=0 width="100%">
    <tbody>
        <tr>
            <td class=bluecell bgColor=#000080><font color=#010100 size=2 face=Arial><strong><img border=0 alt="Start example" src="" width=" src_cetemp=" height=2 ?></strong></font></td>
        </tr>
    </tbody>
</table>
<p class=first-para>Given <em class=emphasis>n b</em>-bit numbers and any positive integer <em class=emphasis>r</em> <span class=unicode>&#8804;</span> <em class=emphasis>b</em>, RADIX-SORT correctly sorts these numbers in <span class=unicode>&#920;</span>((<em class=emphasis>b/r</em>)(<em class=emphasis>n</em> + 2<sup><em class=emphasis>r</em></sup>)) time.</p>
<p class=last-para><strong class=bold><em class=emphasis>Proof</em></strong> For a value <em class=emphasis>r</em> <span class=unicode>&#8804;</span> <em class=emphasis>b</em>, we view each key as having <em class=emphasis>d</em> = <span class=unicode>&#8968;</span><em class=emphasis>b/r</em><span class=unicode>&#8969;</span> digits of <em class=emphasis>r</em> bits each. Each digit is an integer in the range 0 to 2<sup><em class=emphasis>r</em></sup> - 1, so that we can use counting sort with <em class=emphasis>k</em> = 2<sup><em class=emphasis>r</em></sup> - 1. (For example, we can view a 32-bit word as having 4 8-bit digits, so that <em class=emphasis>b</em> = 32, <em class=emphasis>r</em> = 8, <em class=emphasis>k</em> = 2<sup><em class=emphasis>r</em></sup> - 1 = 255, and <em class=emphasis>d</em> = <em class=emphasis>b/r</em> = 4.) Each pass of counting sort takes time <span class=unicode>&#920;</span>(<em class=emphasis>n</em> + <em class=emphasis>k</em>) = <span class=unicode>&#920;</span>(<em class=emphasis>n</em> + 2<sup><em class=emphasis>r</em></sup>) and there are <em class=emphasis>d</em> passes, for a total running time of <span class=unicode>&#920;</span>(<em class=emphasis>d</em>(<em class=emphasis>n</em> + 2<sup><em class=emphasis>r</em></sup> )) = <span class=unicode>&#920;</span>((<em class=emphasis>b</em>/<em class=emphasis>r</em>)(<em class=emphasis>n</em> + 2<sup><em class=emphasis>r</em></sup>)).</p>
<table class=BlueLine border=0 cellSpacing=0 cellPadding=0 width="100%">
    <tbody>
        <tr>
            <td class=bluecell bgColor=#000080><font color=#010100 size=2 face=Arial><strong><img border=0 alt="End example" src="" width=" src_cetemp=" height=2 ?></strong></font></td>
        </tr>
    </tbody>
</table>
<table class=BlankSpace border=0 cellSpacing=0 cellPadding=0 width="100%">
    <tbody>
        <tr>
            <td height=16></td>
        </tr>
    </tbody>
</table>
</div>
</div>
<p>&#160;</p>
<p class=para></p>
<p class=para>For given values of <em class=emphasis>n</em> and <em class=emphasis>b</em>, we wish to choose the value of <em class=emphasis>r</em>, with <em class=emphasis>r</em> <span class=unicode>&#8804;</span> <em class=emphasis>b</em>, that minimizes the expression (<em class=emphasis>b/r</em>)(<em class=emphasis>n</em> + 2<sup><em class=emphasis>r</em></sup>). If <em class=emphasis>b</em> <span class=unicode>&lt;</span> <span class=unicode>&#8970;</span>lg <em class=emphasis>n</em><span class=unicode>&#8971;</span>, then for any value of <em class=emphasis>r</em> <em class=emphasis>b</em>, we have that (<em class=emphasis>n</em> + 2<sup><em class=emphasis>r</em></sup>) = <span class=unicode>&#920;</span>(<em class=emphasis>n</em>). Thus, choosing <em class=emphasis>r</em> = <em class=emphasis>b</em> yields a running time of (<em class=emphasis>b/b</em>)(<em class=emphasis>n</em> + 2<sup><em class=emphasis>b</em></sup>) = <span class=unicode>&#920;</span>(<em class=emphasis>n</em>), which is asymptotically optimal. If <em class=emphasis>b</em> <span class=unicode>&#8805;</span> <span class=unicode>&#8970;</span>lg <em class=emphasis>n</em><span class=unicode>&#8971;</span>, then choosing <em class=emphasis>r</em> = <span class=unicode>&#8970;</span>lg <em class=emphasis>n</em><span class=unicode>&#8971;</span> gives the best time to within a constant factor, which we can see as follows. Choosing <em class=emphasis>r</em> = <span class=unicode>&#8970;</span>lg <em class=emphasis>n</em><span class=unicode>&#8971;</span> yields a running time of <span class=unicode>&#920;</span>(<em class=emphasis>bn</em>/ lg <em class=emphasis>n</em>). As we increase <em class=emphasis>r</em> above <span class=unicode>&#8970;</span>lg <em class=emphasis>n</em><span class=unicode>&#8971;</span>, the 2<sup><em class=emphasis>r</em></sup> term in the numerator increases faster than <a name=542></a><a name=IDX-173></a>the <em class=emphasis>r</em> term in the denominator, and so increasing <em class=emphasis>r</em> above <span class=unicode>&#8970;</span>lg <em class=emphasis>n</em><span class=unicode>&#8971;</span> yields a running time of <span class=unicode>&#920;</span>(<em class=emphasis>bn</em>/ lg <em class=emphasis>n</em>). If instead we were to decrease <em class=emphasis>r</em> below <span class=unicode>&#8970;</span>lg <em class=emphasis>n</em><span class=unicode>&#8971;</span>, then the <em class=emphasis>b/r</em> term increases and the <em class=emphasis>n</em> + 2<sup><em class=emphasis>r</em></sup> term remains at <span class=unicode>&#920;</span>(<em class=emphasis>n</em>).</p>
<p class=para>Is radix sort preferable to a comparison-based sorting algorithm, such as quick-sort? If <em class=emphasis>b</em> = <em class=emphasis>O</em>(lg <em class=emphasis>n</em>), as is often the case, and we choose <em class=emphasis>r</em> <span class=unicode>≈</span> lg <em class=emphasis>n</em>, then radix sort's running time is <span class=unicode>&#920;</span>(<em class=emphasis>n</em>), which appears to be better than quicksort's average-case time of <span class=unicode>&#920;</span>(<em class=emphasis>n</em> lg <em class=emphasis>n</em>). The constant factors hidden in the <span class=unicode>&#920;</span>-notation differ, however. Although radix sort may make fewer passes than quicksort over the <em class=emphasis>n</em> keys, each pass of radix sort may take significantly longer. Which sorting algorithm is preferable depends on the characteristics of the implementations, of the underlying machine (e.g., quicksort often uses hardware caches more effectively than radix sort), and of the input data. Moreover, the version of radix sort that uses counting sort as the intermediate stable sort does not sort in place, which many of the <span class=unicode>&#920;</span>(<em class=emphasis>n</em> lg <em class=emphasis>n</em>)-time comparison sorts do. Thus, when primary memory storage is at a premium, an in-place algorithm such as quicksort may be preferable</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<p>&nbsp;</p>
<img src ="http://www.cppblog.com/beautykingdom/aggbug/122107.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2010-08-03 21:43 <a href="http://www.cppblog.com/beautykingdom/archive/2010/08/03/122107.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Google之Page Rank分析</title><link>http://www.cppblog.com/beautykingdom/archive/2010/04/05/111678.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Mon, 05 Apr 2010 09:15:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2010/04/05/111678.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/111678.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2010/04/05/111678.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/111678.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/111678.html</trackback:ping><description><![CDATA[<p><font size="3">首先申明，本博文自原创，部分数据来源于网络。</font></p>
<p><font size="3">在<font face="Times New Roman">google</font>的
搜索结果中，<font face="Times New Roman">PR</font>值越
高的网页排在越前面。</font></p>
<p><font size="3">网页权重的算法有很多种，为何我唯独选择了<font face="Times New
Roman">page rank</font>来讨论，不仅因为它是<font face="Times New Roman">Google</font>搜索引擎采用的搜索结果排名算法之核心，且它把整
个互联网当做一个整体来对待且最终依靠经典的数学模型精准地得到<font face="Times New Roman">web</font>上
网页的权重。</font></p>
<p><font size="3">虽然今天的搜索引擎的排名系统远远要比这个算法复杂。域名数据，内容质量，用户数据，建站时间等都可能被考虑进去，但是<font face="Times New Roman">page rank</font>算法仍然是核心的技术之一，使得<font face="Times New Roman">Google</font>名声大噪。关于<font face="Times New Roman">page rank</font>的介绍性文章，在<a href="http://googlechinablog.com/"><font color="#0000ff"><font face="Times New Roman">Google</font>黑板报</font></a>里的<font face="Times New Roman">&#8221;</font><a href="http://googlechinablog.com/2006/02/page-rank-google.html"><font face="Times New Roman"> </font><font color="#0000ff">谈<font face="Times New Roman"> Page Rank </font>&#8211;<font face="Times New Roman"> Google </font>的民主表决式网页排名技术</font></a><font face="Times New Roman">&#8221;</font>。关于其更详细的论述，可以参照<font face="Times New Roman">Google </font>的两个创始人拉里&#8226;佩奇<font face="Times New Roman"> </font>（<font face="Times
New Roman">Larry Page </font>）和谢尔盖&#8226;布林<font face="Times New Roman"> (Sergey Brin)</font>的论文<font face="Times New Roman"><strong> &#8221;</strong> </font><a href="http://ilpubs.stanford.edu:8090/422/"><font face="Times New Roman"><font color="#0000ff"><strong> The PageRank Citation Ranking: Bringing Order
to the Web</strong> </font>&#8221;</font></a>。</font></p>
<p><font size="3">首先，<font face="Times New Roman">page rank</font>基
于以下的假设：<font face="Times New Roman">&#8221;</font>一个
网页被引用<font face="Times New Roman"> (</font>即反向
链接<font face="Times New Roman">)</font>的次数越多，则
说明越重要<font face="Times New Roman">; </font>一个网
页虽然没有被多次引用，但是被重要的网页引用，则它也可能是很重要的；一个网页的重要性被平均的传递到它所引用的网页。<font face="Times New Roman">&#8221;</font>所以，为了说明问题的方便，就引出了下面这个简化了的<font face="Times New Roman">Page Rank</font>算法。简化版一：<font face="Times New Roman">R(u) = c</font>R(1)/N(1) + &#8230;&#8230;+cR(v)/N(v)。(v&#8712;Bu)。
其中R(v)是网页v的PR值，N(v)是
网页v的正向链接数，B(u)是页面u的反向链接的集合。c是
阻尼系数(Damping Factor)，它的值在0到1之间。因
此，阻尼系数的使用，减少了其它页面对当前页面A的排序贡献。那么这个式子如何用数学的方法解答呢？首先可以认为整个互联网是
一个大的有向图G=(V,E)。V是所有页面的集合，E是有向边的集
合，(i,j)表示页i有指向页j的超链接。由于有向图和矩阵在本质上
是可以互相转换的，下面举例是如何互转的：</font></p>
<p><font size="3"><strong><em><img class="blogimg" style="width: 475px; height: 326px;" small="0" src="http://hiphotos.baidu.com/alphahunters/pic/item/58aacfdedf9d7b8acc116606.jpg" align="left" border="0" height="458" width="475">  </em></strong></font></p>
<p>
<strong><em> </em></strong></p>
<p>
<strong><em> </em></strong></p>
<p>
<strong><em> </em></strong></p>
<p>
<strong><em> </em></strong></p>
<p>
<strong><em> </em></strong></p>
<p>
<strong><em> </em></strong></p>
<p>
<strong><em> </em></strong></p>
<p>
<strong><em> </em></strong></p>
<p>
<strong><em> </em></strong></p>
<p>
<strong><em> </em></strong></p>
<p>
<strong><em> </em></strong></p>
<p>
<strong><em> </em></strong></p>
<p>
<strong><em> </em></strong></p>
<p>
<strong><em> </em></strong></p>
<p>
<strong><em> </em></strong></p>
<p>
<strong><em> </em></strong></p>
<p>
<strong><em> </em></strong></p>
<p>
<strong><em> </em></strong></p>
<p>
<strong><em> </em></strong></p>
<p>
<strong><em> </em></strong></p>
<p>
<strong><em> </em></strong></p>
<p>
<strong><em> </em></strong></p>
<p>
<strong><em> </em></strong></p>
<p>
<strong><em> </em></strong></p>
<p>
<strong><em> </em></strong></p>
<p>
<strong><em> </em></strong></p>
<p>
<strong><em> </em></strong></p>
<p>
<strong><em> </em></strong></p>
<p>
<strong><em> </em></strong></p>
<p>
<strong><em> </em></strong></p>
<p>
<strong><em> </em></strong></p>
<p>
<strong><em> </em></strong></p>
<p>
<strong><em> </em></strong></p>
<p>
<strong><em> </em></strong></p>
<p>
<strong><em> </em></strong></p>
<p>
<strong><em> </em></strong></p>
<p>
<strong><em> </em></strong></p>
<p>
<strong><em> </em></strong></p>
<p>
<strong><em> </em></strong></p>
<p>
<strong><em> </em></strong></p>
<p><strong><em><strong> <em> <font size="4">此有向连通图模拟网页间的超链接</font></em> </strong> </em></strong></p>
<p><strong><em><font size="3">链接源I D 链接目标 ID</font></em></strong></p>
<p><strong><em><font size="3">1&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  &nbsp;&nbsp;&nbsp;
2,3 ,4,5, 7</font></em></strong></p>
<p><strong><em><font size="3">2&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  &nbsp;&nbsp;&nbsp;
1</font></em></strong></p>
<p><strong><em><font size="3">3&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  &nbsp;&nbsp;&nbsp;
1,2 </font></em></strong></p>
<p><strong><em><font size="3">4&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  &nbsp;&nbsp;&nbsp;
2,3,5</font></em></strong></p>
<p><strong><em><font size="3">5 &nbsp;&nbsp;&nbsp;&nbsp;  &nbsp;&nbsp;&nbsp;&nbsp;1,3,4,6
</font></em></strong></p>
<p><strong><em><font size="3">6&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  &nbsp;&nbsp;&nbsp;
1,5</font></em></strong></p>
<p><strong><em><font size="3">7&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  &nbsp;&nbsp;&nbsp;
5</font></em></strong></p>
<p><strong><em><font size="3">如果我们假设Aij＝1 ,if (从页面
i 向页面 j 「有 」 链接的情况) ；Aij＝0,
if (从页面 i 向页面 j 「没有」链接的情况) 。
则根据以上我们可以构造如下矩阵</font></em></strong></p>
<p><strong><em><font size="3">A = [</font></em></strong></p>
<p><strong><em><font size="3">&nbsp;&nbsp;  0, 1, 1, 1, 1, 0, 1; </font></em></strong></p>
<p><strong><em><font size="3">&nbsp;&nbsp;  1, 0, 0, 0, 0, 0, 0;</font></em></strong></p>
<p><strong><em><font size="3">&nbsp;&nbsp;  1, 1, 0, 0, 0, 0, 0; </font></em></strong></p>
<p><strong><em><font size="3">&nbsp;&nbsp;  0, 1, 1, 0, 1, 0, 0;</font></em></strong></p>
<p><strong><em><font size="3">&nbsp;&nbsp;  1, 0, 1, 1, 0, 1, 0;</font></em></strong></p>
<p><strong><em><font size="3">&nbsp;&nbsp;  1, 0, 0, 0, 1, 0, 0; </font></em></strong></p>
<p><strong><em><font size="3">&nbsp;&nbsp;  0, 0, 0, 0, 1, 0, 0; </font></em></strong></p>
<p><strong><em><font size="3">]</font></em></strong></p>
<p><strong><em><font size="3">接下来再来看看公式一中的PR值求法，即</font></em></strong></p>
<p><strong><em><font size="3">PR(1) = c[1*PR(2) + (1/2)*PR(3) + (1/4)*PR(5) +(1/2)*PR(6)];</font></em></strong></p>
<p><strong><em><font size="3">PR(2) = c[(1/5)*PR(1) + (1/2)*PR(3) + 0.25*PR(5) + 0.5*PR(5)];</font></em></strong></p>
<p><strong><em><font size="3">............</font></em></strong></p>
<p><strong><em><font size="3">PR(7) = c[(1/5)*PR(1) + 0+ 0......];</font></em></strong></p>
<p><strong><em><font size="3">则，可以得出P<sup>T = </sup>cMP<sup>T</sup><sup>，</sup>其中M的方阵如下，</font></em></strong></p>
<p><strong><em><font size="3">M = [ </font></em></strong></p>
<p><strong><em><font size="3">&nbsp;&nbsp;&nbsp;  0, &nbsp;&nbsp;&nbsp;1,&nbsp;&nbsp;  1/2,&nbsp;&nbsp;&nbsp;  0, &nbsp;&nbsp;&nbsp;  1/4,&nbsp;&nbsp;&nbsp;  1/2,&nbsp;&nbsp;&nbsp;
0; </font></em></strong></p>
<p><strong><em><font size="3">&nbsp;&nbsp;&nbsp;  1/5,&nbsp;&nbsp;&nbsp;  0, 1/2,&nbsp;&nbsp;&nbsp;  1/3,&nbsp;&nbsp;&nbsp;
0, &nbsp;&nbsp;&nbsp;  0, &nbsp;&nbsp;&nbsp;  0; </font></em></strong></p>
<p><strong><em><font size="3">&nbsp;&nbsp;&nbsp;  1/5,&nbsp;&nbsp;&nbsp;  0, 0, &nbsp;&nbsp;&nbsp;  1/3,&nbsp;&nbsp;&nbsp;  1/4,&nbsp;&nbsp;&nbsp;  0, &nbsp;&nbsp;&nbsp;  0; </font></em></strong></p>
<p><strong><em><font size="3">&nbsp;&nbsp;&nbsp;  1/5,&nbsp;&nbsp;&nbsp;  0, 0,&nbsp;&nbsp;  &nbsp;&nbsp;  0, &nbsp;&nbsp;&nbsp;  1/4,&nbsp;&nbsp;&nbsp;  0, &nbsp;&nbsp;&nbsp;  0; </font></em></strong></p>
<p><strong><em><font size="3">&nbsp;&nbsp;&nbsp;  1/5,&nbsp;&nbsp;&nbsp;  0, 0, &nbsp;&nbsp;&nbsp;  1/3,&nbsp;&nbsp;&nbsp;  0, &nbsp;&nbsp;&nbsp;  1/2,&nbsp;&nbsp;&nbsp;  1; </font></em></strong></p>
<p><strong><em><font size="3">&nbsp;&nbsp;&nbsp;  0,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  0, 0,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;  0, &nbsp;&nbsp;&nbsp;  1/4,&nbsp;&nbsp;&nbsp;  0, &nbsp;&nbsp;&nbsp;  0;</font></em></strong></p>
<p><strong><em><font size="3">&nbsp;&nbsp;&nbsp;  1/5,&nbsp;&nbsp;&nbsp;  0, 0, &nbsp;&nbsp;&nbsp;  0, &nbsp;&nbsp;&nbsp;  0, &nbsp;&nbsp;&nbsp;  0, &nbsp;&nbsp;&nbsp;  0;</font></em></strong></p>
<p><strong><em><font size="3">]</font></em></strong></p>
<p><strong><em><font size="3">所以，P<sup>T</sup>为M的特征根为c的
特征向量。只需求出最大特征根的特征向量，就是网页集对应的最终PageRank值，这可以用迭代方法计算。如何迭代呢？如果
我们给定初始向量P<sup>T1&#8217;</sup>做第一次迭代，就相当于用初始向量乘以上面的矩阵。第二次迭代就相当于用第一
迭代的结果再乘以上面的矩阵&#8230;&#8230;实际上，在随机过程的理论中，上述矩阵被称为&#8220;转移概率矩阵&#8221;。这种离散状态按照离散时间的随机转移过程称为马尔可夫链(Markov
chain)。设转移概率矩阵为P，若存在正整数N，使得P<sub>N</sub>&gt;0(每
一个元素大于0)，这种链被称作正则链，它存在唯一的极限状态概率，并且与初始状态无关。这篇<a href="http://hi.baidu.com/huojiwu/blog/item/ef85ec73057595158601b070.html"><font color="#0000ff">&#8221;Google搜索与Inter网中的数学</font></a><font color="#0000ff" face="Times New Roman">&#8221;</font>文章
里，描述了马氏链与page rank的关系。</font></em></strong></p>
<p><strong><em><font size="3">最后可以看到，从最开始的矩阵A到矩阵M可以
很容易转化得到(将A倒置后将各个数值除以各自的非零要素)。</font></em></strong></p>
<p><strong><em><font size="3">现在考虑有一个页面（比如是页面7），它不含有任何的超链接，即它的前向
链接或者说出度为0，很显然，方阵M的最后一行为全零，这样，特征向量P<sup>T</sup>也
为全零。我们也可以从图论的角度来阐述这个问题。我们可以这样定义一个有向图：图G的顶点集合为V={V1,V2,&#8230;,Vn}，
边的集合为E={E<sub>ij</sub>}。我们把有向图G的每个顶点都给定一个权值P(Vi)，
即为它的PR值。有向边AB的权值定义为A为B贡
献的PageRank，也即网站A链接到网站B的概率。这样，对于一个
顶点，若它的出度大于0，则从它出去的权值和为1（这一点可以从上述的方阵M中
的列可以看出，满足了全概率）。显然，如果图中有一个顶点X的出度是0，那么经过有限次迭代后所有
顶点的PR值都将变为0。这是因为由于X不对外贡献任何PR，
所以整体的PR总和在不断减少，最终减为0。这个被拉里&#8226;佩奇和谢尔盖
&#8226;布林称为<font face="Times New Roman">rank sink</font>。
为了克服这个问题，就有了下面这个公式：<font face="Times New Roman">Rank</font>算
法简化版二：<font face="Times New Roman">R(u)
= </font>（<font face="Times New Roman">1-c</font>）<font face="Times New Roman">+
c</font>R(1)/N(1) + &#8230;&#8230;+cR(v)/N(v)。(v&#8712;Bu)。 &#8230;&#8230;公式二</font></em></strong></p>
<p><strong><em><font size="3">(1-c)实际上为了服从概率分布。这样可以推导出P = (1-c)e +
cMP，即</font></em></strong></p>
<p><strong><em><font size="3">P = [(1-c)ee<sup>T</sup>/n + cM]P (e<sup>T</sup>P=n)。关于用矩阵方法来推导的更详细的文章，可以参考这篇<a href="http://www.rose-hulman.edu/%7Ebryan/googleFinalVersionFixed.pdf"><font face="Times New Roman"><strong> <font color="#0000ff">"The
$25,000,000,000 Eigenvector: The Linear Algebra Behind Google</font>"</strong> </font></a><font face="Times New Roman"><strong> .</strong> </font></font></em></strong></p>
<p><strong><em><font size="3">&nbsp;&nbsp;  现在可以想象一下整个web中
有250亿不止的网页，收敛速度是至关重要的。所以为什么作者拉里&#8226;佩奇<font face="Times New Roman"> </font>（<font face="Times
New Roman">Larry Page </font>）和谢尔盖&#8226;布林<font face="Times New Roman"> (Sergey Brin)</font>要取<font face="Times New Roman">c</font>为<font face="Times New Roman">0.85,</font>在这篇文章<font color="#0000ff" face="Times New Roman"><strong> &#8221;<a href="http://www.ams.org/featurecolumn/archive/pagerank.html"><font color="#0000ff">How Google</font> <font color="#0000ff">Finds Your
Needle in the Web's Haystack</font></a></strong> <font color="#0000ff">&#8221;</font></font>的最后部分讨论到。</font></em></strong></p>
<p><strong><em><font size="3">Pagerank算法除了对搜索结果进行排序外，还可
以应用到其它方面，如估算网络流量，向后链接的预测器，为用户导航等。这篇文章<a href="http://www.mattcutts.com/blog/pagerank-sculpting/"><font color="#0000ff" face="Times New Roman"><strong> PageRank sculptin</strong> g</font></a>.讲述了当前Google的一些改进.</font></em></strong></p>
<p><strong><em><font size="3">&nbsp;&nbsp;&nbsp;  后记，2001年9月，PageRank被
授予美国专利，专利被正式颁发给斯坦福大学，佩奇作为发明人列于文件中。最后要说的一点，分析PR算法，用到了离散数学，线性
代数，概率论，数值计算甚至随机过程，所以看来数学确实很好很强大需要认真学习啊。</font></em></strong></p>
<p><br><strong><em></em></strong></p>
<p><strong><em><font size="3">from:</font></em></strong></p>
<p><strong><em><font size="3"><a  href="http://hi.baidu.com/alphahunters/blog/item/e0e8a92d1b2820321f3089a0.html">http://hi.baidu.com/alphahunters/blog/item/e0e8a92d1b2820321f3089a0.html <br></a></font></em></strong></p>
<p><strong><em><font size="3"><a  href="http://blog.csdn.net/boyplayee/archive/2009/09/13/4548930.aspx">http://blog.csdn.net/boyplayee/archive/2009/09/13/4548930.aspx</a>
<br></font></em></strong></p>
<strong><em>	</em></strong><br><img src ="http://www.cppblog.com/beautykingdom/aggbug/111678.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2010-04-05 17:15 <a href="http://www.cppblog.com/beautykingdom/archive/2010/04/05/111678.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hash 算法及其应用</title><link>http://www.cppblog.com/beautykingdom/archive/2010/03/09/109319.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Tue, 09 Mar 2010 13:02:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2010/03/09/109319.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/109319.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2010/03/09/109319.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/109319.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/109319.html</trackback:ping><description><![CDATA[<font color="#555555">什么是 Hash <br>Hash 的重要特性 <br>Hash 函数的实现 <br>主要的 Hash 算法 <br>Hash 算法的安全问题 <br>Hash 算法的应用 <br>结 论 <br>--------------- <br></font><br><font color="#555555">Hash，
一般翻译做&#8220;散列&#8221;，也有直接音译为"哈希"的，就是把任意长度的输入（又叫做预映射，
pre-image），通过散列算法，变换成固定长度的输出，该输出就是散列值。这种转换是一种压缩映射，也就是，散列值的空间通常远小于输入的空间，不
同的输入可能会散列成相同的输出，而不可能从散列值来唯一的确定输入值。 </font>
<p><font color="#555555">数学表述为：h = H(M) ，其中H( )--单向散列函数，M--任意长度明文，h--固定长度散列值。 </font></p>
<p><font color="#555555">在信息安全领域中应用的</font><a name="0"></a>
<p><font color="#555555">第
一当然是单向性(one-way)，从预映射，能够简单迅速的得到散列值，而在计算上不可能构造一个预映射，使其散列结果等于某个特定的散列值，即构造相
应的M=H-1(h)不可行。这样，散列值就能在统计上唯一的表征输入值，因此，密码学上的 Hash 又被称为"消息摘要(message
digest)"，就是要求能方便的将"消息"进行"摘要"，但在"摘要"中无法得到比"摘要"本身更多的关于"消息"的信息。 </font></p>
<p><font color="#555555">第
二是抗冲突性(collision-resistant)，即在统计上无法产生2个散列值相同的预映射。给定M，计算上无法找到M
，满足H(M)=H(M ) ，此谓弱抗冲突性；计算上也难以寻找一对任意的M和M ，使满足H(M)=H(M )
，此谓强抗冲突性。要求"强抗冲突性"主要是为了防范所谓"生日攻击(birthday
attack)"，在一个10人的团体中，你能找到和你生日相同的人的概率是2.4%，而在同一团体中，有2人生日相同的概率是11.7%。类似的，当预
映射的空间很大的情况下，算法必须有足够的强度来保证不能轻易找到"相同生日"的人。 </font></p>
<p><font color="#555555">第
三是映射分布均匀性和差分分布均匀性，散列结果中，为 0 的 bit 和为 1 的 bit ，其总数应该大致相等；输入中一个 bit
的变化，散列结果中将有一半以上的 bit 改变，这又叫做"雪崩效应(avalanche effect)"；要实现使散列结果中出现 1bit
的变化，则输入中至少有一半以上的 bit 必须发生变化。其实质是必须使输入中每一个 bit 的信息，尽量均匀的反映到输出的每一个 bit
上去；输出中的每一个 bit，都是输入中尽可能多 bit 的信息一起作用的结果。 </font></p>
<p><font color="#555555">Damgard
和 Merkle 定义了所谓&#8220;压缩函数(compression
function)&#8221;，就是将一个固定长度输入，变换成较短的固定长度的输出，这对密码学实践上 Hash
函数的设计产生了很大的影响。Hash函数就是被设计为基于通过特定压缩函数的不断重复&#8220;压缩&#8221;输入的分组和前一次压缩处理的结果的过程，直到整个消息都
被压缩完毕，最后的输出作为整个消息的散列值。尽管还缺乏严格的证明，但绝大多数业界的研究者都同意，如果压缩函数是安全的，那么以上述形式散列任意长度
的消息也将是安全的。这就是所谓 Damgard/Merkle 结构： </font></p>
<p><font color="#555555">在
下图中，任意长度的消息被分拆成符合压缩函数输入要求的分组，最后一个分组可能需要在末尾添上特定的填充字节，这些分组将被顺序处理，除了第一个消息分组
将与散列初始化值一起作为压缩函数的输入外，当前分组将和前一个分组的压缩函数输出一起被作为这一次压缩的输入，而其输出又将被作为下一个分组压缩函数输
入的一部分，直到最后一个压缩函数的输出，将被作为整个消息散列的结果。 </font></p>
<p><font color="#555555">MD5 和 SHA1 可以说是目前应用最广泛的<strong style="color: black; background-color: #ffff66;">Hash算法</strong>，而它们都是以 MD4 为基础设计的。 </font></p>
<p><font color="#555555">1) MD4 <br>MD4(RFC
1320)是 MIT 的 Ronald L. Rivest 在 1990 年设计的，MD 是 Message Digest
的缩写。它适用在32位字长的处理器上用高速软件实现--它是基于 32 位操作数的位操作来实现的。它的安全性不像RSA那样基于数学假设，尽管
Den Boer、Bosselaers 和 Dobbertin 很快就用分析和差分成功的攻击了它3轮变换中的 2
轮，证明了它并不像期望的那样安全，但它的整个算法并没有真正被破解过，Rivest 也很快进行了改进。 </font></p>
<p><font color="#555555">下面是一些MD4散列结果的例子： </font></p>
<p><font color="#555555">MD4 ("") = 31d6cfe0d16ae931b73c59d7e0c089c0 <br>MD4 ("a") = bde52cb31de33e46245e05fbdbd6fb24 <br>MD4 ("abc") = a448017aaf21d8525fc10ae87aa6729d <br>MD4 ("message digest") = d9130a8164549fe818874806e1c7014b <br>MD4 ("abcdefghijklmnopqrstuvwxyz") = d79e1c308aa5bbcdeea8ed63df412da9 <br>MD4 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") = 043f8582f241db351ce627e153e7f0e4 <br>MD4 ("12345678901234567890123456789012345678901234567890123456789012345678901234567890") = e33b4ddc9c38f2199c3e7b164fcc0536 <br></font><br><font color="#555555">2) MD5 <br>MD5(RFC 1321)是 Rivest 于1991年对MD4的改进版本。它对输入仍以512位分组，其输出是4个32位字的级联，与 MD4 相同。它较MD4所做的改进是： </font></p>
<p><font color="#555555">1) 加入了第四轮 <br>2) 每一步都有唯一的加法常数； <br>3) 第二轮中的G函数从((X ∧ Y) ∨ (X ∧ Z) ∨ (Y ∧ Z)) 变为 ((X ∧ Z) ∨ (Y ∧ ～Z))以减小其对称性； <br>4) 每一步都加入了前一步的结果，以加快"雪崩效应"； <br>5) 改变了第2轮和第3轮中访问输入子分组的顺序，减小了形式的相似程度； <br>6) 近似优化了每轮的循环左移位移量，以期加快"雪崩效应"，各轮的循环左移都不同。 <br>尽管MD5比MD4来得复杂，并且速度较之要慢一点，但更安全，在抗分析和抗差分方面表现更好。 </font></p>
<p><font color="#555555">消
息首先被拆成若干个512位的分组，其中最后512位一个分组是&#8220;消息尾+填充字节(100&#8230;0)+64
位消息长度&#8221;，以确保对于不同长度的消息，该分组不相同。64位消息长度的限制导致了MD5安全的输入长度必须小于264bit，因为大于64位的长度信
息将被忽略。而4个32位寄存器字初始化为A=0x01234567，B=0x89abcdef，C=0xfedcba98，D=0x76543210，
它们将始终参与运算并形成最终的散列结果。 </font></p>
<p><font color="#555555">接着各个512位消息分组以16个32位字的形式进入算法的主循环，512位消息分组的个数据决定了循环的次数。主循环有4轮，每轮分别用到了非线性函数 </font></p>
<p><font color="#555555">F(X, Y, Z) = (X ∧ Y) ∨ (～X ∧ Z) <br>G(X, Y, Z) = (X ∧ Z) ∨ (Y ∧ ～Z) <br>H(X, Y, Z) =X &#8853; Y &#8853; Z <br>I(X, Y, Z) = X &#8853; (Y ∨ ～Z) <br>这
4轮变换是对进入主循环的512位消息分组的16个32位字分别进行如下操作：将A、B、C、D的副本a、b、c、d中的3个经F、G、H、I运算后的结
果与第4个相加，再加上32位字和一个32位字的加法常数，并将所得之值循环左移若干位，最后将所得结果加上a、b、c、d之一，并回送至ABCD，由此
完成一次循环。 </font></p>
<p><font color="#555555">所用的加法常数由这样一张表T[i]来定义，其中i为1&#8230;64，T[i]是i的正弦绝对值之4294967296次方的整数部分，这样做是为了通过正弦函数和幂函数来进一步消除变换中的线性性。 </font></p>
<p><font color="#555555">当所有512位分组都运算完毕后，ABCD的级联将被输出为MD5散列的结果。下面是一些MD5散列结果的例子： </font></p>
<p><font color="#555555">MD5 ("") = d41d8cd98f00b204e9800998ecf8427e <br>MD5 ("a") = 0cc175b9c0f1b6a831c399e269772661 <br>MD5 ("abc") = 900150983cd24fb0d6963f7d28e17f72 <br>MD5 ("message digest") = f96b697d7cb7938d525a2f31aaf161d0 <br>MD5 ("abcdefghijklmnopqrstuvwxyz") = c3fcd3d76192e4007dfb496cca67e13b <br>MD5 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") = d174ab98d277d9f5a5611c2c9f419d9f <br>MD5 ("12345678901234567890123456789012345678901234567890123456789012345678901234567890") = 57edf4a22be3c955ac49da2e2107b67a <br>参考相应RFC文档可以得到MD4、MD5算法的详细描述和算法的C源代码。 </font></p>
<p><font color="#555555">3) SHA1 及其他 <br>SHA1
是由NIST
NSA设计为同DSA一起使用的，访问http://www.itl.nist.gov/fipspubs可以得到它的详细规范
--[/url]"FIPS PUB 180-1 SECURE HASH
STANDARD"。它对长度小于264的输入，产生长度为160bit的散列值，因此抗穷举(brute-force)性更好。SHA-1
设计时基于和MD4相同原理,并且模仿了该算法。因为它将产生160bit的散列值，因此它有5个参与运算的32位寄存器字，消息分组和填充方式与MD5
相同，主循环也同样是4轮，但每轮进行20次操作，非线性运算、移位和加法运算也与MD5类似，但非线性函数、加法常数和循环左移操作的设计有一些区别，
可以参考上面提到的规范来了解这些细节。下面是一些SHA1散列结果的例子： </font></p>
<p><font color="#555555">SHA1 ("abc") = a9993e36 4706816a ba3e2571 7850c26c 9cd0d89d <br>SHA1 ("abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq") = 84983e44 1c3bd26e baae4aa1 f95129e5 e54670f1 <br>其他一些知名的<strong style="color: black; background-color: #ffff66;">Hash算法</strong>还有MD2、N-Hash、RIPE-MD、HAVAL等等。上面提到的这些都属于"纯"<strong style="color: black; background-color: #ffff66;">Hash算法</strong>。还有另2类<strong style="color: black; background-color: #ffff66;">Hash算法</strong>，
一类就是基于对称分组算法的单向散列算法，典型的例子是基于DES的所谓Davies-Meyer算法，另外还有经IDEA改进的Davies-
Meyer算法，它们两者目前都被认为是安全的算法。另一类是基于模运算/离散对数的，也就是基于公开密钥算法的，但因为其运算开销太大，而缺乏很好的应
用前景。 </font></p>
<p><font color="#555555">没有通过分析和差分攻击考验的算法，大多都已经夭折在实验室里了，因此，如果目前流行的<strong style="color: black; background-color: #ffff66;">Hash算法</strong>能
完全符合密码学意义上的单向性和抗冲突性，就保证了只有穷举，才是破坏Hash运算安全特性的唯一方法。为了对抗弱抗冲突性，我们可能要穷举个数和散列值
空间长度一样大的输入，即尝试2^128或2^160个不同的输入，目前一台高档个人电脑可能需要10^25年才能完成这一艰巨的工作，即使是最高端的并
行系统，这也不是在几千年里的干得完的事。而因为"生日攻击"有效的降低了需要穷举的空间，将其降低为大约1.2*2^64或1.2*2^80，所以，强
抗冲突性是决定<strong style="color: black; background-color: #ffff66;">Hash算法</strong>安全性的关键。 </font></p>
<p><font color="#555555">在NIST新的 Advanced Encryption Standard (AES)中，使用了长度为128、192、256bit 的密钥，因此相应的设计了 SHA256、SHA384、SHA512，它们将提供更好的安全性。 </font></p>
<p><font color="#555555"><strong style="color: black; background-color: #ffff66;">Hash算法</strong>在信息安全方面的应用主要体现在以下的3个方面： </font></p>
<p><font color="#555555">1) 文件校验 <br>我们比较熟悉的校验算法有奇偶校验和CRC校验，这2种校验并没有抗数据篡改的能力，它们一定程度上能检测并纠正数据传输中的信道误码，但却不能防止对数据的恶意破坏。 </font></p>
<p><font color="#555555">MD5 <strong style="color: black; background-color: #ffff66;">Hash算法</strong>的"数字指纹"特性，使它成为目前应用最广泛的一种文件完整性校验和(Checksum)算法，不少Unix系统有提供计算md5 checksum的命令。它常被用在下面的2种情况下： </font></p>
<p><font color="#555555">第
一是文件传送后的校验，将得到的目标文件计算 md5 checksum，与源文件的md5 checksum 比对，由两者 md5
checksum
的一致性，可以从统计上保证2个文件的每一个码元也是完全相同的。这可以检验文件传输过程中是否出现错误，更重要的是可以保证文件在传输过程中未被恶意篡
改。一个很典型的应用是ftp服务，用户可以用来保证多次断点续传，特别是从镜像站点下载的文件的正确性。 </font></p>
<p><font color="#555555">更
出色的解决方法是所谓的代码签名，文件的提供者在提供文件的同时，提供对文件Hash值用自己的代码签名密钥进行数字签名的值，及自己的代码签名证书。文
件的接受者不仅能验证文件的完整性，还可以依据自己对证书签发者和证书拥有者的信任程度，决定是否接受该文件。浏览器在下载运行插件和java小程序时，
使用的就是这样的模式。 </font></p>
<p><font color="#555555">第二是用作保存二进制文件系统的数字指纹，以便检
测文件系统是否未经允许的被修改。不少系统管理/系统安全软件都提供这一文件系统完整性评估的功能，在系统初始安装完毕后，建立对文件系统的基础校验和数
据库，因为散列校验和的长度很小，它们可以方便的被存放在容量很小的存储介质上。此后，可以定期或根据需要，再次计算文件系统的校验和，一旦发现与原来保
存的值有不匹配，说明该文件已经被非法修改，或者是被病毒感染，或者被木马程序替代。TripWire就提供了一个此类应用的典型例子。 </font></p>
<p><font color="#555555">更
完美的方法是使用"MAC"。"MAC" 是一个与Hash密切相关的名词，即信息鉴权码(Message Authority
Code)。它是与密钥相关的Hash值，必须拥有该密钥才能检验该Hash值。文件系统的数字指纹也许会被保存在不可信任的介质上，只对拥有该密钥者提
供可鉴别性。并且在文件的数字指纹有可能需要被修改的情况下，只有密钥的拥有者可以计算出新的散列值，而企图破坏文件完整性者却不能得逞。 </font></p>
<p><font color="#555555">2) 数字签名 <br>Hash 算法也是现代密码体系中的一个重要组成部分。由于非对称算法的运算速度较慢，所以在数字签名协议中，单向散列函数扮演了一个重要的角色。 </font></p>
<p><font color="#555555">在这种签名协议中，双方必须事先协商好双方都支持的Hash函数和签名算法。 </font></p>
<p><font color="#555555">签名方先对该数据文件进行计算其散列值，然后再对很短的散列值结果--如Md5是16个字节，SHA1是20字节，用非对称算法进行数字签名操作。对方在验证签名时，也是先对该数据文件进行计算其散列值，然后再用非对称算法验证数字签名。 </font></p>
<p><font color="#555555">对 Hash 值，又称"数字摘要"进行数字签名，在统计上可以认为与对文件本身进行数字签名是等效的。而且这样的协议还有其他的优点： </font></p>
<p><font color="#555555">首先，数据文件本身可以同它的散列值分开保存，签名验证也可以脱离数据文件本身的存在而进行。 </font></p>
<p><font color="#555555">再
者，有些情况下签名密钥可能与解密密钥是同一个，也就是说，如果对一个数据文件签名，与对其进行非对称的解密操作是相同的操作，这是相当危险的，恶意的破
坏者可能将一个试图骗你将其解密的文件，充当一个要求你签名的文件发送给你。因此，在对任何数据文件进行数字签名时，只有对其Hash值进行签名才是安全
的。 </font></p>
<p><font color="#555555">3) 鉴权协议 <br>如下的鉴权协议又被称作"挑战--认证模式：在传输信道是可被侦听，但不可被篡改的情况下，这是一种简单而安全的方法。 </font></p>
<p><font color="#555555">需
要鉴权的一方，向将被鉴权的一方发送随机串（&#8220;挑战&#8221;），被鉴权方将该随机串和自己的鉴权口令字一起进行 Hash
运算后，返还鉴权方，鉴权方将收到的Hash值与在己端用该随机串和对方的鉴权口令字进行 Hash
运算的结果相比较（&#8220;认证&#8221;），如相同，则可在统计上认为对方拥有该口令字，即通过鉴权。 </font></p>
<p><font color="#555555">POP3协议中就有这一应用的典型例子： </font></p>
<p><font color="#555555">S: +OK POP3 server ready &lt;1896.697170952@dbc.mtview.ca.us&gt; <br>C: APOP mrose c4c9334bac560ecc979e58001b3e22fb <br>S: +OK maildrop has 1 message (369 octets) <br>在
上面的一段POP3协议会话中，双方都共享的对称密钥（鉴权口令字）是tanstaaf，服务器发出的挑战
是&lt;1896.697170952@dbc.mtview.ca.us&gt;，客户端对挑战的应答是
MD5("&lt;1896.697170952@dbc.mtview.ca.us&gt;tanstaaf") =
c4c9334bac560ecc979e58001b3e22fb，这个正确的应答使其通过了认证。 </font></p>
<p><font color="#555555">散列算法长期以来一直在计算机科学中大量应用，随着现代密码学的发展，单向散列函数已经成为信息安全领域中一个重要的结构模块，我们有理由深入研究其设计理论和应用方法。</font></p>
from:<br>http://www.coood.com/postfile/2007-1-4/20071495110.shtml
<br><br><img src ="http://www.cppblog.com/beautykingdom/aggbug/109319.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2010-03-09 21:02 <a href="http://www.cppblog.com/beautykingdom/archive/2010/03/09/109319.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Knuth–Morris–Pratt algorithm</title><link>http://www.cppblog.com/beautykingdom/archive/2010/03/08/109232.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Mon, 08 Mar 2010 14:51:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2010/03/08/109232.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/109232.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2010/03/08/109232.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/109232.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/109232.html</trackback:ping><description><![CDATA[<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;The <strong>Knuth&#8211;Morris&#8211;Pratt <a title="String searching algorithm" href="http://en.wikipedia.org/wiki/String_searching_algorithm"><font color="#002bb8">string searching algorithm</font></a></strong> (or <strong>KMP algorithm</strong>) searches for occurrences of a "word" <code><font style="background-color: #f9f9f9;">W</font></code> within a main "text string" <code><font style="background-color: #f9f9f9;">S</font></code> by employing the observation that when a mismatch occurs, the word itself embodies sufficient information to determine where the next match could begin, thus bypassing re-examination of previously matched characters.</p>
<p>&nbsp;&nbsp;&nbsp; The <a title="Algorithm" href="http://en.wikipedia.org/wiki/Algorithm"><font color="#002bb8">algorithm</font></a> was conceived by <a title="Donald knuth" href="http://en.wikipedia.org/wiki/Donald_Knuth"><font color="#002bb8">Donald Knuth</font></a> and <a title="Vaughan pratt" href="http://en.wikipedia.org/wiki/Vaughan_Pratt"><font color="#002bb8">Vaughan Pratt</font></a> and independently by <a class="mw-redirect" title="J. h. morris" href="http://en.wikipedia.org/wiki/J._H._Morris"><font color="#002bb8">J. H. Morris</font></a> in 1977, but the three published it jointly.</p>
<p>In this article, we will be using <a title="Array data type" href="http://en.wikipedia.org/wiki/Array_data_type"><font color="#002bb8">zero-based arrays</font></a> for our strings; thus the <code><font style="background-color: #f9f9f9;">'C'</font></code> in <code><font style="background-color: #f9f9f9;">W</font></code> (shown <a href="http://en.wikipedia.org/wiki/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm#Worked_example_of_the_search_algorithm"><font color="#002bb8">below</font></a>) will be denoted <code><font style="background-color: #f9f9f9;">W[2]</font></code>.</p>
<span id="Worked_example_of_the_search_algorithm" class="mw-headline">Worked example of the search algorithm</span>
<p>To illustrate the algorithm's details, we work through a (relatively artificial) run of the algorithm. At any given time, the algorithm is in a state determined by two integers, <code><font style="background-color: #f9f9f9;">m</font></code> and <code><font style="background-color: #f9f9f9;">i</font></code>, which denote respectively the position within <code><font style="background-color: #f9f9f9;">S</font></code> which is the beginning of a prospective <em>match</em> for <code><font style="background-color: #f9f9f9;">W</font></code>, and the <em>index</em> in <code><font style="background-color: #f9f9f9;">W</font></code> denoting the character currently under consideration. This is depicted, at the start of the run, like</p>
<pre>             1         2
m: 01234567890123456789012
S: ABC ABCDAB ABCDABCDABDE
W: ABCDABD
i: 0123456
</pre>
<p>We proceed by comparing successive characters of <code><font style="background-color: #f9f9f9;">W</font></code> to "parallel" characters of <code><font style="background-color: #f9f9f9;">S</font></code>, moving from one to the next if they match. However, in the fourth step, we get <code><font style="background-color: #f9f9f9;">S[3]</font></code> is a space and <code><font style="background-color: #f9f9f9;">W[3] = 'D'</font></code>, a mismatch. Rather than beginning to search again at <code><font style="background-color: #f9f9f9;">S[1]</font></code>, we note that no <code><font style="background-color: #f9f9f9;">'A'</font></code> occurs between positions 0 and 3 in <code><font style="background-color: #f9f9f9;">S</font></code> except at 0; hence, having checked all those characters previously, we know there is no chance of finding the beginning of a match if we check them again. Therefore we move on to the next character, setting <code><font style="background-color: #f9f9f9;">m = 4</font></code> and <code><font style="background-color: #f9f9f9;">i = 0</font></code>.</p>
<pre>             1         2
m: 01234567890123456789012
S: ABC ABCDAB ABCDABCDABDE
W:     ABCDABD
i:     0123456
</pre>
<p>We quickly obtain a nearly complete match <code><font style="background-color: #f9f9f9;">"ABCDAB"</font></code> when, at <code><font style="background-color: #f9f9f9;">W[6]</font></code> (<code><font style="background-color: #f9f9f9;">S[10]</font></code>), we again have a discrepancy. However, just prior to the end of the current partial match, we passed an <code><font style="background-color: #f9f9f9;">"AB"</font></code> which could be the beginning of a new match, so we must take this into consideration. As we already know that these characters match the two characters prior to the current position, we need not check them again; we simply reset <code><font style="background-color: #f9f9f9;">m = 8</font></code>, <code><font style="background-color: #f9f9f9;">i = 2</font></code> and continue matching the current character. Thus, not only do we omit previously matched characters of <code><font style="background-color: #f9f9f9;">S</font></code>, but also previously matched characters of <code><font style="background-color: #f9f9f9;">W</font></code>.</p>
<pre>             1         2
m: 01234567890123456789012
S: ABC ABCDAB ABCDABCDABDE
W:         ABCDABD
i:         0123456
</pre>
<p>This search fails immediately, however, as the pattern still does not contain a space, so as in the first trial, we return to the beginning of <code><font style="background-color: #f9f9f9;">W</font></code> and begin searching at the next character of <code><font style="background-color: #f9f9f9;">S</font></code>: <code><font style="background-color: #f9f9f9;">m = 11</font></code>, reset <code><font style="background-color: #f9f9f9;">i = 0</font></code>.</p>
<pre>             1         2
m: 01234567890123456789012
S: ABC ABCDAB ABCDABCDABDE
W:            ABCDABD
i:            0123456
</pre>
<p>Once again we immediately hit upon a match <code><font style="background-color: #f9f9f9;">"ABCDAB"</font></code> but the next character, <code><font style="background-color: #f9f9f9;">'C'</font></code>, does not match the final character <code><font style="background-color: #f9f9f9;">'D'</font></code> of the word <code><font style="background-color: #f9f9f9;">W</font></code>. Reasoning as before, we set <code><font style="background-color: #f9f9f9;">m = 15</font></code>, to start at the two-character string <code><font style="background-color: #f9f9f9;">"AB"</font></code> leading up to the current position, set <code><font style="background-color: #f9f9f9;">i = 2</font></code>, and continue matching from the current position.</p>
<pre>             1         2
m: 01234567890123456789012
S: ABC ABCDAB ABCDABCDABDE
W:                ABCDABD
i:                0123456
</pre>
<p>This time we are able to complete the match, whose first character is <code><font style="background-color: #f9f9f9;">S[15]</font></code>.</p>
<br><span id="Description_of_and_pseudocode_for_the_search_algorithm" class="mw-headline">Description of and pseudocode for the search algorithm</span>
<p>The above example contains all the elements of the algorithm. For the moment, we assume the existence of a "partial match" table <code><font style="background-color: #f9f9f9;">T</font></code>, described <a href="http://en.wikipedia.org/wiki/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm#.22partial_match.22_table_.28also_known_as_.22failure_function.22.29"><font color="#002bb8">below</font></a>, which indicates where we need to look for the start of a new match in the event that the current one ends in a mismatch. The entries of <code><font style="background-color: #f9f9f9;">T</font></code> are constructed so that if we have a match starting at <code><font style="background-color: #f9f9f9;">S[m]</font></code> that fails when comparing <code><font style="background-color: #f9f9f9;">S[m + i]</font></code> to <code><font style="background-color: #f9f9f9;">W[i]</font></code>, then the next possible match will start at index <code><font style="background-color: #f9f9f9;">m + i - T[i]</font></code> in <code><font style="background-color: #f9f9f9;">S</font></code> (that is, <code><font style="background-color: #f9f9f9;">T[i]</font></code> is the amount of "backtracking" we need to do after a mismatch). This has two implications: first, <code><font style="background-color: #f9f9f9;">T[0] = -1</font></code>, which indicates that if <code><font style="background-color: #f9f9f9;">W[0]</font></code> is a mismatch, we cannot backtrack and must simply check the next character; and second, although the next possible match will <em>begin</em> at index <code><font style="background-color: #f9f9f9;">m + i - T[i]</font></code>, as in the example above, we need not actually check any of the <code><font style="background-color: #f9f9f9;">T[i]</font></code> characters after that, so that we continue searching from <code><font style="background-color: #f9f9f9;">W[T[i]]</font></code>. The following is a sample <a title="Pseudocode" href="http://en.wikipedia.org/wiki/Pseudocode"><font color="#002bb8">pseudocode</font></a> implementation of the KMP search algorithm.</p>
<pre><strong>algorithm</strong> <em>kmp_search</em>:
<strong>input</strong>:
an array of characters, S (the text to be searched)
an array of characters, W (the word sought)
<strong>output</strong>:
an integer (the <a title="Array data type" href="http://en.wikipedia.org/wiki/Array_data_type"><font color="#002bb8">zero-based</font></a> position in S at which W is found)
<strong>define variables</strong>:
an integer, m &#8592; 0 (the beginning of the current match in S)
an integer, i &#8592; 0 (the position of the current character in W)
an array of integers, T (the table, computed elsewhere)
<strong>while</strong> m + i is less than the length of S, <br><strong>do</strong><span style="font-weight: bold;"><br>   </span><strong> if</strong> W[i] = S[m + i],
<strong>       let</strong> i &#8592; i + 1
<strong>       if</strong> i equals the length of W,
<strong>       return</strong> m
<strong>    otherwise</strong>{<br>       <strong>&nbsp;let</strong> m &#8592; m + i - T[i],
<strong>       // this if else statement is utilized to reposition i<br>       if</strong> T[i] is greater than -1,
<strong>          let</strong> i &#8592; T[i]
<strong>       else</strong>
<strong>          let</strong> i &#8592; 0
}<br>done (if we reach here, we have searched all of S unsuccessfully)
<strong>return</strong> the length of S, that is m+i. </pre>
<span class="editsection">[<a title="Edit section: efficiency of the search algorithm" href="http://en.wikipedia.org/w/index.php?title=Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm&amp;action=edit&amp;section=4"><font color="#002bb8">edit</font></a>]</span> <span id="Efficiency_of_the_search_algorithm" class="mw-headline">Efficiency of the search algorithm</span>
<p>Assuming the prior existence of the table <code><font style="background-color: #f9f9f9;">T</font></code>, the search portion of the Knuth&#8211;Morris&#8211;Pratt algorithm has <a title="Computational complexity theory" href="http://en.wikipedia.org/wiki/Computational_complexity_theory"><font color="#002bb8">complexity</font></a> <code><font style="background-color: #f9f9f9;">O(k)</font></code>, where <code><font style="background-color: #f9f9f9;">k</font></code> is the length of <code><font style="background-color: #f9f9f9;">S</font></code> and the <code><font style="background-color: #f9f9f9;">O</font></code> is <a class="mw-redirect" title="Big-O notation" href="http://en.wikipedia.org/wiki/Big-O_notation"><font color="#002bb8">big-O notation</font></a>. As except for the fixed overhead incurred in entering and exiting the function, all the computations are performed in the <code><strong><font style="background-color: #f9f9f9;">while</font></strong></code> loop, we will calculate a bound on the number of iterations of this loop; in order to do this we first make a key observation about the nature of <code><font style="background-color: #f9f9f9;">T</font></code>. By definition it is constructed so that if a match which had begun at <code><font style="background-color: #f9f9f9;">S[m]</font></code> fails while comparing <code><font style="background-color: #f9f9f9;">S[m + i]</font></code> to <code><font style="background-color: #f9f9f9;">W[i]</font></code>, then the next possible match must begin at <code><font style="background-color: #f9f9f9;">S[m + (i - T[i])]</font></code>. In particular the next possible match must occur at a higher index than <code><font style="background-color: #f9f9f9;">m</font></code>, so that <code><font style="background-color: #f9f9f9;">T[i] &lt; i</font></code>.</p>
<p>Using this fact, we will show that the loop can execute at most <code><font style="background-color: #f9f9f9;">2k</font></code> times. For in each iteration, it executes one of the two branches in the loop. The first branch invariably increases <code><font style="background-color: #f9f9f9;">i</font></code> and does not change <code><font style="background-color: #f9f9f9;">m</font></code>, so that the index <code><font style="background-color: #f9f9f9;">m + i</font></code> of the currently scrutinized character of <code><font style="background-color: #f9f9f9;">S</font></code> is increased. The second branch adds <code><font style="background-color: #f9f9f9;">i - T[i]</font></code> to <code><font style="background-color: #f9f9f9;">m</font></code>, and as we have seen, this is always a positive number. Thus the location <code><font style="background-color: #f9f9f9;">m</font></code> of the beginning of the current potential match is increased. Now, the loop ends if <code><font style="background-color: #f9f9f9;">m + i = k</font></code>; therefore each branch of the loop can be reached at most <code><font style="background-color: #f9f9f9;">k</font></code> times, since they respectively increase either <code><font style="background-color: #f9f9f9;">m + i</font></code> or <code><font style="background-color: #f9f9f9;">m</font></code>, and <code><font style="background-color: #f9f9f9;">m &#8804; m + i</font></code>: if <code><font style="background-color: #f9f9f9;">m = k</font></code>, then certainly <code><font style="background-color: #f9f9f9;">m + i &#8805; k</font></code>, so that since it increases by unit increments at most, we must have had <code><font style="background-color: #f9f9f9;">m + i = k</font></code> at some point in the past, and therefore either way we would be done.</p>
<p>Thus the loop executes at most <code><font style="background-color: #f9f9f9;">2k</font></code> times, showing that the time complexity of the search algorithm is <code><font style="background-color: #f9f9f9;">O(k)</font></code>.</p>
<br><span id=".22Partial_match.22_table_.28also_known_as_.22failure_function.22.29" class="mw-headline">"Partial match" table (also known as "failure function")</span>
<p>The goal of the table is to allow the algorithm not to match any character of <code><font style="background-color: #f9f9f9;">S</font></code> more than once. The key observation about the nature of a linear search that allows this to happen is that in having checked some segment of the main string against an <em>initial segment</em> of the pattern, we know exactly at which places a new potential match which could continue to the current position could begin prior to the current position. In other words, we "pre-search" the pattern itself and compile a list of all possible fallback positions that bypass a maximum of hopeless characters while not sacrificing any potential matches in doing so.</p>
<p>We want to be able to look up, for each position in <code><font style="background-color: #f9f9f9;">W</font></code>, the length of the longest possible initial segment of <code><font style="background-color: #f9f9f9;">W</font></code> leading up to (but not including) that position, other than the full segment starting at <code><font style="background-color: #f9f9f9;">W[0]</font></code> that just failed to match; this is how far we have to backtrack in finding the next match. Hence <code><font style="background-color: #f9f9f9;">T[i]</font></code> is exactly the length of the longest possible <em>proper</em> initial segment of <code><font style="background-color: #f9f9f9;">W</font></code> which is also a segment of the substring ending at <code><font style="background-color: #f9f9f9;">W[i - 1]</font></code>. We use the convention that the empty string has length 0. Since a mismatch at the very start of the pattern is a special case (there is no possibility of backtracking), we set <code><font style="background-color: #f9f9f9;">T[0] = -1</font></code>, as discussed <a href="http://en.wikipedia.org/wiki/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm#Description_of_and_pseudocode_for_the_search_algorithm"><font color="#002bb8">above</font></a>.</p>
<br><span id="Worked_example_of_the_table-building_algorithm" class="mw-headline">Worked example of the table-building algorithm</span>
<p>We consider the example of <code><font style="background-color: #f9f9f9;">W = "ABCDABD"</font></code> first. We will see that it follows much the same pattern as the main search, and is efficient for similar reasons. We set <code><font style="background-color: #f9f9f9;">T[0] = -1</font></code>. To find <code><font style="background-color: #f9f9f9;">T[1]</font></code>, we must discover a <a title="Substring" href="http://en.wikipedia.org/wiki/Substring"><font color="#002bb8">proper suffix</font></a> of <code><font style="background-color: #f9f9f9;">"A"</font></code> which is also a prefix of <code><font style="background-color: #f9f9f9;">W</font></code>. But there are no proper suffixes of <code><font style="background-color: #f9f9f9;">"A"</font></code>, so we set <code><font style="background-color: #f9f9f9;">T[1] = 0</font></code>. Likewise, <code><font style="background-color: #f9f9f9;">T[2] = 0</font></code>.</p>
<p>Continuing to <code><font style="background-color: #f9f9f9;">T[3]</font></code>, we note that there is a shortcut to checking <em>all</em> suffixes: let us say that we discovered a <a title="Substring" href="http://en.wikipedia.org/wiki/Substring"><font color="#002bb8">proper suffix</font></a> which is a <a title="Substring" href="http://en.wikipedia.org/wiki/Substring"><font color="#002bb8">proper prefix</font></a> and ending at <code><font style="background-color: #f9f9f9;">W[2]</font></code> with length 2 (the maximum possible); then its first character is a proper prefix of a proper prefix of <code><font style="background-color: #f9f9f9;">W</font></code>, hence a proper prefix itself, and it ends at <code><font style="background-color: #f9f9f9;">W[1]</font></code>, which we already determined cannot occur in case T[2]. Hence at each stage, the shortcut rule is that one needs to consider checking suffixes of a given size m&gt;1 only if a valid suffix of size m-1 was found at the previous stage (e.g. T[x]=m-1).</p>
<p>Therefore we need not even concern ourselves with substrings having length 2, and as in the previous case the sole one with length 1 fails, so <code><font style="background-color: #f9f9f9;">T[3] = 0</font></code>.</p>
<p>We pass to the subsequent <code><font style="background-color: #f9f9f9;">W[4]</font></code>, <code><font style="background-color: #f9f9f9;">'A'</font></code>. The same logic shows that the longest substring we need consider has length 1, and although in this case <code><font style="background-color: #f9f9f9;">'A'</font></code> <em>does</em> work, recall that we are looking for segments ending <em>before</em> the current character; hence <code><font style="background-color: #f9f9f9;">T[4] = 0</font></code> as well.</p>
<p>Considering now the next character, <code><font style="background-color: #f9f9f9;">W[5]</font></code>, which is <code><font style="background-color: #f9f9f9;">'B'</font></code>, we exercise the following logic: if we were to find a subpattern beginning before the previous character <code><font style="background-color: #f9f9f9;">W[4]</font></code>, yet continuing to the current one <code><font style="background-color: #f9f9f9;">W[5]</font></code>, then in particular it would itself have a proper initial segment ending at <code><font style="background-color: #f9f9f9;">W[4]</font></code> yet beginning before it, which contradicts the fact that we already found that <code><font style="background-color: #f9f9f9;">'A'</font></code> itself is the earliest occurrence of a proper segment ending at <code><font style="background-color: #f9f9f9;">W[4]</font></code>. Therefore we need not look before <code><font style="background-color: #f9f9f9;">W[4]</font></code> to find a terminal string for <code><font style="background-color: #f9f9f9;">W[5]</font></code>. Therefore <code><font style="background-color: #f9f9f9;">T[5] = 1</font></code>.</p>
<p>Finally, we see that the next character in the ongoing segment starting at <code><font style="background-color: #f9f9f9;">W[4] = 'A'</font></code> would be <code><font style="background-color: #f9f9f9;">'B'</font></code>, and indeed this is also <code><font style="background-color: #f9f9f9;">W[5]</font></code>. Furthermore, the same argument as above shows that we need not look before <code><font style="background-color: #f9f9f9;">W[4]</font></code> to find a segment for <code><font style="background-color: #f9f9f9;">W[6]</font></code>, so that this is it, and we take <code><font style="background-color: #f9f9f9;">T[6] = 2</font></code>.</p>
<p>Therefore we compile the following table:</p>
<table style="text-align: right; background-color: white; font-family: monospace;" class="wikitable">
    <tbody>
        <tr>
            <th><code><font style="background-color: #f9f9f9;">i</font></code></th>
            <td>0</td>
            <td>1</td>
            <td>2</td>
            <td>3</td>
            <td>4</td>
            <td>5</td>
            <td>6</td>
        </tr>
        <tr>
            <th><code><font style="background-color: #f9f9f9;">W[i]</font></code></th>
            <td>A</td>
            <td>B</td>
            <td>C</td>
            <td>D</td>
            <td>A</td>
            <td>B</td>
            <td>D</td>
        </tr>
        <tr>
            <th><code><font style="background-color: #f9f9f9;">T[i]</font></code></th>
            <td>-1</td>
            <td>0</td>
            <td>0</td>
            <td>0</td>
            <td>0</td>
            <td>1</td>
            <td>2</td>
        </tr>
    </tbody>
</table>
<br><span id="Description_of_and_pseudocode_for_the_table-building_algorithm" class="mw-headline">Description of and pseudocode for the table-building algorithm</span>
<p>The example above illustrates the general technique for assembling the table with a minimum of fuss. The principle is that of the overall search: most of the work was already done in getting to the current position, so very little needs to be done in leaving it. The only minor complication is that the logic which is correct late in the string erroneously gives non-proper substrings at the beginning. This necessitates some initialization code.</p>
<pre><strong>algorithm</strong> <em>kmp_table</em>:
<strong>input</strong>:
an array of characters, W (the word to be analyzed)
an array of integers, T (the table to be filled)
<strong>output</strong>:
nothing (but during operation, it populates the table)
<strong>define variables</strong>:
an integer, pos &#8592; 2 (the current position we are computing in T)
an integer, cnd &#8592; 0 (the zero-based index in W of the next <br>character of the current candidate substring)
(the first few values are fixed but different from what the algorithm <br>might suggest)
<strong>let</strong> T[0] &#8592; -1, T[1] &#8592; 0
<strong>while</strong> pos is less than the length of W, do:
(first case: the substring continues)
<strong>if</strong> W[pos - 1] = W[cnd], <br>          <strong>let</strong> T[pos] &#8592; cnd + 1, pos &#8592; pos + 1, cnd &#8592; cnd + 1
(second case: it doesn't, but we can fall back)
<strong>otherwise</strong>, <strong>if</strong> cnd &gt; 0, <strong>let</strong> cnd &#8592; T[cnd]
(third case: we have run out of candidates.  Note cnd = 0)
<strong>otherwise</strong>, <strong>let</strong> T[pos] &#8592; 0, pos &#8592; pos + 1
</pre>
<br><span id="Efficiency_of_the_table-building_algorithm" class="mw-headline">Efficiency of the table-building algorithm</span>
<p>The complexity of the table algorithm is <code><font style="background-color: #f9f9f9;">O(n)</font></code>, where <code><font style="background-color: #f9f9f9;">n</font></code> is the length of <code><font style="background-color: #f9f9f9;">W</font></code>. As except for some initialization all the work is done in the <code><strong><font style="background-color: #f9f9f9;">while</font></strong></code> loop, it is sufficient to show that this loop executes in <code><font style="background-color: #f9f9f9;">O(n)</font></code> time, which will be done by simultaneously examining the quantities <code><font style="background-color: #f9f9f9;">pos</font></code> and <code><font style="background-color: #f9f9f9;">pos - cnd</font></code>. In the first branch, <code><font style="background-color: #f9f9f9;">pos - cnd</font></code> is preserved, as both <code><font style="background-color: #f9f9f9;">pos</font></code> and <code><font style="background-color: #f9f9f9;">cnd</font></code> are incremented simultaneously, but naturally, <code><font style="background-color: #f9f9f9;">pos</font></code> is increased. In the second branch, <code><font style="background-color: #f9f9f9;">cnd</font></code> is replaced by <code><font style="background-color: #f9f9f9;">T[cnd]</font></code>, which we saw <a href="http://en.wikipedia.org/wiki/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm#The_efficiency_of_the_search_algorithm"><font color="#002bb8">above</font></a> is always strictly less than <code><font style="background-color: #f9f9f9;">cnd</font></code>, thus increasing <code><font style="background-color: #f9f9f9;">pos - cnd</font></code>. In the third branch, <code><font style="background-color: #f9f9f9;">pos</font></code> is incremented and <code><font style="background-color: #f9f9f9;">cnd</font></code> is not, so both <code><font style="background-color: #f9f9f9;">pos</font></code> and <code><font style="background-color: #f9f9f9;">pos - cnd</font></code> increase. Since <code><font style="background-color: #f9f9f9;">pos &#8805; pos - cnd</font></code>, this means that at each stage either <code><font style="background-color: #f9f9f9;">pos</font></code> or a lower bound for <code><font style="background-color: #f9f9f9;">pos</font></code> increases; therefore since the algorithm terminates once <code><font style="background-color: #f9f9f9;">pos = n</font></code>, it must terminate after at most <code><font style="background-color: #f9f9f9;">2n</font></code> iterations of the loop, since <code><font style="background-color: #f9f9f9;">pos - cnd</font></code> begins at <code><font style="background-color: #f9f9f9;">1</font></code>. Therefore the complexity of the table algorithm is <code><font style="background-color: #f9f9f9;">O(n)</font></code>.</p>
<br><span id="Efficiency_of_the_KMP_algorithm" class="mw-headline">Efficiency of the KMP algorithm</span>
<p>Since the two portions of the algorithm have, respectively, complexities of <code><font style="background-color: #f9f9f9;">O(k)</font></code> and <code><font style="background-color: #f9f9f9;">O(n)</font></code>, the complexity of the overall algorithm is <code><font style="background-color: #f9f9f9;">O(n + k)</font></code>.</p>
<p>As is apparent from the <a href="http://en.wikipedia.org/wiki/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm#A_worked_example_of_the_search_algorithm"><font color="#002bb8">worked example</font></a>, the algorithm makes its greatest gains over a naive string-searching algorithm when it can skip the most characters at a time. That is, the less it has to backtrack, the faster it goes, which is reflected in the table <code><font style="background-color: #f9f9f9;">T</font></code> by the presence of zeroes. A word such as <code><font style="background-color: #f9f9f9;">"ABCDEFG"</font></code> works well with this algorithm because it has no repetitions of its beginning, so that its table is simply all zeroes with a -1 at the beginning. On the opposite end of the spectrum, <code><font style="background-color: #f9f9f9;">W = "AAAAAAA"</font></code> works terribly, because its table is</p>
<table style="text-align: right; background-color: white; font-family: monospace;" class="wikitable">
    <tbody>
        <tr>
            <th><code><font style="background-color: #f9f9f9;">i</font></code></th>
            <td>0</td>
            <td>1</td>
            <td>2</td>
            <td>3</td>
            <td>4</td>
            <td>5</td>
            <td>6</td>
        </tr>
        <tr>
            <th><code><font style="background-color: #f9f9f9;">W[i]</font></code></th>
            <td>A</td>
            <td>A</td>
            <td>A</td>
            <td>A</td>
            <td>A</td>
            <td>A</td>
            <td>A</td>
        </tr>
        <tr>
            <th><code><font style="background-color: #f9f9f9;">T[i]</font></code></th>
            <td>-1</td>
            <td>0</td>
            <td>1</td>
            <td>2</td>
            <td>3</td>
            <td>4</td>
            <td>5</td>
        </tr>
    </tbody>
</table>
<p>This is the worst possible pattern for <code><font style="background-color: #f9f9f9;">T</font></code>, and it can be exploited by a word such as <code><font style="background-color: #f9f9f9;">S = "AAAAAABAAAAAABAAAAAAA"</font></code>, in which the algorithm tries to match each <code><font style="background-color: #f9f9f9;">'A'</font></code> against each 'B' before giving up; this results in the maximum possible number of iterations, verging on twice the number of characters of S as the number of repetitions of <code><font style="background-color: #f9f9f9;">"AAAAAAB"</font></code> increases. Although the table-building routine is rapid for this word (since no backtracking ever occurs), this routine is run only once for a given <code><font style="background-color: #f9f9f9;">W</font></code>, while the search routine is potentially run many times. If each time, this <code><font style="background-color: #f9f9f9;">W</font></code> is searched for in strings like <code><font style="background-color: #f9f9f9;">S</font></code>, the overall efficiency will be as poor as possible. By way of comparison, this particular combination is a <em>best</em> case for the <a class="mw-redirect" title="Boyer-Moore string search algorithm" href="http://en.wikipedia.org/wiki/Boyer-Moore_string_search_algorithm"><font color="#002bb8">Boyer-Moore string search algorithm</font></a>.</p>
<p>Note that in practice, the KMP algorithm is not good at searching in natural language texts because it can only skip characters when the first part of the pattern actually matches a part of the text. In practice this only happens occasionally in natural language texts. For instance, consider how many times a prefix of the pattern "text" matches something in this paragraph.</p>
<br>there are also some references&nbsp;and furtuer explanation for&nbsp;kmp algorithm:<br>1.<a href="http://www.ics.uci.edu/~eppstein/161/960227.html">http://www.ics.uci.edu/~eppstein/161/960227.html</a><br>2.<a href="http://www.ics.uci.edu/~eppstein/161/kmp/">http://www.ics.uci.edu/~eppstein/161/kmp/</a><br>3.<a href="http://www-igm.univ-mlv.fr/~lecroq/string/node8.html">http://www-igm.univ-mlv.fr/~lecroq/string/node8.html</a><br>4.<a href="http://www.inf.fh-flensburg.de/lang/algorithmen/pattern/kmpen.htm">http://www.inf.fh-flensburg.de/lang/algorithmen/pattern/kmpen.htm</a><br><br><br>from:<br>1.<a href="http://en.wikipedia.org/wiki/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm">http://en.wikipedia.org/wiki/Knuth%E2%80%93Morris%E2%80%93Pratt_algorithm<br></a><br><br> <img src ="http://www.cppblog.com/beautykingdom/aggbug/109232.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2010-03-08 22:51 <a href="http://www.cppblog.com/beautykingdom/archive/2010/03/08/109232.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Hash Function related</title><link>http://www.cppblog.com/beautykingdom/archive/2010/03/07/109150.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Sun, 07 Mar 2010 15:24:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2010/03/07/109150.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/109150.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2010/03/07/109150.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/109150.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/109150.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp; 基于比较的的查找方法，查找效率依赖比较次数，其实理想的查找是希望不经比较，一次存取便能得到所查记录。这样就必须在记录的存储位置和它的关键字之间建立一个确定
的对应关系f，查找k时,只要根据这个对应关系f找到给定值k的像f(k)。这种对应关系f叫哈希（hash）函数。按这种思想建立的表叫哈希表（也叫散
列表）。
<p style="margin-top: 0px; margin-bottom: 0px;" align="left">&nbsp;&nbsp;&nbsp; 哈希表存取方便但存储时容易冲突（collision）：即不同的关键字可以对应同一哈希地址。如何确定哈希函数和解决冲突是哈希表查找的关键。</p>
<p style="margin-top: 0px; margin-bottom: 0px;" align="left">&nbsp;&nbsp;&nbsp; <strong>1.哈希函数的构造方法</strong></p>
<p style="margin-top: 0px; margin-bottom: 0px;" align="left">&nbsp;&nbsp;&nbsp; 构造哈希函数的方法有很多，这里介绍几种常用的。</p>
<p style="margin-top: 0px; margin-bottom: 0px;" align="left"><font color="#ff0000">直接定址法</font>:H(k)=k 或H(k)=a*k+b(线形函数)</p>
<p style="margin-top: 0px; margin-bottom: 0px;" align="left">如:人口数字统计表</p>
<table border="0" width="100%">
    <tbody>
        <tr>
            <td align="middle" width="11%">地址</td>
            <td align="middle" width="11%">1</td>
            <td align="middle" width="11%">2</td>
            <td align="middle" width="11%">3</td>
            <td align="middle" width="11%">...</td>
            <td align="middle" width="12%">100</td>
        </tr>
        <tr>
            <td align="middle" width="11%">年龄</td>
            <td align="middle" width="11%">1</td>
            <td align="middle" width="11%">2</td>
            <td align="middle" width="11%">3</td>
            <td align="middle" width="11%">...</td>
            <td align="middle" width="12%">100</td>
        </tr>
        <tr>
            <td align="middle" width="11%">人数</td>
            <td align="middle" width="11%">67</td>
            <td align="middle" width="11%">3533</td>
            <td align="middle" width="11%">244</td>
            <td align="middle" width="11%">...</td>
            <td align="middle" width="12%">4</td>
        </tr>
    </tbody>
</table>
<p style="margin-top: 0px; margin-bottom: 0px;" align="left"><font color="#ff0000">数字分析法</font>:取关键字的若干数位组成哈希地址</p>
<p style="margin-top: 0px; margin-bottom: 0px;" align="left">如：关键字如下：若哈希表长为100则可取中间两位10进制数作为哈希地址。&nbsp;&nbsp; </p>
<table border="0" width="100%">
    <tbody>
        <tr>
            <td align="middle" width="12%">81346532</td>
            <td align="middle" width="12%">81372242</td>
            <td align="middle" width="12%">81387422</td>
            <td align="middle" width="12%">81301367</td>
            <td align="middle" width="13%">81322817</td>
            <td align="middle" width="13%">81338967</td>
            <td align="middle" width="13%">81354157</td>
            <td align="middle" width="13%">81368537</td>
        </tr>
    </tbody>
</table>
<p style="margin-top: 0px; margin-bottom: 0px;" align="left"><font color="#ff0000">平方取中法</font>：关键字平方后取中间几位数组成哈希地址</p>
<p style="margin-top: 0px; margin-bottom: 0px;" align="left"><font color="#ff0000">折叠法</font>：将关键数字分割成位数相同的几部分（最后一部分的位数可以不同）然后取几部分的叠加和（舍去进位）作为哈希地址。</p>
<p style="margin-top: 0px; margin-bottom: 0px;" align="left"><font color="#ff0000">除留余数法</font>：取关键字被某个不大于表长m的数p除后所得的余数为哈希地址。</p>
<p style="margin-top: 0px; margin-bottom: 0px;" align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; H(k)=k mod p&nbsp; p&lt;=m</p>
<p style="margin-top: 0px; margin-bottom: 0px;" align="left"><font color="#ff0000">随机数法</font>：H(k)=rondom(k)。</p>
<p style="margin-top: 0px; margin-bottom: 0px;" align="left">　</p>
<p style="margin-top: 0px; margin-bottom: 0px;" align="left">&nbsp;&nbsp;&nbsp; <strong>2.处理冲突的方法</strong></p>
<p style="margin-top: 0px; margin-bottom: 0px;" align="left">&nbsp;&nbsp;&nbsp;
假设地址集为0..n-1,由关键字得到的哈希地址为j(0&lt;=j&lt;=n-1)的位置已存有记录,处理冲突就是为该关键字的记录找到另一个"
空"的哈希地址。在处理中可能得到一个地址序列Hi i=1，2，...k
0&lt;=Hi&lt;=n-1),即在处理冲突时若得到的另一个哈希地址H1仍发生冲突,再求下一地址H2,若仍冲突,再求H3...。怎样得到Hi
呢？</p>
<p style="margin-top: 0px; margin-bottom: 0px;" align="left"><font color="#ff0000">开放定址法</font><font color="#000000">：Hi=(H(k)+di) mod m&nbsp; （H(k)为哈希函数；m为哈希表长；di为增量序列）</font></p>
<p style="margin-top: 0px; margin-bottom: 0px;" align="left"><font color="#000000">当di=1，2，3，... m-1 时叫</font><font color="#ff0000">线性探测</font><font color="#000000">再散列。</font></p>
<p style="margin-top: 0px; margin-bottom: 0px;" align="left"><font color="#000000">当di=1<sup>2</sup>，-1<sup>2</sup>，2<sup>2</sup>，-2<sup>2</sup>，3<sup>2</sup>，-3<sup>2</sup>，...,k<sup>2</sup>,-k<sup>2</sup>时叫</font><font color="#ff0000">二次探测</font><font color="#000000">再散列。</font></p>
<p style="margin-top: 0px; margin-bottom: 0px;" align="left"><font color="#000000">当di=random（m）时叫</font><font color="#ff0000">伪随机探测</font><font color="#000000">序列。</font></p>
<p style="margin-top: 0px; margin-bottom: 0px;" align="left"><font color="#000000">例：长度为11的哈希表关键字分别为17，60，29，哈希函数为H(k)=k mod 11,第四个记录的关键字为38，分别按上述方法添入哈希表的地址为8，4，3（随机数=9）。<span style="color: red;">---为什么不是6，5，7呢</span></font></p>
<p style="margin-top: 0px; margin-bottom: 0px;" align="left"><font color="#ff0000">再哈希法</font><font color="#000000">：Hi=RHi(key) i=1,2,...,k,其中RHi均为不同的哈希函数。</font></p>
<p style="margin-top: 0px; margin-bottom: 0px;" align="left"><font color="#ff0000">链地址法</font><font color="#000000">：这种方法很象基数排序，相同的地址的关键字值均链入对应的链表中。</font></p>
<p style="margin-top: 0px; margin-bottom: 0px;" align="left"><font color="#ff0000">建立公益区法</font><font color="#000000">：另设一个溢出表，不管得到的哈希地址如何，一旦发生冲突，都填入溢出表。</font></p>
<p style="margin-top: 0px; margin-bottom: 0px;" align="left">&nbsp;</p>
<p style="margin-top: 0px; margin-bottom: 0px;" align="left"><font color="#000000">&nbsp;&nbsp;&nbsp; <strong>3.哈希表的查找</strong></font></p>
<p style="margin-top: 0px; margin-bottom: 0px;" align="left"><font color="#000000">例:如下一组关键字按哈希函数H(k)=k mod 13和线性探测处理冲突所得的哈希表a[0..15]:</font></p>
<table border="0" height="41" width="102%">
    <tbody>
        <tr>
            <td align="middle" bgcolor="#008000" height="16" width="6%"><font color="#ffffff">&nbsp;0</font></td>
            <td align="middle" bgcolor="#008000" height="16" width="6%"><font color="#ffffff">1</font></td>
            <td align="middle" bgcolor="#008000" height="16" width="6%"><font color="#ffffff">2</font></td>
            <td align="middle" bgcolor="#008000" height="16" width="6%"><font color="#ffffff">3</font></td>
            <td align="middle" bgcolor="#008000" height="16" width="6%"><font color="#ffffff">4</font></td>
            <td align="middle" bgcolor="#008000" height="16" width="6%"><font color="#ffffff">5</font></td>
            <td align="middle" bgcolor="#008000" height="16" width="6%"><font color="#ffffff">6</font></td>
            <td align="middle" bgcolor="#008000" height="16" width="6%"><font color="#ffffff">7</font></td>
            <td align="middle" bgcolor="#008000" height="16" width="6%"><font color="#ffffff">8</font></td>
            <td align="middle" bgcolor="#008000" height="16" width="6%"><font color="#ffffff">9</font></td>
            <td align="middle" bgcolor="#008000" height="16" width="6%"><font color="#ffffff">10</font></td>
            <td align="middle" bgcolor="#008000" height="16" width="6%"><font color="#ffffff">11</font></td>
            <td align="middle" bgcolor="#008000" height="16" width="7%"><font color="#ffffff">12</font></td>
            <td align="middle" bgcolor="#008000" height="16" width="7%"><font color="#ffffff">13</font></td>
            <td align="middle" bgcolor="#008000" height="16" width="7%"><font color="#ffffff">14</font></td>
            <td align="middle" bgcolor="#008000" height="16" width="7%"><font color="#ffffff">15</font></td>
        </tr>
        <tr>
            <td align="middle" bgcolor="#008000" height="13" width="6%"><font color="#ffffff">　</font></td>
            <td align="middle" bgcolor="#008000" height="13" width="6%"><font color="#ffffff">14</font></td>
            <td align="middle" bgcolor="#008000" height="13" width="6%"><font color="#ffffff">01</font></td>
            <td align="middle" bgcolor="#008000" height="13" width="6%"><font color="#ffffff">68</font></td>
            <td align="middle" bgcolor="#008000" height="13" width="6%"><font color="#ffffff">27</font></td>
            <td align="middle" bgcolor="#008000" height="13" width="6%"><font color="#ffffff">55</font></td>
            <td align="middle" bgcolor="#008000" height="13" width="6%"><font color="#ffffff">19</font></td>
            <td align="middle" bgcolor="#008000" height="13" width="6%"><font color="#ffffff">20</font></td>
            <td align="middle" bgcolor="#008000" height="13" width="6%"><font color="#ffffff">84</font></td>
            <td align="middle" bgcolor="#008000" height="13" width="6%"><font color="#ffffff">79</font></td>
            <td align="middle" bgcolor="#008000" height="13" width="6%"><font color="#ffffff">23</font></td>
            <td align="middle" bgcolor="#008000" height="13" width="6%"><font color="#ffffff">11</font></td>
            <td align="middle" bgcolor="#008000" height="13" width="7%"><font color="#ffffff">10</font></td>
            <td align="middle" bgcolor="#008000" height="13" width="7%"><font color="#ffffff">　</font></td>
            <td align="middle" bgcolor="#008000" height="13" width="7%">　</td>
            <td align="middle" bgcolor="#008000" height="13" width="7%">　</td>
        </tr>
    </tbody>
</table>
<p style="margin-top: 0px; margin-bottom: 0px;" align="left">当给定值k=84,则首先和a[6]比，再依次和a[7],a[8]比，结果a[8]=84查找成功。</p>
<p style="margin-top: 0px; margin-bottom: 0px;" align="left">当给定值k=38,则首先和a[12]比,再和a[13]比,由于a[13]没有,查找不成功,表中不存在关键字等于38的记录。</p>
<br>from：<br>http://www.coood.com/postfile/2006-12-31/20061231174649.shtml
<br>others will be appended later<br> <img src ="http://www.cppblog.com/beautykingdom/aggbug/109150.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2010-03-07 23:24 <a href="http://www.cppblog.com/beautykingdom/archive/2010/03/07/109150.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>Trie树|字典树的简介及实现（转）</title><link>http://www.cppblog.com/beautykingdom/archive/2010/01/28/106650.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Thu, 28 Jan 2010 09:07:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2010/01/28/106650.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/106650.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2010/01/28/106650.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/106650.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/106650.html</trackback:ping><description><![CDATA[Trie,又称字典树、单词查找树,是一种树形结构，用于保存大量的字符串。它的优点是：利用字符串的公共前缀来节约存储空间。<br>相对来说,Trie树是一种比较简单的数据结构.理解起来比较简单,正所谓简单的东西也得付出代价.故Trie树也有它的缺点,Trie树的内存消耗非常大.当然,或许用左儿子右兄弟的方法建树的话,可能会好点.<br>
<p><font face="楷体_GB2312" size="3">其基本性质可以归纳为：<br>1. 根节点不包含字符，除根节点外每一个节点都只包含一个字符。 <br>2. 从根节点到某一节点，路径上经过的字符连接起来，为该节点对应的字符串。 <br>3. 每个节点的所有子节点包含的字符都不相同。</font></p>
<p><font face="楷体_GB2312" size="3">其基本操作有:查找 插入和删除,当然删除操作比较少见.我在这里只是实现了对整个树的删除操作,至于单个word的删除操作也很简单.</font></p>
<p><font face="楷体_GB2312" size="3"><span>搜索字典项目的方法为：</span></font></p>
<p><font face="楷体_GB2312" size="3"><span>(1) 从根结点开始一次搜索；</span><span><br></span></font></p>
<p><font face="楷体_GB2312" size="3"><span>(2) 取得要查找关键词的第一个字母，并根据该字母选择对应的子树并转到该子树继续进行检索；</span></font></p>
<div align="left"><font face="楷体_GB2312" size="3"><span>(3) 在相应的子树上，取得要查找关键词的第二个字母,</span>并进一步选择对应的子树进行检索。</font></div>
<div align="left"><font face="楷体_GB2312" size="3"><span>(4) 迭代过程&#8230;&#8230;</span></font></div>
<div align="left"><font face="楷体_GB2312" size="3"><span>(5) 在某个结点处，关键词的所有字母已被取出，则读取</span>附在该结点上的信息，即完成查找。<br>其他操作类似处理.<br></font></div>
<div forimg="1"><font face="楷体_GB2312" size="3"><img  src="http://www.cppblog.com/images/cppblog_com/abilitytao/Trie.jpg" alt="" width="388" border="0" height="325"></font></div>
<font face="楷体_GB2312" size="3"><br></font>
<p>&nbsp;</p>
<font face="楷体_GB2312" size="3">
</font>
<div style="border: 1px solid #cccccc; padding: 4px 5px 4px 4px; font-size: 13px; width: 98%; background-color: #eeeeee;"><font face="楷体_GB2312" size="3"><img  src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" id="Codehighlighter1_0_73_Open_Image" onclick="this.style.display='none'; codehighlighter1_0_73_open_text.style.display="'none';" codehighlighter1_0_73_closed_image.style.display="'inline';" codehighlighter1_0_73_closed_text.style.display="'inline';"" align="top"><img  src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" id="Codehighlighter1_0_73_Closed_Image" style="display: none;" onclick="this.style.display='none'; codehighlighter1_0_73_closed_text.style.display="'none';" codehighlighter1_0_73_open_image.style.display="'inline';" codehighlighter1_0_73_open_text.style.display="'inline';"" align="top"><span id="Codehighlighter1_0_73_Closed_Text" style="border: 1px solid #808080; display: none; background-color: #ffffff;">/**/</span><span id="Codehighlighter1_0_73_Open_Text"><span style="color: #008000;">/*</span><span style="color: #008000;"><br><img  src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">Name:&nbsp;Trie树的基本实现&nbsp;<br><img  src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">Author:&nbsp;MaiK&nbsp;<br><img  src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">Description:&nbsp;Trie树的基本实现&nbsp;,包括查找&nbsp;插入和删除操作</span><span style="color: #008000;">*/</span></span><span style="color: #000000;"><br><img  src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top">#include</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">algorithm</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br><img  src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top">#include</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">iostream</span><span style="color: #000000;">&gt;</span><span style="color: #000000;"><br><img  src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"></span><span style="color: #0000ff;">using</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">namespace</span><span style="color: #000000;">&nbsp;std;<br><img  src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"><br><img  src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"></span><span style="color: #0000ff;">const</span><span style="color: #000000;">&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;sonnum</span><span style="color: #000000;">=</span><span style="color: #000000;">26</span><span style="color: #000000;">,</span><span style="color: #0000ff;">base</span><span style="color: #000000;">=</span><span style="color: #000000;">'</span><span style="color: #000000;">a</span><span style="color: #000000;">'</span><span style="color: #000000;">;<br><img  src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"></span><span style="color: #0000ff;">struct</span><span style="color: #000000;">&nbsp;Trie<br><img  src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" id="Codehighlighter1_178_388_Open_Image" onclick="this.style.display='none'; codehighlighter1_178_388_open_text.style.display="'none';" codehighlighter1_178_388_closed_image.style.display="'inline';" codehighlighter1_178_388_closed_text.style.display="'inline';"" align="top"><img  src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" id="Codehighlighter1_178_388_Closed_Image" style="display: none;" onclick="this.style.display='none'; codehighlighter1_178_388_closed_text.style.display="'none';" codehighlighter1_178_388_open_image.style.display="'inline';" codehighlighter1_178_388_open_text.style.display="'inline';"" align="top"></span><span id="Codehighlighter1_178_388_Closed_Text" style="border: 1px solid #808080; display: none; background-color: #ffffff;"><img  src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_178_388_Open_Text"><span style="color: #000000;">{<br><img  src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;num;</span><span style="color: #008000;">//</span><span style="color: #008000;">to&nbsp;remember&nbsp;how&nbsp;many&nbsp;word&nbsp;can&nbsp;reach&nbsp;here,that&nbsp;is&nbsp;to&nbsp;say,prefix</span><span style="color: #008000;"><br><img  src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">bool</span><span style="color: #000000;">&nbsp;terminal;</span><span style="color: #008000;">//</span><span style="color: #008000;">If&nbsp;terminal==true&nbsp;,the&nbsp;current&nbsp;point&nbsp;has&nbsp;no&nbsp;following&nbsp;point</span><span style="color: #008000;"><br><img  src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top"></span><span style="color: #000000;">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">struct</span><span style="color: #000000;">&nbsp;Trie&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">son[sonnum];</span><span style="color: #008000;">//</span><span style="color: #008000;">the&nbsp;following&nbsp;point</span><span style="color: #008000;"><br><img  src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top"></span><span style="color: #000000;">}</span></span><span style="color: #000000;">;<br><img  src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top">Trie&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">NewTrie()</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;create&nbsp;a&nbsp;new&nbsp;node</span><span style="color: #008000;"><br><img  src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" id="Codehighlighter1_427_557_Open_Image" onclick="this.style.display='none'; codehighlighter1_427_557_open_text.style.display="'none';" codehighlighter1_427_557_closed_image.style.display="'inline';" codehighlighter1_427_557_closed_text.style.display="'inline';"" align="top"><img  src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" id="Codehighlighter1_427_557_Closed_Image" style="display: none;" onclick="this.style.display='none'; codehighlighter1_427_557_closed_text.style.display="'none';" codehighlighter1_427_557_open_image.style.display="'inline';" codehighlighter1_427_557_open_text.style.display="'inline';"" align="top"></span><span id="Codehighlighter1_427_557_Closed_Text" style="border: 1px solid #808080; display: none; background-color: #ffffff;"><img  src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_427_557_Open_Text"><span style="color: #000000;">{<br><img  src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;Trie&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">temp</span><span style="color: #000000;">=</span><span style="color: #0000ff;">new</span><span style="color: #000000;">&nbsp;Trie;<br><img  src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;temp</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">num</span><span style="color: #000000;">=</span><span style="color: #000000;">1</span><span style="color: #000000;">;temp</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">terminal</span><span style="color: #000000;">=</span><span style="color: #0000ff;">false</span><span style="color: #000000;">;<br><img  src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&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;">0</span><span style="color: #000000;">;i</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">sonnum;</span><span style="color: #000000;">++</span><span style="color: #000000;">i)temp</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">son[i]</span><span style="color: #000000;">=</span><span style="color: #000000;">NULL;<br><img  src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;temp;<br><img  src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}</span></span><span style="color: #000000;"><br><img  src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"></span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;Insert(Trie&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">pnt,</span><span style="color: #0000ff;">char</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">s,</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;len)</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;insert&nbsp;a&nbsp;new&nbsp;word&nbsp;to&nbsp;Trie&nbsp;tree</span><span style="color: #008000;"><br><img  src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" id="Codehighlighter1_631_864_Open_Image" onclick="this.style.display='none'; codehighlighter1_631_864_open_text.style.display="'none';" codehighlighter1_631_864_closed_image.style.display="'inline';" codehighlighter1_631_864_closed_text.style.display="'inline';"" align="top"><img  src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" id="Codehighlighter1_631_864_Closed_Image" style="display: none;" onclick="this.style.display='none'; codehighlighter1_631_864_closed_text.style.display="'none';" codehighlighter1_631_864_open_image.style.display="'inline';" codehighlighter1_631_864_open_text.style.display="'inline';"" align="top"></span><span id="Codehighlighter1_631_864_Closed_Text" style="border: 1px solid #808080; display: none; background-color: #ffffff;"><img  src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_631_864_Open_Text"><span style="color: #000000;">{<br><img  src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;Trie&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">temp</span><span style="color: #000000;">=</span><span style="color: #000000;">pnt;<br><img  src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&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;">0</span><span style="color: #000000;">;i</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">len;</span><span style="color: #000000;">++</span><span style="color: #000000;">i)<br><img  src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" id="Codehighlighter1_684_837_Open_Image" onclick="this.style.display='none'; codehighlighter1_684_837_open_text.style.display="'none';" codehighlighter1_684_837_closed_image.style.display="'inline';" codehighlighter1_684_837_closed_text.style.display="'inline';"" align="top"><img  src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" id="Codehighlighter1_684_837_Closed_Image" style="display: none;" onclick="this.style.display='none'; codehighlighter1_684_837_closed_text.style.display="'none';" codehighlighter1_684_837_open_image.style.display="'inline';" codehighlighter1_684_837_open_text.style.display="'inline';"" align="top">&nbsp;&nbsp;&nbsp;&nbsp;</span><span id="Codehighlighter1_684_837_Closed_Text" style="border: 1px solid #808080; display: none; background-color: #ffffff;"><img  src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_684_837_Open_Text"><span style="color: #000000;">{<br><img  src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">(temp</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">son[s[i]</span><span style="color: #000000;">-</span><span style="color: #0000ff;">base</span><span style="color: #000000;">]</span><span style="color: #000000;">==</span><span style="color: #000000;">NULL)temp</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">son[s[i]</span><span style="color: #000000;">-</span><span style="color: #0000ff;">base</span><span style="color: #000000;">]</span><span style="color: #000000;">=</span><span style="color: #000000;">NewTrie();<br><img  src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">else</span><span style="color: #000000;">&nbsp;temp</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">son[s[i]</span><span style="color: #000000;">-</span><span style="color: #0000ff;">base</span><span style="color: #000000;">]</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">num</span><span style="color: #000000;">++</span><span style="color: #000000;">;<br><img  src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;temp</span><span style="color: #000000;">=</span><span style="color: #000000;">temp</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">son[s[i]</span><span style="color: #000000;">-</span><span style="color: #0000ff;">base</span><span style="color: #000000;">];<br><img  src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000;"><br><img  src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;temp</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">terminal</span><span style="color: #000000;">=</span><span style="color: #0000ff;">true</span><span style="color: #000000;">;<br><img  src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}</span></span><span style="color: #000000;"><br><img  src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"></span><span style="color: #0000ff;">void</span><span style="color: #000000;">&nbsp;Delete(Trie&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">pnt)</span><span style="color: #008000;">//</span><span style="color: #008000;">&nbsp;delete&nbsp;the&nbsp;whole&nbsp;tree</span><span style="color: #008000;"><br><img  src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" id="Codehighlighter1_913_1059_Open_Image" onclick="this.style.display='none'; codehighlighter1_913_1059_open_text.style.display="'none';" codehighlighter1_913_1059_closed_image.style.display="'inline';" codehighlighter1_913_1059_closed_text.style.display="'inline';"" align="top"><img  src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" id="Codehighlighter1_913_1059_Closed_Image" style="display: none;" onclick="this.style.display='none'; codehighlighter1_913_1059_closed_text.style.display="'none';" codehighlighter1_913_1059_open_image.style.display="'inline';" codehighlighter1_913_1059_open_text.style.display="'inline';"" align="top"></span><span id="Codehighlighter1_913_1059_Closed_Text" style="border: 1px solid #808080; display: none; background-color: #ffffff;"><img  src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_913_1059_Open_Text"><span style="color: #000000;">{<br><img  src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">(pnt</span><span style="color: #000000;">!=</span><span style="color: #000000;">NULL)<br><img  src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" id="Codehighlighter1_937_1057_Open_Image" onclick="this.style.display='none'; codehighlighter1_937_1057_open_text.style.display="'none';" codehighlighter1_937_1057_closed_image.style.display="'inline';" codehighlighter1_937_1057_closed_text.style.display="'inline';"" align="top"><img  src="http://www.cppblog.com/Images/OutliningIndicators/ContractedSubBlock.gif" id="Codehighlighter1_937_1057_Closed_Image" style="display: none;" onclick="this.style.display='none'; codehighlighter1_937_1057_closed_text.style.display="'none';" codehighlighter1_937_1057_open_image.style.display="'inline';" codehighlighter1_937_1057_open_text.style.display="'inline';"" align="top">&nbsp;&nbsp;&nbsp;&nbsp;</span><span id="Codehighlighter1_937_1057_Closed_Text" style="border: 1px solid #808080; display: none; background-color: #ffffff;"><img  src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_937_1057_Open_Text"><span style="color: #000000;">{<br><img  src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&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;">0</span><span style="color: #000000;">;i</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">sonnum;</span><span style="color: #000000;">++</span><span style="color: #000000;">i)</span><span style="color: #0000ff;">if</span><span style="color: #000000;">(pnt</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">son[i]</span><span style="color: #000000;">!=</span><span style="color: #000000;">NULL)Delete(pnt</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">son[i]);<br><img  src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;delete&nbsp;pnt;&nbsp;<br><img  src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pnt</span><span style="color: #000000;">=</span><span style="color: #000000;">NULL;<br><img  src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="color: #000000;"><br><img  src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}</span></span><span style="color: #000000;"><br><img  src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top">Trie</span><span style="color: #000000;">*</span><span style="color: #000000;">&nbsp;Find(Trie&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">pnt,</span><span style="color: #0000ff;">char</span><span style="color: #000000;">&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">s,</span><span style="color: #0000ff;">int</span><span style="color: #000000;">&nbsp;len)</span><span style="color: #008000;">//</span><span style="color: #008000;">trie&nbsp;to&nbsp;find&nbsp;the&nbsp;current&nbsp;word</span><span style="color: #008000;"><br><img  src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockStart.gif" id="Codehighlighter1_1130_1287_Open_Image" onclick="this.style.display='none'; codehighlighter1_1130_1287_open_text.style.display="'none';" codehighlighter1_1130_1287_closed_image.style.display="'inline';" codehighlighter1_1130_1287_closed_text.style.display="'inline';"" align="top"><img  src="http://www.cppblog.com/Images/OutliningIndicators/ContractedBlock.gif" id="Codehighlighter1_1130_1287_Closed_Image" style="display: none;" onclick="this.style.display='none'; codehighlighter1_1130_1287_closed_text.style.display="'none';" codehighlighter1_1130_1287_open_image.style.display="'inline';" codehighlighter1_1130_1287_open_text.style.display="'inline';"" align="top"></span><span id="Codehighlighter1_1130_1287_Closed_Text" style="border: 1px solid #808080; display: none; background-color: #ffffff;"><img  src="http://www.cppblog.com/Images/dot.gif"></span><span id="Codehighlighter1_1130_1287_Open_Text"><span style="color: #000000;">{<br><img  src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;Trie&nbsp;</span><span style="color: #000000;">*</span><span style="color: #000000;">temp</span><span style="color: #000000;">=</span><span style="color: #000000;">pnt;<br><img  src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&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;">0</span><span style="color: #000000;">;i</span><span style="color: #000000;">&lt;</span><span style="color: #000000;">len;</span><span style="color: #000000;">++</span><span style="color: #000000;">i)<br><img  src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">if</span><span style="color: #000000;">(temp</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">son[s[i]</span><span style="color: #000000;">-</span><span style="color: #0000ff;">base</span><span style="color: #000000;">]</span><span style="color: #000000;">!=</span><span style="color: #000000;">NULL)temp</span><span style="color: #000000;">=</span><span style="color: #000000;">temp</span><span style="color: #000000;">-&gt;</span><span style="color: #000000;">son[s[i]</span><span style="color: #000000;">-</span><span style="color: #0000ff;">base</span><span style="color: #000000;">];<br><img  src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&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;">return</span><span style="color: #000000;">&nbsp;NULL;<br><img  src="http://www.cppblog.com/Images/OutliningIndicators/InBlock.gif" align="top">&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000ff;">return</span><span style="color: #000000;">&nbsp;temp;<br><img  src="http://www.cppblog.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align="top">}</span></span><span style="color: #000000;">&nbsp;<br><img  src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"><br><img  src="http://www.cppblog.com/Images/OutliningIndicators/None.gif" align="top"></span></font></div>
<font face="楷体_GB2312" size="3"><br>转自：<a  href="http://hi.baidu.com/luyade1987/blog/item/2667811631106657f2de320a.html">http://hi.baidu.com/luyade1987/blog/item/2667811631106657f2de320a.html</a></font><img src ="http://www.cppblog.com/beautykingdom/aggbug/106650.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2010-01-28 17:07 <a href="http://www.cppblog.com/beautykingdom/archive/2010/01/28/106650.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>网上应聘笔试题目大收集&lt;转&gt;</title><link>http://www.cppblog.com/beautykingdom/archive/2009/12/06/102677.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Sun, 06 Dec 2009 15:35:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2009/12/06/102677.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/102677.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2009/12/06/102677.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/102677.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/102677.html</trackback:ping><description><![CDATA[网上应聘笔试题目大收集！权威！（没事时做做无害） 2008-02-18 17:35 应聘笔试题目：<a href="http://zhan.cn.yahoo.com/wuliu56/369471/1.html">http://zhan.cn.yahoo.com/wuliu56/369471/1.html</a><br>应聘笔试题（考察你的数学分析推理能力 <a href="http://zhan.cn.yahoo.com/articles/071120/43551_29.html">http://zhan.cn.yahoo.com/articles/071120/43551_29.html</a><br>两道逻辑考题<a href="http://zhan.cn.yahoo.com/articles/071120/43551_28.html">http://zhan.cn.yahoo.com/articles/071120/43551_28.html</a><br>应聘笔试题目 <a href="http://zhan.cn.yahoo.com/articles/071120/43551_27.html">http://zhan.cn.yahoo.com/articles/071120/43551_27.html</a><br>企业招聘笔试题荟萃(理工科)http://zhan.cn.yahoo.com/articles/071120/43551_26.html<br>IBM1999社会招聘笔试题 <a href="http://zhan.cn.yahoo.com/articles/071120/43551_25.html">http://zhan.cn.yahoo.com/articles/071120/43551_25.html</a><br>微软笔试题 <br><a href="http://zhan.cn.yahoo.com/articles/071120/43551_24.html">http://zhan.cn.yahoo.com/articles/071120/43551_24.html</a><br>德勤CLUB笔试题整理 <br><a href="http://zhan.cn.yahoo.com/articles/071120/43551_23.html">http://zhan.cn.yahoo.com/articles/071120/43551_23.html</a><br>笔试智力题<br><a href="http://zhan.cn.yahoo.com/articles/071120/43551_22.html">http://zhan.cn.yahoo.com/articles/071120/43551_22.html</a><br>笔试题;怎样为肯德基选址！ <a href="http://zhan.cn.yahoo.com/articles/071120/43551_21.html">http://zhan.cn.yahoo.com/articles/071120/43551_21.html</a><br>500个面试智力题！（2） <br><a href="http://zhan.cn.yahoo.com/articles/071120/43551_20.html">http://zhan.cn.yahoo.com/articles/071120/43551_20.html</a><br>593个智力题！应聘者笔试时必看！ <br><a href="http://zhan.cn.yahoo.com/articles/071120/43551_19.html">http://zhan.cn.yahoo.com/articles/071120/43551_19.html</a><br>国泰君安应聘笔试题目 <br><a href="http://zhan.cn.yahoo.com/articles/071120/43551_16.html">http://zhan.cn.yahoo.com/articles/071120/43551_16.html</a><br>世界500强应聘笔试题目（2） <br><a href="http://zhan.cn.yahoo.com/articles/071120/43551_14.html">http://zhan.cn.yahoo.com/articles/071120/43551_14.html</a><br>世界500强面试/笔试题荟萃 <br><a href="http://zhan.cn.yahoo.com/articles/071120/43551_12.html">http://zhan.cn.yahoo.com/articles/071120/43551_12.html</a><br>经典：第一财经日报笔试题及分析 <br><a href="http://zhan.cn.yahoo.com/articles/071120/43551_11.html">http://zhan.cn.yahoo.com/articles/071120/43551_11.html</a><br>应聘笔试试题（考验你的创意） <br><a href="http://zhan.cn.yahoo.com/articles/071120/43551_10.html">http://zhan.cn.yahoo.com/articles/071120/43551_10.html</a><br>挑战推理能力的极限（只有千分之一的人能完成） <a href="http://zhan.cn.yahoo.com/articles/071120/43551_9.html">http://zhan.cn.yahoo.com/articles/071120/43551_9.html</a><br>应聘笔试智力题<a href="http://zhan.cn.yahoo.com/articles/071120/43551_8.html">http://zhan.cn.yahoo.com/articles/071120/43551_8.html</a><br>物流企业笔试题目：马士基笔试题目 <a href="http://zhan.cn.yahoo.com/articles/071120/43551_6.html">http://zhan.cn.yahoo.com/articles/071120/43551_6.html</a><br><br>转自<br><a href="http://blog.chinaunix.net/u2/76292/showart_1389406.html">http://blog.chinaunix.net/u2/76292/showart_1389406.html</a>
<img src ="http://www.cppblog.com/beautykingdom/aggbug/102677.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2009-12-06 23:35 <a href="http://www.cppblog.com/beautykingdom/archive/2009/12/06/102677.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>微软面试中简单的算法题目(转)</title><link>http://www.cppblog.com/beautykingdom/archive/2009/12/06/102675.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Sun, 06 Dec 2009 15:31:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2009/12/06/102675.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/102675.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2009/12/06/102675.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/102675.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/102675.html</trackback:ping><description><![CDATA[（说明：这些题就不是什么花样了，考的是你的基础知识怎么样。再聪明而没有实学的人都将会被这些题所淘汰。）&nbsp; <br>1.链表和数组的区别在哪里？ <br><br>ANSWER 主要在基本概念上的理解。但是最好能考虑的全面一点，现在公司招人的竞争可能就在细节上产生，谁比较仔细，谁获胜的机会就大。<br><br>1）数组在内存中是逐个存放的，也就是说倘若数组的第一个元素在地址A,则数组第二个元素就在地址A+1。而链表则不是，链表每个节点没有相对固定的位置关系。某个节点在地址A其后的节点不一定是A+1,而在内存的其他空闲区域，呈现一种随机的状态。<br><br>2）数组一旦显式的被申明后，其大小就固定了，不能动态进行扩充。而链表则可以，可以动态生成节点并且添加到已有的链表后面。<br><br>3) &#8230;&#8230; （大家一起想想）<br><br>&nbsp;<br><br>2.编写实现链表排序的一种算法。说明为什么你会选择用这样的方法？<br><br>ANSWER 链表通常是插入排序,为什么呢？在数组中插入排序实现时会大量的移动数据从而删除位置不正确的元素，这是顺序表删除操作的低效性。从数学的角度，顺序表 （即数组）的删除操作是O(n).链表就不同，由于其存储位置的不固定性，其删除固定位置的元素只需要O(1)的时间，所以整体性能上获得比较大的提高。<br><br>&nbsp;<br><br>3.编写实现数组排序的一种算法。说明为什么你会选择用这样的方法？ <br><br>ANSWER 排序算法非常成熟了，实际上排序是研究算法的很有效例子。回答的时候尽量找一些比较有技术性的算法，比如堆排序或者快速排序，如果写冒泡什么的，别人都会 写，也就显示不出你的优秀了。当然一定要注意给定的条件。不至于三个数让你排序，你搞个快排，这就有点&#8220;宰牛刀杀鸡&#8221;了。<br><br>&nbsp;<br><br>4.请编写能直接实现strstr()函数功能的代码。 <br><br>ANSWER 首先要知道strstr()这个函数是干什么的，自己去查查C语言的书，一般附录后面会给出C语言标准库的。这个题目实际上也是一类重要的算法门类，叫做 &#8220;字符串的模式匹配&#8221;。它有很多的现成算法，其中最简单的要数朴素的匹配算法，还有KMP,BM这些高级算法，笔试估计是来不及写的。下面给出朴素的匹配 算法。<br><br>int stringMatching(char* pattern,char* text)<br><br>{<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int pLen = strlen(pattern),tLen = strlen(text);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for(int i = 0;i &lt;= tLen - pLen;i++){<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for(int j = 0; pattern[j] == text[i + j];j++);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(j == pLen) return i;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return -1; // Not found<br><br>}<br><br>&nbsp;<br><br>&nbsp;<br><br>5.编写反转字符串的程序，要求优化速度、优化空间。 <br><br>ANSWER:循环当然是最简单的。<br><br>void reverseString(char* str)<br><br>{<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int n = strlen(str);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for(int i = 0;i &lt; n/2;i++)<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {int t = str[i];str[i] = str[n - i - 1];str[n - i - 1] = t;}<br><br>}<br><br>&nbsp;<br><br>6.在链表里如何发现循环链接？ <br><br>ANSWER: 显然只需要判断是否存在回溯指针就行了。判断，是否存在某个节点的后继指向其前面位置的指针。具体实现的时候可以模仿DFS中的访问标志数组的方法，我们可以在struct node中设计该节点的一个访问标志位，设为visited 。每访问一个节点就将其visited域置为1。这样的话，一次遍历下来，如果发现某个后续节点的visited域已经是1，那么就可以判定其存在循环链接。具体的代码就不写了，太简单了。<br><span class="Apple-style-span" style="border-collapse: separate; color: #000000; font-family: Simsun; font-style: normal; font-variant: normal; font-weight: normal; letter-spacing: normal; line-height: normal; orphans: 2; text-indent: 0px; text-transform: none; white-space: normal; widows: 2; word-spacing: 0px; font-size: medium;"><span class="Apple-style-span" style="border-collapse: collapse; font-family: song,Verdana; font-size: 12px;">
<p style="font-family: song,Verdana; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none;"><font color="#003366" size="3">bool findloop(node *head)</font></p>
<p style="font-family: song,Verdana; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none;"><font color="#003366" size="3">&nbsp;{ node *pf=head;</font></p>
<p style="font-family: song,Verdana; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none;"><font color="#003366" size="3">&nbsp;&nbsp; node *ps=head-&gt;next;</font></p>
<p style="font-family: song,Verdana; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none;"><font color="#003366" size="3">&nbsp;&nbsp; while(pf!=NULL&amp;&amp;ps!=NULL&amp;&amp;pf-&gt;next!=NULL&amp;&amp;ps-&gt;next!=NULL)</font></p>
<p style="font-family: song,Verdana; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none;"><font color="#003366" size="3">&nbsp;&nbsp; { pf=pf-&gt;next;</font></p>
<p style="font-family: song,Verdana; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none;"><font color="#003366" size="3">&nbsp;&nbsp;&nbsp;&nbsp; ps=ps-&gt;next-&gt;next;</font></p>
<p style="font-family: song,Verdana; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none;"><font color="#003366" size="3">&nbsp;&nbsp;&nbsp;&nbsp; if(pf==ps)return true;</font></p>
<p style="font-family: song,Verdana; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none;"><font color="#003366" size="3">&nbsp;&nbsp; }</font></p>
<p style="font-family: song,Verdana; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none;"><font color="#003366" size="3">return false;</font></p>
<p style="font-family: song,Verdana; font-style: normal; font-variant: normal; font-weight: normal; font-size: 12px; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none;"><font color="#003366" size="3">&nbsp;}</font></p>
</span></span><br>7.写一个函数，检查字符是否是整数，如果是，返回其整数值。（或者：怎样只用4行代码编写出一个从字符串到长整形的函数？）<br><br>分析 ：简单！扫描一遍，每次生成对应整数的最高位。一行也就搞定了！<br><br>long convert(char* s_string,long s_integer)<br><br>{<br><br>for(int sLen = strlen(s_string), i = 0; i &lt; sLen;s_integer += (s_string[i++] - '0')*pow(10,sLen - i - 1));<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return s_integer;<br><br>}<br><br>&nbsp;<br><br>8.给出一个函数来输出一个字符串的所有排列。<br><br>ANSWER 简单的回溯就可以实现了。当然排列的产生也有很多种算法，去看看组合数学，还有逆序生成排列和一些不需要递归生成排列的方法。印象中Knuth的&lt; TAOCP&gt;第一卷里面深入讲了排列的生成。这些算法的理解需要一定的数学功底，也需要一定的灵感，有兴趣最好看看。<br><br>void permStr(char* str,int i)<br><br>{<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(i == strlen(str) - 1)<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("%s\n",str);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for(int j = i;j &lt; strlen(str);j++)<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; {<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; swap(&amp;str[i],&amp;str[j]);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; permStr(str,i + 1);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; swap(&amp;str[i],&amp;str[j]);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br><br>}<br><br>&nbsp;<br><br>9.给出一个函数来复制两个字符串A和B。字符串A的后几个字节和字符串B的前几个字节重叠。<br><br>anSwer&nbsp; 记住，这种题目往往就是考你对边界的考虑情况。编程除了技术上的熟练以外，细心也是非常重要的。其实很多编程的大师可能并不是有特别的技术，往往就是他们 非常的耐心和细心，记住：编程是计算机科学中最基本的工作，它是最容易去掌握的，耐心点，细心点你一定能够学好它。代码看下面：<br><br>char* myStrcpy(char* s,char* a,char* b,char n)<br><br>{<br><br>int aLen = strlen(a),bLen = strlen(b);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(n &gt; aLen || n &gt; bLen)<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return NULL; // Error <br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for(int i = 0;i &lt; aLen + bLen - n;i++)<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(i &lt; aLen - n) s[i] = a[i];<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else s[i] = b[i - aLen + n];<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; s[i] = '\0';<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return s;<br><br>}<br><br>&nbsp;<br><br>10.怎样编写一个程序，把一个有序整数数组放到二叉树中？ <br><br>ANSWER :二叉搜索树的建树方法。简单的递归结构。实在不理解，干脆记下来好了。关于树的算法设计一定要联想到递归，因为树本身就是递归的定义。这里的递归应该是 理所当然的吧，不过，学会把递归改称非递归也是一种必要的技术。毕竟，递归会造成栈溢出，关于系统底层的程序中不到非不得以最好不要用。但是对某些数学问 题，就一定要学会用递归去解决。<br><br>void insertNode(bTree** root,int val)<br><br>{ <br><br>&nbsp;&nbsp;&nbsp; bTree* newNode = (bTree* ) malloc(sizeof(bTree));<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; newNode-&gt;data = val;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; newNode-&gt;lChild = NULL;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; newNode-&gt;rChild = NULL;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(!(*root)) <br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; *root = newNode;<br><br>&nbsp;&nbsp;&nbsp; else if(newNode-&gt;data &lt; (*root)-&gt;data)<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; insertNode(&amp;(*root)-&gt;lChild,val);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; insertNode(&amp;(*root)-&gt;rChild,val);&nbsp;&nbsp; <br><br>}<br><br>&nbsp;<br><br>11.怎样从顶部开始逐层打印二叉树结点数据？请编程。 <br><br>ANSWER 二叉树的层次遍历没什么好说的，如果你不会还是早点把基础复习一下。一个劲的往后学，才会发现原来最最重要的还是以前最基础最简单的。<br><br>typedef struct myBinaryTree<br><br>{<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int data;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct myBinaryTree* lChild;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct myBinaryTree* rChild;<br><br>} bTree;<br><br>&nbsp;<br><br>struct myQueen<br><br>{<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bTree* que[QSIZE];<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int front;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int rear;<br><br>} binQueue; // Global var<br><br>&nbsp;<br><br>void initQueue()<br><br>{<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; // front == real makes the queue empty<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; binQueue.rear = QSIZE - 1;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; binQueue.front = binQueue.rear;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; for(int i = 0;i &lt; QSIZE;i++)<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; binQueue.que[i] = NULL;<br><br>}<br><br>&nbsp;<br><br>int enQueue(bTree* newNode)<br><br>{<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(binQueue.front &gt;= 1)<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; binQueue.que[binQueue.front--] = newNode;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else return 0;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 1;<br><br>}<br><br>&nbsp;<br><br>bTree* deQueue()<br><br>{<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int t;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(binQueue.front != binQueue.rear){<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; t = binQueue.rear;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; binQueue.rear--;<br><br>&nbsp;&nbsp;&nbsp; return binQueue.que[t];<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; else return NULL;<br><br>}<br><br>int levelTraversal(bTree** root)<br><br>{<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; initQueue();<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bTree* lc = (bTree* ) malloc(sizeof(bTree));<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bTree* rc = (bTree* ) malloc(sizeof(bTree));<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; bTree* p = (bTree* ) malloc(sizeof(bTree));<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if((!lc) || (!rc) || (!p)){<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("OVERFLOW\n");<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; exit(OVERFLOW); // Allocation Error<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p = *root;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(!p) { <br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("Empty Tree,build it first !\n");<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; enQueue(p); // enqueue the root of the tree<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while (binQueue.front != binQueue.rear){<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p = deQueue();<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("%d ",p-&gt;data);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; lc = p-&gt;lChild;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; rc = p-&gt;rChild;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(lc != NULL) <br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; enQueue(lc);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(rc != NULL)<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; enQueue(rc);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; } <br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("\n");<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 1;<br><br>}<br><br>&nbsp;<br><br>12.怎样把一个链表掉个顺序（也就是反序，注意链表的边界条件并考虑空链表）？<br><br>ANSWER 前面说了，最基本的是最重要的。线性数据结构是学习数据结构的入门，一定要掌握好。微软的题目还是跟国内的公司不一样。国内的一上来就是些概念，跟考历史一样。<br><br>typedef struct listNode<br><br>{<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; struct listNode* link;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int data;<br><br>}node;<br><br>&nbsp;<br><br>node* getNode(node* newNode,int val)<br><br>{<br><br>&nbsp;&nbsp;&nbsp; if(!newNode)<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; exit(OVERFLOW);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; newNode-&gt;link = NULL;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; newNode-&gt;data = val;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return newNode;<br><br>}<br><br>/* <br><br>&nbsp; Insert a new node after p <br><br>*/<br><br>int insertNode(node* prev,node* newNode)<br><br>{<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(!prev) return 0;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; newNode-&gt;link = prev-&gt;link;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; prev-&gt;link = newNode;<br><br>&nbsp;&nbsp;&nbsp; return 1;<br><br>}<br><br>/*<br><br>&nbsp;delete the node after the node prev<br><br>*/<br><br>int eraseNode(node*prev,node* p)<br><br>{<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(p == NULL)<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; prev-&gt;link = p-&gt;link;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; free(p);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 1;<br><br>}<br><br>void buildList(node* head)<br><br>{<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; int value;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; node* newNode = (node* ) malloc(sizeof(node));<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; node* p = head;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; scanf("%d",&amp;value);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while(value != -1){<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; newNode = getNode(newNode,value);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; insertNode(p,newNode);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p = p-&gt;link;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; newNode = (node* ) malloc(sizeof(node));<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; scanf("%d",&amp;value);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br><br>}<br><br>&nbsp;<br><br>int reverseList(node* head)<br><br>{<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; node* p = head-&gt;link;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; node* q = p-&gt;link;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; if(p == NULL){<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("The list is empty!\n");<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 0;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; while(q != NULL){<br><br>&nbsp;&nbsp;&nbsp; node* newNode = (node* ) malloc(sizeof(node));<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; newNode = getNode(newNode,q-&gt;data);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; insertNode(head,newNode);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; eraseNode(p,q);<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; q = (node* ) malloc(sizeof(node)); // Allocate again<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; q = p-&gt;link;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p-&gt;link = NULL;<br><br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; return 1;<br><br>}<br><br>http://blog.chinaunix.net/u2/76292/showart_1388527.html
<br><br> <img src ="http://www.cppblog.com/beautykingdom/aggbug/102675.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2009-12-06 23:31 <a href="http://www.cppblog.com/beautykingdom/archive/2009/12/06/102675.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>大整数的乘法运算－C语言版（转）</title><link>http://www.cppblog.com/beautykingdom/archive/2009/12/06/102674.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Sun, 06 Dec 2009 15:26:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2009/12/06/102674.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/102674.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2009/12/06/102674.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/102674.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/102674.html</trackback:ping><description><![CDATA[ 在计算机中，长整型(long int)变量的范围是 -2147483648 至 2147483647，因此若用长整型变量做乘法运算，乘积最多不能超过 10位数。即便用双精度型(double)变量，也仅能保证 16 位有效数字的精度。在某些需要更高精度的乘法运算的场合，需要用别的办法来实现乘法运算。
    比较容易想到的是做多位数乘法时列竖式进行计算的方法，只要写出模拟这一过程的程序，就能实现任意大整数的乘法运算。经过查阅资料，找到一种更易于编程的方法，即&#8220;列表法&#8221;。
 
下面先介绍&#8220;列表法&#8221;：
例如当计算8765 x 234时，把乘数与被乘数照如下列出，见表1：
 
8 7 6 5 8765
     2 16 14 12 10 2
     3 24 21 18 15 3
     4 32 28 24 20 4
                表 1 表 2
 
    把每个空格所在的行列的数字的乘积填入空格中，得表2。把表2中的数按图示斜线分组（横纵坐标和相等的数分为一组），把每组数的累加起来所得的和记在表格下方，见表 3：

16 14 12 10
   24 21 18 15
      32 28 24 20

16 38 65 56 39 20
 表 3 

    最后把表格下方一行数作如下处理，见表4：
    从最低位的 20 开始，保留个位数字&#8220;0&#8221;，把个位以外的数&#8220;2&#8221;进到前一位；把次低位的 39 加上低位进上来的 2 得 41，保留个位数字&#8220;1&#8221;，把&#8220;4&#8221;进到前一位；以此类推，直至最高位的 16，16 加上低位进上来的4得 20，保留&#8220;0&#8221;，把2进到最高位，得乘积答数 2051010。 
  16 38 65 56 39 20
2 16+4=20 38+7=45 65+6=71 56+4=60 39+2=41 
   留0进2 留5进4 留1进7 留0进6 留1进4 留0进2
2 0 5 1 0 1 0 
 表 4 
    根据以上思路就可以编写C 程序了，再经分析可得：
  1、一个m 位的整数与一个 n 位的整数相乘，乘积为m+n-1 位或m+n 位。
  2、程序中，用三个字符数组分别存储乘数、被乘数与乘积。由第 1 点分析知，存放乘积的字符数组
的长度应不小于存放乘数与被乘数的两个数组的长度之和。
  3、可以把第二步&#8220;计算填表&#8221;与第三四步&#8220;累加进位&#8221;放在一起完成，可以节省存储表格 2所需的空间。
  4、程序关键部分是两层循环，内层循环累计一组数的和，外层循环处理保留的数字与进位。
 
 
编写的程序如下：
程序 1 清单：
/* multiply.c */
/* 11/20/2008 */
#define MAXLENGTH 1000
#include <stdio.h>
#include <string.h>
 
void compute(char *a, char *b, char *c);
 
void main(void)
{
    char a[MAXLENGTH], b[MAXLENGTH], c[MAXLENGTH * 2];
 
    puts("Input multiplier :");
    gets(a);
    puts("Input multiplicand :");
    gets(b);
 
    compute(a, b, c);
 
    puts("Answer :");
    puts(c);
    getchar();
}
 
void compute(char *a, char *b, char *c)
{
    int i, j, m, n;
    long sum, carry;
 
    m = strlen(a) - 1;
    n = strlen(b) - 1;
    for (i = m; i >= 0; i--)
        a[i] -= '0';
    for (i = n; i >= 0; i--)
        b[i] -= '0';
    c[m + n + 2] = '\0';
 
    carry = 0;
    for (i = m + n; i >= 0; i--) /* i 为坐标和 */
    {
        sum = carry;
 
        if ((j = i - m) < 0)
            j = 0;
        for ( ; j<=i && j<=n; j++) /* j 为纵坐标 */
            sum += a[i-j] * b[j]; /* 累计一组数的和 */
 
        c[i + 1] = sum % 10 + '0'; /* 算出保留的数字 */
        carry = sum / 10; /* 算出进位 */
 
    }
 
    if ((c[0] = carry+'0') == '0') /* if no carry, */
        c[0] = '\040'; /* c[0] equals to space */
}
 
 
效率分析：用以上算法计算 m位整数乘以n 位整数，需要先进行 m x n次乘法运算，再进行约 m
+ n次加法运算和 m + n次取模运算(实为整数除法)。把这个程序稍加修改，让它自己产生乘数与被乘
数，然后计算随机的 7200位整数互乘，在Cyrix 6x86 pr166机器的纯DOS方式下耗时 7秒(用Borland C
3.1编译)。
 
经过改进，此算法效率可以提高约9 倍。
注意到以下事实：8216547 x 96785 将两数从个位起，每 3位分为节，列出乘法表，将斜线间的
数字相加；

 8 216 547 
    96 785

 768 20736 52512
      6280 169560 429395
 
 768 27016 222072 429395

将表中最后一行进行如下处理：从个位数开始，每一个方格里只保留三位数字，超出 1000 的部
分进位到前一个方格里；
 
 768 27016 222072 429395
 768+27 27016+222 222072+429
 =795 =27238 =222501 395
 795 238 501 395
 
所以8216547 x 96785 = 795238501395
 
也就是说我们在计算生成这个二维表时，不必一位一位地乘，而可以三位三位地乘；在累加时也是满1000进位。这样，我们在计算 m位整数乘以 n位整数，只需要进行 m x n / 9次乘法运算，再进行约(m + n) / 3次加法运算和(m + n) /3 次取模运算。总体看来，效率约是前一种算法的 9倍。
有人可能会想：既然能够三位三位地乘，为什么不4位 4位甚至5位5位地乘呢？那不是可以提高 16 乃至 25 倍效率吗？听我解来：本算法在累加表中斜线间的数字时，如果用无符号长整数(范围 0至~4294967295)作为累加变量，在最不利的情况下(两个乘数的所有数字均是 9)，能够累加约4294967295/(999*999)=4300 次，也就是能够准确计算任意两个均不超过 12900(每次累加的结果"值"三位，故 4300*3=12900)位的整数相乘。如果 4 位 4 位地乘，在最不利的情况下，能够累加约4294967295/(9999*9999)=43 次，仅能够确保任意两个不超过 172 位的整数相乘，没有什么实用价值，更不要说5位了。
 
请看改进后的算法的实例程序：
该程序随机产生两个72xx位的整数，把乘数与积保存在 result.txt中。
在Borland C++ 3.1 中用
BCC -3 -O2 -G -mh -Z -f287 -pr -T- dashu.cpp
编译生成的exe文件在Cyrix 6x86 pr166的机器上运行耗时0.82 秒。
 
 
 
 
程序 2 清单：
#include<conio.h>
#include<string.h>
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#define N 7200 //作 72xx 位的整数乘法

int max(int,int,int);
int initarray(int a[]);
void write(int a[],int l);
FILE *fp;
 
void main()
{
    int a[5000]={0},b[5000]={0},k[10001]={0}; //声明存放乘数、被乘数与积的数组

    clock_t start, end; //声明用于计时的变量

    unsigned long c,d,e; //声明作累加用的无符号长整数变量

    int i,j,la,lb,ma,mi,p,q,t; //声明其它变量

    randomize(); //初始化随机数

 
    la=initarray(a); //产生被乘数，并返回其长度

    lb=initarray(b); //产生乘数，并返回其长度

 
    if(la<lb) //如果被乘数长度小于乘数，则交换被乘数与乘数

    {
        p=(lb>la)?lb:la;
        for (q=0;q<p;q++) //交换被乘数与乘数

        t=a[q],a[q]=b[q],b[q]=t;
        t=la,la=lb,lb=t; //交换被乘数的长度与乘数的长度

    }
 
    start = clock();//开始计时

    c=d=0; //清空累加变量，其中 C 用于累加斜线间的数，d 用作进位标志

    for(i=la+lb-2;i>=0;i--) //累加斜线间的数，i 为横纵坐标之和

    {
        c=d; //将前一位的进位标志存入累加变量 c

        ma=max(0,i-la+1,i-lb+1); //求累加的下限

        mi=(i>la-1)?(la-1):i; //求累加的上限

        for(j=ma;j<=mi;j++) //计算出横纵坐标之和为 i 的单元内的数,并累加到 C 中

            c+=(long)a[j]*b[i-j];
        d=c/1000; //求进位标志

        if(c>999)
            c%=1000; //取 c 的末三位

        k[i]=c; //保存至表示乘积的数组 k[]

    }
    e=k[0]+1000*d; //求出乘积的最高位

    end = clock();//停止计时

    fp = fopen("result.txt", "w+"); //保存结果到 result.txt

    printf("\nThe elapsed time was: %3.4f\n", (end - start) / CLK_TCK);
    //打印消耗的时间

    fprintf(fp,"%d",a[0]); //打印被乘数最高位

    write(a,la); //打印被乘数其他位

    fprintf(fp,"%d",b[0]); //打印乘数最高位

    write(b,lb); //打印乘数其他位

    fprintf(fp,"%ld",e); //打印乘积最高位

    write(k,la+lb-1); //打印乘积其他位

    fclose(fp);
}

max(int a,int b,int c)
{
    int d;
    d=(a>b)?a:b;
    return (d>c)?d:c;
}
 
int initarray(int a[])
{
    int q,p,i;
    q=N+random(100);
    if(q%3==0)
        p=q/3;
    else
        p=q/3+1;
   
    for(i=0;i<p;i++)
        a[i]=random(1000);
   
    if(q%3==0)
        a[0]=100+random(900);
    if(q%3==2)
        a[0]=10+random(90);
    if(q%3==1)
        a[0]=1+random(9);
   
    return p;
}
 
void write(int a[],int l)
{
    int i;
    char string[10];
    for(i=1;i<l;i++)
    {
        itoa(a[i],string,10);
        if (strlen(string)==1)
            fprintf(fp,"00");
        if (strlen(string)==2)
            fprintf(fp,"0");
        fprintf(fp,"%s",string);
        if((i+1)%25==0)
            fprintf(fp,"\n");
    }
    fprintf(fp,"\n");
    fprintf(fp,"\n");
}

http://blog.chinaunix.net/u2/76292/showart_1661979.html<img src ="http://www.cppblog.com/beautykingdom/aggbug/102674.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2009-12-06 23:26 <a href="http://www.cppblog.com/beautykingdom/archive/2009/12/06/102674.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>小算法题</title><link>http://www.cppblog.com/beautykingdom/archive/2009/12/05/102634.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Sat, 05 Dec 2009 15:32:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2009/12/05/102634.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/102634.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2009/12/05/102634.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/102634.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/102634.html</trackback:ping><description><![CDATA[<p>A厂有1万个工人，编号0-9999，( EE[10000] ),&nbsp; 1个厂长( GG )分派任务,&nbsp; 1个监工( MM )管理工人. <br>厂子忙的时间不确定,可能突然很忙,1天接到任务5000多个,1个任务只能分配给1个工人做, 也可能好几十天没新任务. </p>
<p>厂长分配任务给这1万个工人干，按工人编号一个一个来，到最后一个工人就又从头开始，任务完成时间各不相同， <br>可能一个工人在分配任务的时候手里还有任务， 就得换下一个。 </p>
<p>但是这1万个工人都很懒，领到了任务先不做，需要监工1个1个去问，如果工人有任务，就做，如果工人没任务，则不做。&nbsp; <br>厂长只管分任务，1个1个来，可能几天也没新任务，不累；&nbsp; <br>但是监工很累，监工每天都要看所有工人的情况，即使这些工人都没有任务, 实际上每天工人（80%左右）是没任务的， <br>请问，怎么让监工的工作轻松下来. 比如说每天只问1小半工人.</p>
有个想法：<br>厂头从(0-9999)依次分配任务．有一个第一次分配的标志 <br>监工每天依次20%左右的人头催工．每天收工记录当天收工点．首轮时如果不到20%遇到第一个无工作的人，则记录下当前工人．明天从此点开始催工．
<img src ="http://www.cppblog.com/beautykingdom/aggbug/102634.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2009-12-05 23:32 <a href="http://www.cppblog.com/beautykingdom/archive/2009/12/05/102634.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>讲解排序算法C语言实现</title><link>http://www.cppblog.com/beautykingdom/archive/2009/11/23/101741.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Mon, 23 Nov 2009 13:27:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2009/11/23/101741.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/101741.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2009/11/23/101741.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/101741.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/101741.html</trackback:ping><description><![CDATA[<table style="BORDER-COLLAPSE: collapse; WORD-WRAP: break-word" border=0 cellSpacing=0 cellPadding=0 width="100%">
    <tbody>
        <tr>
            <td height=25 align=middle><font style="FONT-SIZE: 14pt" color=#02368d><strong>各种排序算法</strong></font></strong></font><br></td>
        </tr>
        <tr>
            <td bgColor=#d2dee2 height=1></td>
        </tr>
        <tr>
            <td bgColor=#ffffff height=1></td>
        </tr>
        <tr>
            <td align=middle>
            <table style="BORDER-COLLAPSE: collapse; WORD-WRAP: break-word" border=0 cellSpacing=0 cellPadding=0 width="100%">
                <tbody>
                    <tr>
                        <td width="100%">
                        <div style="MARGIN: 15px" id=art width="100%">另外连接：http://blog.csdn.net/fly_lb/category/368127.aspx <br>排序算法是一种基本并且常用的算法。由于实际工作中处理的数量巨大，所以排序算法 <br>对算法本身的速度要求很高。 <br>&nbsp;&nbsp;而一般我们所谓的算法的性能主要是指算法的复杂度，一般用O方法来表示。在后面我将 <br>给出详细的说明。 <br><br>&nbsp;&nbsp;对于排序的算法我想先做一点简单的介绍，也是给这篇文章理一个提纲。 <br>&nbsp;&nbsp;我将按照算法的复杂度，从简单到难来分析算法。 <br>&nbsp;&nbsp;第一部分是简单排序算法，后面你将看到他们的共同点是算法复杂度为O(N*N)（因为没有 <br>使用word,所以无法打出上标和下标）。 <br>&nbsp;&nbsp;第二部分是高级排序算法，复杂度为O(Log2(N))。这里我们只介绍一种算法。另外还有几种 <br>算法因为涉及树与堆的概念，所以这里不于讨论。 <br>&nbsp;&nbsp;第三部分类似动脑筋。这里的两种算法并不是最好的（甚至有最慢的），但是算法本身比较 <br>奇特，值得参考（编程的角度）。同时也可以让我们从另外的角度来认识这个问题。 <br>&nbsp;&nbsp;第四部分是我送给大家的一个餐后的甜点——一个基于模板的通用快速排序。由于是模板函数 <br>可以对任何数据类型排序（抱歉，里面使用了一些论坛专家的呢称）。 <br>&nbsp;&nbsp; <br>&nbsp;&nbsp;现在，让我们开始吧： <br>&nbsp;&nbsp; <br>一、简单排序算法 <br>由于程序比较简单，所以没有加什么注释。所有的程序都给出了完整的运行代码，并在我的VC环境 <br>下运行通过。因为没有涉及MFC和WINDOWS的内容，所以在BORLAND C++的平台上应该也不会有什么 <br>问题的。在代码的后面给出了运行过程示意，希望对理解有帮助。 <br><br>1.冒泡法： <br>这是最原始，也是众所周知的最慢的算法了。他的名字的由来因为它的工作看来象是冒泡： <br>#include &lt;iostream.h&gt; <br><br>void BubbleSort(int* pData,int Count) <br>{ <br>&nbsp;&nbsp;int iTemp; <br>&nbsp;&nbsp;for(int i=1;i&lt;Count;i++) <br>&nbsp;&nbsp;{ <br>&nbsp;&nbsp;&nbsp;&nbsp;for(int j=Count-1;j&gt;=i;j--) <br>&nbsp;&nbsp;&nbsp;&nbsp;{ <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(pData[j]&lt;pData[j-1]) <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iTemp = pData[j-1]; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pData[j-1] = pData[j]; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pData[j] = iTemp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} <br>&nbsp;&nbsp;&nbsp;&nbsp;} <br>&nbsp;&nbsp;} <br>} <br><br>void main() <br>{ <br>&nbsp;&nbsp;int data[] = {10,9,8,7,6,5,4}; <br>&nbsp;&nbsp;BubbleSort(data,7); <br>&nbsp;&nbsp;for (int i=0;i&lt;7;i++) <br>&nbsp;&nbsp;&nbsp;&nbsp;cout&lt;&lt;data[i]&lt;&lt;" "; <br>&nbsp;&nbsp;cout&lt;&lt;"\n"; <br>} <br><br>倒序(最糟情况) <br>第一轮：10,9,8,7-&gt;10,9,7,8-&gt;10,7,9,8-&gt;7,10,9,8(交换3次) <br>第二轮：7,10,9,8-&gt;7,10,8,9-&gt;7,8,10,9(交换2次) <br>第一轮：7,8,10,9-&gt;7,8,9,10(交换1次) <br>循环次数：6次 <br>交换次数：6次 <br><br>其他： <br>第一轮：8,10,7,9-&gt;8,10,7,9-&gt;8,7,10,9-&gt;7,8,10,9(交换2次) <br>第二轮：7,8,10,9-&gt;7,8,10,9-&gt;7,8,10,9(交换0次) <br>第一轮：7,8,10,9-&gt;7,8,9,10(交换1次) <br>循环次数：6次 <br>交换次数：3次 <br><br>上面我们给出了程序段，现在我们分析它：这里，影响我们算法性能的主要部分是循环和交换， <br>显然，次数越多，性能就越差。从上面的程序我们可以看出循环的次数是固定的，为1+2+...+n-1。 <br>写成公式就是1/2*(n-1)*n。 <br>现在注意，我们给出O方法的定义： <br><br>&nbsp;&nbsp;若存在一常量K和起点n0，使当n&gt;=n0时，有f(n)&lt;=K*g(n),则f(n) = O(g(n))。（呵呵，不要说没 <br>学好数学呀，对于编程数学是非常重要的！！！） <br><br>现在我们来看1/2*(n-1)*n，当K=1/2，n0=1，g(n)=n*n时，1/2*(n-1)*n&lt;=1/2*n*n=K*g(n)。所以f(n) <br>=O(g(n))=O(n*n)。所以我们程序循环的复杂度为O(n*n)。 <br>再看交换。从程序后面所跟的表可以看到，两种情况的循环相同，交换不同。其实交换本身同数据源的 <br>有序程度有极大的关系，当数据处于倒序的情况时，交换次数同循环一样（每次循环判断都会交换）， <br>复杂度为O(n*n)。当数据为正序，将不会有交换。复杂度为O(0)。乱序时处于中间状态。正是由于这样的 <br>原因，我们通常都是通过循环次数来对比算法。 <br><br><br>2.交换法： <br>交换法的程序最清晰简单，每次用当前的元素一一的同其后的元素比较并交换。 <br>#include &lt;iostream.h&gt; <br>void ExchangeSort(int* pData,int Count) <br>{ <br>&nbsp;&nbsp;int iTemp; <br>&nbsp;&nbsp;for(int i=0;i&lt;Count-1;i++) <br>&nbsp;&nbsp;{ <br>&nbsp;&nbsp;&nbsp;&nbsp;for(int j=i+1;j&lt;Count;j++) <br>&nbsp;&nbsp;&nbsp;&nbsp;{ <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(pData[j]&lt;pData[i]) <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iTemp = pData[i]; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pData[i] = pData[j]; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pData[j] = iTemp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} <br>&nbsp;&nbsp;&nbsp;&nbsp;} <br>&nbsp;&nbsp;} <br>} <br><br>void main() <br>{ <br>&nbsp;&nbsp;int data[] = {10,9,8,7,6,5,4}; <br>&nbsp;&nbsp;ExchangeSort(data,7); <br>&nbsp;&nbsp;for (int i=0;i&lt;7;i++) <br>&nbsp;&nbsp;&nbsp;&nbsp;cout&lt;&lt;data[i]&lt;&lt;" "; <br>&nbsp;&nbsp;cout&lt;&lt;"\n"; <br>} <br>倒序(最糟情况) <br>第一轮：10,9,8,7-&gt;9,10,8,7-&gt;8,10,9,7-&gt;7,10,9,8(交换3次) <br>第二轮：7,10,9,8-&gt;7,9,10,8-&gt;7,8,10,9(交换2次) <br>第一轮：7,8,10,9-&gt;7,8,9,10(交换1次) <br>循环次数：6次 <br>交换次数：6次 <br><br>其他： <br>第一轮：8,10,7,9-&gt;8,10,7,9-&gt;7,10,8,9-&gt;7,10,8,9(交换1次) <br>第二轮：7,10,8,9-&gt;7,8,10,9-&gt;7,8,10,9(交换1次) <br>第一轮：7,8,10,9-&gt;7,8,9,10(交换1次) <br>循环次数：6次 <br>交换次数：3次 <br><br>从运行的表格来看，交换几乎和冒泡一样糟。事实确实如此。循环次数和冒泡一样 <br>也是1/2*(n-1)*n，所以算法的复杂度仍然是O(n*n)。由于我们无法给出所有的情况，所以 <br>只能直接告诉大家他们在交换上面也是一样的糟糕（在某些情况下稍好，在某些情况下稍差）。 <br><br>3.选择法： <br>现在我们终于可以看到一点希望：选择法，这种方法提高了一点性能（某些情况下） <br>这种方法类似我们人为的排序习惯：从数据中选择最小的同第一个值交换，在从省下的部分中 <br>选择最小的与第二个交换，这样往复下去。 <br>#include &lt;iostream.h&gt; <br>void SelectSort(int* pData,int Count) <br>{ <br>&nbsp;&nbsp;int iTemp; <br>&nbsp;&nbsp;int iPos; <br>&nbsp;&nbsp;for(int i=0;i&lt;Count-1;i++) <br>&nbsp;&nbsp;{ <br>&nbsp;&nbsp;&nbsp;&nbsp;iTemp = pData[i]; <br>&nbsp;&nbsp;&nbsp;&nbsp;iPos = i; <br>&nbsp;&nbsp;&nbsp;&nbsp;for(int j=i+1;j&lt;Count;j++) <br>&nbsp;&nbsp;&nbsp;&nbsp;{ <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(pData[j]&lt;iTemp) <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iTemp = pData[j]; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iPos = j; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} <br>&nbsp;&nbsp;&nbsp;&nbsp;} <br>&nbsp;&nbsp;&nbsp;&nbsp;pData[iPos] = pData[i]; <br>&nbsp;&nbsp;&nbsp;&nbsp;pData[i] = iTemp; <br>&nbsp;&nbsp;} <br>} <br><br>void main() <br>{ <br>&nbsp;&nbsp;int data[] = {10,9,8,7,6,5,4}; <br>&nbsp;&nbsp;SelectSort(data,7); <br>&nbsp;&nbsp;for (int i=0;i&lt;7;i++) <br>&nbsp;&nbsp;&nbsp;&nbsp;cout&lt;&lt;data[i]&lt;&lt;" "; <br>&nbsp;&nbsp;cout&lt;&lt;"\n"; <br>} <br>倒序(最糟情况) <br>第一轮：10,9,8,7-&gt;(iTemp=9)10,9,8,7-&gt;(iTemp=8)10,9,8,7-&gt;(iTemp=7)7,9,8,10(交换1次) <br>第二轮：7,9,8,10-&gt;7,9,8,10(iTemp=8)-&gt;(iTemp=8)7,8,9,10(交换1次) <br>第一轮：7,8,9,10-&gt;(iTemp=9)7,8,9,10(交换0次) <br>循环次数：6次 <br>交换次数：2次 <br><br>其他： <br>第一轮：8,10,7,9-&gt;(iTemp=8)8,10,7,9-&gt;(iTemp=7)8,10,7,9-&gt;(iTemp=7)7,10,8,9(交换1次) <br>第二轮：7,10,8,9-&gt;(iTemp=8)7,10,8,9-&gt;(iTemp=8)7,8,10,9(交换1次) <br>第一轮：7,8,10,9-&gt;(iTemp=9)7,8,9,10(交换1次) <br>循环次数：6次 <br>交换次数：3次 <br>遗憾的是算法需要的循环次数依然是1/2*(n-1)*n。所以算法复杂度为O(n*n)。 <br>我们来看他的交换。由于每次外层循环只产生一次交换（只有一个最小值）。所以f(n)&lt;=n <br>所以我们有f(n)=O(n)。所以，在数据较乱的时候，可以减少一定的交换次数。 <br><br><br>4.插入法： <br>插入法较为复杂，它的基本工作原理是抽出牌，在前面的牌中寻找相应的位置插入，然后继续下一张 <br>#include &lt;iostream.h&gt; <br>void InsertSort(int* pData,int Count) <br>{ <br>&nbsp;&nbsp;int iTemp; <br>&nbsp;&nbsp;int iPos; <br>&nbsp;&nbsp;for(int i=1;i&lt;Count;i++) <br>&nbsp;&nbsp;{ <br>&nbsp;&nbsp;&nbsp;&nbsp;iTemp = pData[i]; <br>&nbsp;&nbsp;&nbsp;&nbsp;iPos = i-1; <br>&nbsp;&nbsp;&nbsp;&nbsp;while((iPos&gt;=0) &amp;&amp; (iTemp&lt;pData[iPos])) <br>&nbsp;&nbsp;&nbsp;&nbsp;{ <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pData[iPos+1] = pData[iPos]; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iPos--; <br>&nbsp;&nbsp;&nbsp;&nbsp;} <br>&nbsp;&nbsp;&nbsp;&nbsp;pData[iPos+1] = iTemp; <br>&nbsp;&nbsp;} <br>} <br><br>void main() <br>{ <br>&nbsp;&nbsp;int data[] = {10,9,8,7,6,5,4}; <br>&nbsp;&nbsp;InsertSort(data,7); <br>&nbsp;&nbsp;for (int i=0;i&lt;7;i++) <br>&nbsp;&nbsp;&nbsp;&nbsp;cout&lt;&lt;data[i]&lt;&lt;" "; <br>&nbsp;&nbsp;cout&lt;&lt;"\n"; <br>} <br><br>倒序(最糟情况) <br>第一轮：10,9,8,7-&gt;9,10,8,7(交换1次)(循环1次) <br>第二轮：9,10,8,7-&gt;8,9,10,7(交换1次)(循环2次) <br>第一轮：8,9,10,7-&gt;7,8,9,10(交换1次)(循环3次) <br>循环次数：6次 <br>交换次数：3次 <br><br>其他： <br>第一轮：8,10,7,9-&gt;8,10,7,9(交换0次)(循环1次) <br>第二轮：8,10,7,9-&gt;7,8,10,9(交换1次)(循环2次) <br>第一轮：7,8,10,9-&gt;7,8,9,10(交换1次)(循环1次) <br>循环次数：4次 <br>交换次数：2次 <br><br>上面结尾的行为分析事实上造成了一种假象，让我们认为这种算法是简单算法中最好的，其实不是， <br>因为其循环次数虽然并不固定，我们仍可以使用O方法。从上面的结果可以看出，循环的次数f(n)&lt;= <br>1/2*n*(n-1)&lt;=1/2*n*n。所以其复杂度仍为O(n*n)（这里说明一下，其实如果不是为了展示这些简单 <br>排序的不同，交换次数仍然可以这样推导）。现在看交换，从外观上看，交换次数是O(n)（推导类似 <br>选择法），但我们每次要进行与内层循环相同次数的&#8216;=&#8217;操作。正常的一次交换我们需要三次&#8216;=&#8217; <br>而这里显然多了一些，所以我们浪费了时间。 <br><br>最终，我个人认为，在简单排序算法中，选择法是最好的。 <br><br><br>二、高级排序算法： <br>高级排序算法中我们将只介绍这一种，同时也是目前我所知道（我看过的资料中）的最快的。 <br>它的工作看起来仍然象一个二叉树。首先我们选择一个中间值middle程序中我们使用数组中间值，然后 <br>把比它小的放在左边，大的放在右边（具体的实现是从两边找，找到一对后交换）。然后对两边分别使 <br>用这个过程（最容易的方法——递归）。 <br><br>1.快速排序： <br>#include &lt;iostream.h&gt; <br><br>void run(int* pData,int left,int right) <br>{ <br>&nbsp;&nbsp;int i,j; <br>&nbsp;&nbsp;int middle,iTemp; <br>&nbsp;&nbsp;i = left; <br>&nbsp;&nbsp;j = right; <br>&nbsp;&nbsp;middle = pData[(left+right)/2];&nbsp;//求中间值 <br>&nbsp;&nbsp;do{ <br>&nbsp;&nbsp;&nbsp;&nbsp;while((pData[i]&lt;middle) &amp;&amp; (i&lt;right))//从左扫描大于中值的数 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;i++;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;while((pData[j]&gt;middle) &amp;&amp; (j&gt;left))//从右扫描大于中值的数 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;j--; <br>&nbsp;&nbsp;&nbsp;&nbsp;if(i&lt;=j)//找到了一对值 <br>&nbsp;&nbsp;&nbsp;&nbsp;{ <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//交换 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iTemp = pData[i]; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pData[i] = pData[j]; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pData[j] = iTemp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;i++; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;j--; <br>&nbsp;&nbsp;&nbsp;&nbsp;} <br>&nbsp;&nbsp;}while(i&lt;=j);//如果两边扫描的下标交错，就停止（完成一次） <br><br>&nbsp;&nbsp;//当左边部分有值(left&lt;j)，递归左半边 <br>&nbsp;&nbsp;if(left&lt;j) <br>&nbsp;&nbsp;&nbsp;&nbsp;run(pData,left,j); <br>&nbsp;&nbsp;//当右边部分有值(right&gt;i)，递归右半边 <br>&nbsp;&nbsp;if(right&gt;i) <br>&nbsp;&nbsp;&nbsp;&nbsp;run(pData,i,right); <br>} <br><br>void QuickSort(int* pData,int Count) <br>{ <br>&nbsp;&nbsp;run(pData,0,Count-1); <br>} <br><br>void main() <br>{ <br>&nbsp;&nbsp;int data[] = {10,9,8,7,6,5,4}; <br>&nbsp;&nbsp;QuickSort(data,7); <br>&nbsp;&nbsp;for (int i=0;i&lt;7;i++) <br>&nbsp;&nbsp;&nbsp;&nbsp;cout&lt;&lt;data[i]&lt;&lt;" "; <br>&nbsp;&nbsp;cout&lt;&lt;"\n"; <br>} <br><br>这里我没有给出行为的分析，因为这个很简单，我们直接来分析算法：首先我们考虑最理想的情况 <br>1.数组的大小是2的幂，这样分下去始终可以被2整除。假设为2的k次方，即k=log2(n)。 <br>2.每次我们选择的值刚好是中间值，这样，数组才可以被等分。 <br>第一层递归，循环n次，第二层循环2*(n/2)...... <br>所以共有n+2(n/2)+4(n/4)+...+n*(n/n) = n+n+n+...+n=k*n=log2(n)*n <br>所以算法复杂度为O(log2(n)*n) <br>其他的情况只会比这种情况差，最差的情况是每次选择到的middle都是最小值或最大值，那么他将变 <br>成交换法（由于使用了递归，情况更糟）。但是你认为这种情况发生的几率有多大？？呵呵，你完全 <br>不必担心这个问题。实践证明，大多数的情况，快速排序总是最好的。 <br>如果你担心这个问题，你可以使用堆排序，这是一种稳定的O(log2(n)*n)算法，但是通常情况下速度要慢 <br>于快速排序（因为要重组堆）。 <br><br>三、其他排序 <br>1.双向冒泡： <br>通常的冒泡是单向的，而这里是双向的，也就是说还要进行反向的工作。 <br>代码看起来复杂，仔细理一下就明白了，是一个来回震荡的方式。 <br>写这段代码的作者认为这样可以在冒泡的基础上减少一些交换（我不这么认为，也许我错了）。 <br>反正我认为这是一段有趣的代码，值得一看。 <br>#include &lt;iostream.h&gt; <br>void Bubble2Sort(int* pData,int Count) <br>{ <br>&nbsp;&nbsp;int iTemp; <br>&nbsp;&nbsp;int left = 1; <br>&nbsp;&nbsp;int right =Count -1; <br>&nbsp;&nbsp;int t; <br>&nbsp;&nbsp;do <br>&nbsp;&nbsp;{ <br>&nbsp;&nbsp;&nbsp;&nbsp;//正向的部分 <br>&nbsp;&nbsp;&nbsp;&nbsp;for(int i=right;i&gt;=left;i--) <br>&nbsp;&nbsp;&nbsp;&nbsp;{ <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(pData[i]&lt;pData[i-1]) <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iTemp = pData[i]; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pData[i] = pData[i-1]; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pData[i-1] = iTemp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t = i; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} <br>&nbsp;&nbsp;&nbsp;&nbsp;} <br>&nbsp;&nbsp;&nbsp;&nbsp;left = t+1; <br><br>&nbsp;&nbsp;&nbsp;&nbsp;//反向的部分 <br>&nbsp;&nbsp;&nbsp;&nbsp;for(i=left;i&lt;right+1;i++) <br>&nbsp;&nbsp;&nbsp;&nbsp;{ <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(pData[i]&lt;pData[i-1]) <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iTemp = pData[i]; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pData[i] = pData[i-1]; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pData[i-1] = iTemp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;t = i; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} <br>&nbsp;&nbsp;&nbsp;&nbsp;} <br>&nbsp;&nbsp;&nbsp;&nbsp;right = t-1; <br>&nbsp;&nbsp;}while(left&lt;=right); <br>} <br><br>void main() <br>{ <br>&nbsp;&nbsp;int data[] = {10,9,8,7,6,5,4}; <br>&nbsp;&nbsp;Bubble2Sort(data,7); <br>&nbsp;&nbsp;for (int i=0;i&lt;7;i++) <br>&nbsp;&nbsp;&nbsp;&nbsp;cout&lt;&lt;data[i]&lt;&lt;" "; <br>&nbsp;&nbsp;cout&lt;&lt;"\n"; <br>} <br><br><br>2.SHELL排序 <br>这个排序非常复杂，看了程序就知道了。 <br>首先需要一个递减的步长，这里我们使用的是9、5、3、1（最后的步长必须是1）。 <br>工作原理是首先对相隔9-1个元素的所有内容排序，然后再使用同样的方法对相隔5-1个元素的排序 <br>以次类推。 <br>#include &lt;iostream.h&gt; <br>void ShellSort(int* pData,int Count) <br>{ <br>&nbsp;&nbsp;int step[4]; <br>&nbsp;&nbsp;step[0] = 9; <br>&nbsp;&nbsp;step[1] = 5; <br>&nbsp;&nbsp;step[2] = 3; <br>&nbsp;&nbsp;step[3] = 1; <br><br>&nbsp;&nbsp;int iTemp; <br>&nbsp;&nbsp;int k,s,w; <br>&nbsp;&nbsp;for(int i=0;i&lt;4;i++) <br>&nbsp;&nbsp;{ <br>&nbsp;&nbsp;&nbsp;&nbsp;k = step[i]; <br>&nbsp;&nbsp;&nbsp;&nbsp;s = -k; <br>&nbsp;&nbsp;&nbsp;&nbsp;for(int j=k;j&lt;Count;j++) <br>&nbsp;&nbsp;&nbsp;&nbsp;{ <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iTemp = pData[j]; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;w = j-k;//求上step个元素的下标 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;if(s ==0) <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s = -k; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;s++; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pData[s] = iTemp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;while((iTemp&lt;pData[w]) &amp;&amp; (w&gt;=0) &amp;&amp; (w&lt;=Count)) <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{ <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pData[w+k] = pData[w]; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;w = w-k; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;} <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pData[w+k] = iTemp; <br>&nbsp;&nbsp;&nbsp;&nbsp;} <br>&nbsp;&nbsp;} <br>} <br><br>void main() <br>{ <br>&nbsp;&nbsp;int data[] = {10,9,8,7,6,5,4,3,2,1,-10,-1}; <br>&nbsp;&nbsp;ShellSort(data,12); <br>&nbsp;&nbsp;for (int i=0;i&lt;12;i++) <br>&nbsp;&nbsp;&nbsp;&nbsp;cout&lt;&lt;data[i]&lt;&lt;" "; <br>&nbsp;&nbsp;cout&lt;&lt;"\n"; <br>} <br>呵呵，程序看起来有些头疼。不过也不是很难，把s==0的块去掉就轻松多了，这里是避免使用0 <br>步长造成程序异常而写的代码。这个代码我认为很值得一看。 <br>这个算法的得名是因为其发明者的名字D.L.SHELL。依照参考资料上的说法：&#8220;由于复杂的数学原因 <br>避免使用2的幂次步长，它能降低算法效率。&#8221;另外算法的复杂度为n的1.2次幂。同样因为非常复杂并 <br>&#8220;超出本书讨论范围&#8221;的原因（我也不知道过程），我们只有结果了。 <br><br><br>四、基于模板的通用排序： <br>这个程序我想就没有分析的必要了，大家看一下就可以了。不明白可以在论坛上问。 <br>MyData.h文件 <br>/////////////////////////////////////////////////////// <br>class CMyData&nbsp; <br>{ <br>public: <br>&nbsp;&nbsp;CMyData(int Index,char* strData); <br>&nbsp;&nbsp;CMyData(); <br>&nbsp;&nbsp;virtual ~CMyData(); <br><br>&nbsp;&nbsp;int m_iIndex; <br>&nbsp;&nbsp;int GetDataSize(){ return m_iDataSize; }; <br>&nbsp;&nbsp;const char* GetData(){ return m_strDatamember; }; <br>&nbsp;&nbsp;//这里重载了操作符： <br>&nbsp;&nbsp;CMyData&amp; operator =(CMyData &amp;SrcData); <br>&nbsp;&nbsp;bool operator &lt;(CMyData&amp; data ); <br>&nbsp;&nbsp;bool operator &gt;(CMyData&amp; data ); <br><br>private: <br>&nbsp;&nbsp;char* m_strDatamember; <br>&nbsp;&nbsp;int m_iDataSize; <br>}; <br>//////////////////////////////////////////////////////// <br><br>MyData.cpp文件 <br>//////////////////////////////////////////////////////// <br>CMyData::CMyData(): <br>m_iIndex(0), <br>m_iDataSize(0), <br>m_strDatamember(NULL) <br>{ <br>} <br><br>CMyData::~CMyData() <br>{ <br>&nbsp;&nbsp;if(m_strDatamember != NULL) <br>&nbsp;&nbsp;&nbsp;&nbsp;delete[] m_strDatamember; <br>&nbsp;&nbsp;m_strDatamember = NULL; <br>} <br><br>CMyData::CMyData(int Index,char* strData): <br>m_iIndex(Index), <br>m_iDataSize(0), <br>m_strDatamember(NULL) <br>{ <br>&nbsp;&nbsp;m_iDataSize = strlen(strData); <br>&nbsp;&nbsp;m_strDatamember = new char[m_iDataSize+1]; <br>&nbsp;&nbsp;strcpy(m_strDatamember,strData); <br>} <br><br>CMyData&amp; CMyData::operator =(CMyData &amp;SrcData) <br>{ <br>&nbsp;&nbsp;m_iIndex = SrcData.m_iIndex; <br>&nbsp;&nbsp;m_iDataSize = SrcData.GetDataSize(); <br>&nbsp;&nbsp;m_strDatamember = new char[m_iDataSize+1]; <br>&nbsp;&nbsp;strcpy(m_strDatamember,SrcData.GetData()); <br>&nbsp;&nbsp;return *this; <br>} <br><br>bool CMyData::operator &lt;(CMyData&amp; data ) <br>{ <br>&nbsp;&nbsp;return m_iIndex&lt;data.m_iIndex; <br>} <br><br>bool CMyData::operator &gt;(CMyData&amp; data ) <br>{ <br>&nbsp;&nbsp;return m_iIndex&gt;data.m_iIndex; <br>} <br>/////////////////////////////////////////////////////////// <br><br>////////////////////////////////////////////////////////// <br>//主程序部分 <br>#include &lt;iostream.h&gt; <br>#include "MyData.h" <br><br>template &lt;class T&gt; <br>void run(T* pData,int left,int right) <br>{ <br>&nbsp;&nbsp;int i,j; <br>&nbsp;&nbsp;T middle,iTemp; <br>&nbsp;&nbsp;i = left; <br>&nbsp;&nbsp;j = right; <br>&nbsp;&nbsp;//下面的比较都调用我们重载的操作符函数 <br>&nbsp;&nbsp;middle = pData[(left+right)/2];&nbsp;//求中间值 <br>&nbsp;&nbsp;do{ <br>&nbsp;&nbsp;&nbsp;&nbsp;while((pData[i]&lt;middle) &amp;&amp; (i&lt;right))//从左扫描大于中值的数 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;i++;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; <br>&nbsp;&nbsp;&nbsp;&nbsp;while((pData[j]&gt;middle) &amp;&amp; (j&gt;left))//从右扫描大于中值的数 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;j--; <br>&nbsp;&nbsp;&nbsp;&nbsp;if(i&lt;=j)//找到了一对值 <br>&nbsp;&nbsp;&nbsp;&nbsp;{ <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;//交换 <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;iTemp = pData[i]; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pData[i] = pData[j]; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;pData[j] = iTemp; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;i++; <br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;j--; <br>&nbsp;&nbsp;&nbsp;&nbsp;} <br>&nbsp;&nbsp;}while(i&lt;=j);//如果两边扫描的下标交错，就停止（完成一次） <br><br>&nbsp;&nbsp;//当左边部分有值(left&lt;j)，递归左半边 <br>&nbsp;&nbsp;if(left&lt;j) <br>&nbsp;&nbsp;&nbsp;&nbsp;run(pData,left,j); <br>&nbsp;&nbsp;//当右边部分有值(right&gt;i)，递归右半边 <br>&nbsp;&nbsp;if(right&gt;i) <br>&nbsp;&nbsp;&nbsp;&nbsp;run(pData,i,right); <br>} <br><br>template &lt;class T&gt; <br>void QuickSort(T* pData,int Count) <br>{ <br>&nbsp;&nbsp;run(pData,0,Count-1); <br>} <br><br>void main() <br>{ <br>&nbsp;&nbsp;CMyData data[] = { <br>&nbsp;&nbsp;&nbsp;&nbsp;CMyData(8,"xulion"), <br>&nbsp;&nbsp;&nbsp;&nbsp;CMyData(7,"sanzoo"), <br>&nbsp;&nbsp;&nbsp;&nbsp;CMyData(6,"wangjun"), <br>&nbsp;&nbsp;&nbsp;&nbsp;CMyData(5,"VCKBASE"), <br>&nbsp;&nbsp;&nbsp;&nbsp;CMyData(4,"jacky2000"), <br>&nbsp;&nbsp;&nbsp;&nbsp;CMyData(3,"cwally"), <br>&nbsp;&nbsp;&nbsp;&nbsp;CMyData(2,"VCUSER"), <br>&nbsp;&nbsp;&nbsp;&nbsp;CMyData(1,"isdong") <br>&nbsp;&nbsp;}; <br>&nbsp;&nbsp;QuickSort(data,8); <br>&nbsp;&nbsp;for (int i=0;i&lt;8;i++) <br>&nbsp;&nbsp;&nbsp;&nbsp;cout&lt;&lt;data[i].m_iIndex&lt;&lt;"&nbsp;"&lt;&lt;data[i].GetData()&lt;&lt;"\n"; <br>&nbsp;&nbsp;cout&lt;&lt;"\n"; <br>} </div>
                        </td>
                    </tr>
                </tbody>
            </table>
            </td>
        </tr>
    </tbody>
</table>
<em>转自：<br><a href="http://blog.chinaunix.net/u/28584/showart.php?id=1211650">http://blog.chinaunix.net/u/28584/showart.php?id=1211650</a></em>
<img src ="http://www.cppblog.com/beautykingdom/aggbug/101741.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2009-11-23 21:27 <a href="http://www.cppblog.com/beautykingdom/archive/2009/11/23/101741.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>单链表和双链表的倒序 </title><link>http://www.cppblog.com/beautykingdom/archive/2009/11/21/101567.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Sat, 21 Nov 2009 10:41:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2009/11/21/101567.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/101567.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2009/11/21/101567.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/101567.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/101567.html</trackback:ping><description><![CDATA[<div style="MARGIN: 15px" id=art>#include &lt;iostream&gt;<br><br>using namespace std;<br><br>//single link<br>struct slink_t{<br>&nbsp;&nbsp; &nbsp;struct slink_t* next;<br>&nbsp;&nbsp; &nbsp;int data;<br>&nbsp;&nbsp; &nbsp;slink_t(): next(0), data(0){<br>&nbsp;&nbsp; &nbsp;}<br>&nbsp;&nbsp; &nbsp;slink_t(slink_t* p, int d): next(p), data(d){<br>&nbsp;&nbsp; &nbsp;}<br>};<br><br>/*output data of single link */<br>ostream&amp; operator&lt;&lt; (ostream&amp; os, const struct slink_t* p)<br>{<br>&nbsp;&nbsp; &nbsp;cout &lt;&lt; "Output : ";<br>&nbsp;&nbsp; &nbsp;while (p &amp;&amp; cout &lt;&lt; p-&gt;data &lt;&lt; ' ')<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;p = p-&gt;next;<br>&nbsp;&nbsp; &nbsp;return os;<br>}<br><br>/* reverse the single link */<br>struct slink_t* slink_reverse(struct slink_t* p)<br>{<br>&nbsp;&nbsp; &nbsp;struct slink_t* t = NULL, *tp = NULL;<br>&nbsp;&nbsp; &nbsp;while (p)<br>&nbsp;&nbsp; &nbsp;{<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;tp = t;<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;t = p;<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;p = p-&gt;next;<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;t-&gt;next = tp;<br>&nbsp;&nbsp; &nbsp;}<br>&nbsp;&nbsp; &nbsp;return t;<br>}<br><br>//double link<br>struct dlink_t{<br>&nbsp;&nbsp; &nbsp;struct dlink_t* next;<br>&nbsp;&nbsp; &nbsp;struct dlink_t* prev;<br>&nbsp;&nbsp; &nbsp;int data;<br>&nbsp;&nbsp; &nbsp;dlink_t(): next(0), prev(0), data(0){<br>&nbsp;&nbsp; &nbsp;}<br>&nbsp;&nbsp; &nbsp;dlink_t(dlink_t* n, dlink_t* p, int d): next(n), prev(p), data(d){<br>&nbsp;&nbsp; &nbsp;}<br>};<br><br>/* output data of double link */<br>ostream&amp; operator&lt;&lt; (ostream&amp; os, const struct dlink_t* p)<br>{<br>&nbsp;&nbsp; &nbsp;cout &lt;&lt; "Output : ";<br>&nbsp;&nbsp; &nbsp;while (p &amp;&amp; cout &lt;&lt; p-&gt;data &lt;&lt; ' ')<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;p = p-&gt;next;<br>&nbsp;&nbsp; &nbsp;return os;<br>}<br><br>/* reverse the double link */<br>struct dlink_t* dlink_reverse(struct dlink_t* p)<br>{<br>&nbsp;&nbsp; &nbsp;struct dlink_t* t = NULL;<br>&nbsp;&nbsp; &nbsp;while (p)<br>&nbsp;&nbsp; &nbsp;{<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;t = p;<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;p = p-&gt;next;<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;t-&gt;next = t-&gt;prev;<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;t-&gt;prev = p;<br>&nbsp;&nbsp; &nbsp;}<br>&nbsp;&nbsp; &nbsp;return t;<br>}<br><br>#define TEST__<br><br>#ifdef TEST__<br>/* test */<br>int main()<br>{<br>&nbsp;&nbsp; &nbsp;struct slink_t* sl = new slink_t(new slink_t(new slink_t(new slink_t(new slink_t(new slink_t(NULL, 6), 5), 4), 3), 2), 1);<br>&nbsp;&nbsp; &nbsp;cout &lt;&lt; sl &lt;&lt; endl;<br>&nbsp;&nbsp; &nbsp;sl = slink_reverse(sl);<br>&nbsp;&nbsp; &nbsp;cout &lt;&lt; sl &lt;&lt; endl;<br>&nbsp;&nbsp; &nbsp;struct dlink_t* dl = NULL;<br>&nbsp;&nbsp; &nbsp;struct dlink_t* h = new dlink_t(NULL, dl, 1);<br>&nbsp;&nbsp; &nbsp;dl = h;<br>&nbsp;&nbsp; &nbsp;for (int i = 2; i &lt; 10; i++)<br>&nbsp;&nbsp; &nbsp;{<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;struct dlink_t* t = new dlink_t(NULL, dl, i);<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;dl-&gt;next = t;<br>&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;dl = t;<br>//&nbsp;&nbsp; &nbsp;&nbsp;&nbsp; &nbsp;dl-&gt;prev-&gt;next = dl;<br>&nbsp;&nbsp; &nbsp;}<br>&nbsp;&nbsp; &nbsp;cout &lt;&lt; h &lt;&lt; endl;<br>&nbsp;&nbsp; &nbsp;h = dlink_reverse(h);<br>&nbsp;&nbsp; &nbsp;cout &lt;&lt; h &lt;&lt; endl;<br>&nbsp;&nbsp; &nbsp;cout &lt;&lt; "Hello world" &lt;&lt; endl;<br>&nbsp;&nbsp; &nbsp;return 0;<br>}<br>#endif </div>
转自：<br><a href="http://blog.chinaunix.net/u3/101003/showart.php?id=2095827">http://blog.chinaunix.net/u3/101003/showart.php?id=2095827</a><br>
<img src ="http://www.cppblog.com/beautykingdom/aggbug/101567.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2009-11-21 18:41 <a href="http://www.cppblog.com/beautykingdom/archive/2009/11/21/101567.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>算法面试题</title><link>http://www.cppblog.com/beautykingdom/archive/2009/11/16/101050.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Mon, 16 Nov 2009 04:18:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2009/11/16/101050.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/101050.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2009/11/16/101050.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/101050.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/101050.html</trackback:ping><description><![CDATA[<div>1.比较两个字符串如果不等返回True？</div><div><br></div><div><br></div><div>答案：</div><div>Java代码&nbsp;</div><div>package com.test.kaoshi; &nbsp; &nbsp;</div><div>&nbsp;&nbsp;&nbsp;</div><div>public class StringDemo { &nbsp; &nbsp;</div><div>&nbsp;&nbsp;&nbsp;</div><div>&nbsp;&nbsp; &nbsp;private static String a = "abc"; &nbsp; &nbsp;</div><div>&nbsp;&nbsp; &nbsp;private static String b = "abcg"; &nbsp; &nbsp;</div><div>&nbsp;&nbsp;&nbsp;</div><div>&nbsp;&nbsp; &nbsp;public static boolean equalString() { &nbsp; &nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;if (a.equals(b)) { &nbsp; &nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return false; &nbsp; &nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;} else { &nbsp; &nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return true; &nbsp; &nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;} &nbsp; &nbsp;</div><div>&nbsp;&nbsp; &nbsp;} &nbsp; &nbsp;</div><div>&nbsp;&nbsp; &nbsp;public static void main(String[] args) { &nbsp; &nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;StringDemo &nbsp;sd = new StringDemo(); &nbsp; &nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;System.out.println("主要考察返回Boolean变量和字符串比较使用的方法?+sd.equalString()); &nbsp; &nbsp;</div><div>&nbsp;&nbsp; &nbsp;} &nbsp; &nbsp;</div><div>} &nbsp;&nbsp;</div><div><br></div><div><br></div><div><br></div><div><br></div><div>2.随机产生20个字符并且排序？</div><div><br></div><div>答案：</div><div>Java代码&nbsp;</div><div>package com.test.kaoshi; &nbsp; &nbsp;</div><div>&nbsp;&nbsp;&nbsp;</div><div>import java.util.HashSet; &nbsp; &nbsp;</div><div>import java.util.Iterator; &nbsp; &nbsp;</div><div>import java.util.Random; &nbsp; &nbsp;</div><div>import java.util.Set; &nbsp; &nbsp;</div><div>import java.util.TreeSet; &nbsp; &nbsp;</div><div>&nbsp;&nbsp;&nbsp;</div><div>public class RadomDemo { &nbsp; &nbsp;</div><div>&nbsp;&nbsp;&nbsp;</div><div>&nbsp;&nbsp; &nbsp;public Set getChar(){ &nbsp; &nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;Set numberSet01 = new HashSet(); &nbsp; &nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;Random rdm = new Random(); &nbsp; &nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;char ch; &nbsp; &nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;while(numberSet01.size()&lt;20){ &nbsp; &nbsp;&nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; int rdGet = Math.abs(rdm.nextInt())%26+97;//产生97到122的随机数a-z值 &nbsp; &nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ch=(char)rdGet; &nbsp; &nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;numberSet01.add(ch); &nbsp; &nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;//Set中是不能放进重复的值的，当它有20个时，就满足你的条件了 &nbsp; &nbsp;&nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;} &nbsp; &nbsp;&nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;return numberSet01; &nbsp; &nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;} &nbsp; &nbsp;</div><div>&nbsp;&nbsp; &nbsp;public static void main(String[] args) { &nbsp; &nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;RadomDemo rd = new RadomDemo(); &nbsp; &nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;Set numberSet01=rd.getChar(); &nbsp; &nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;Set numberSet = new TreeSet(); &nbsp; &nbsp;&nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;numberSet.addAll(numberSet01); &nbsp; &nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;for(Iterator it=numberSet01.iterator();it.hasNext();){ &nbsp; &nbsp;&nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;System.out.print(it.next()); &nbsp; &nbsp;&nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;} &nbsp; &nbsp;&nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;System.out.println(); &nbsp; &nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;for(Iterator it=numberSet.iterator();it.hasNext();){ &nbsp; &nbsp;&nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;System.out.print(it.next()); &nbsp; &nbsp;&nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;} &nbsp; &nbsp;&nbsp;</div><div>&nbsp;&nbsp; &nbsp;} &nbsp; &nbsp;</div><div>} &nbsp;&nbsp;</div><div><br></div><div><br></div><div><br></div><div>3.50个人围成一圈数到三和三的倍数时出圈，问剩下的人是谁？在原来的位置是多少？</div><div><br></div><div><br></div><div>答案：</div><div><br></div><div>Java代码&nbsp;</div><div>package com.test.kaoshi; &nbsp; &nbsp;</div><div>&nbsp;&nbsp;&nbsp;</div><div>import java.util.Iterator; &nbsp; &nbsp;</div><div>import java.util.LinkedList; &nbsp; &nbsp;</div><div>&nbsp;&nbsp;&nbsp;</div><div>public class YouXi { &nbsp; &nbsp;</div><div>&nbsp;&nbsp; &nbsp;public static int removeNM(int n, int m) { &nbsp; &nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;LinkedList ll = new LinkedList(); &nbsp; &nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;for (int i = 0; i &lt; n; i++) &nbsp; &nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ll.add(new Integer(i + 1)); &nbsp; &nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;int removed = -1; &nbsp; &nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;while (ll.size() &gt; 1) { &nbsp; &nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;removed = (removed + m) % ll.size(); &nbsp; &nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;ll.remove(removed--); &nbsp; &nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;} &nbsp; &nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;return ((Integer) ll.get(0)).intValue(); &nbsp; &nbsp;</div><div>&nbsp;&nbsp; &nbsp;} &nbsp; &nbsp;</div><div>&nbsp;&nbsp;&nbsp;</div><div>&nbsp;&nbsp; &nbsp;public static void main(String[] args) { &nbsp; &nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;System.out.println(removeNM(50, 3)); &nbsp; &nbsp;</div><div>&nbsp;&nbsp; &nbsp;} &nbsp; &nbsp;</div><div>} &nbsp;&nbsp;</div><div><br></div><div>. 时针分针重合几次</div><div>表面上有60个小格，每小格代表一分钟，</div><div>时针每分钟走1/12小格，分针每分钟走1小格，从第一次重合到第二次重合分针比时针多走一圈即60小格，所以</div><div>60/（1-1/12）=720/11</div><div>每隔720/11分才重合一次（而并不是每小时重合一次）</div><div><br></div><div>1440里有22个720/11，如果说算上0点和24点，那也是重合23次而已，但我觉得0点应该算到前一天的24点头上，所以每一天循环下来重合22次啊</div><div><br></div><div>2. 找出字符串的最长不重复子串，输出长度</div><div>建一个256个单元的数组，每一个单元代表一个字符，数组中保存上次该字符上次出现的位置；</div><div>依次读入字符串，同时维护数组的值；</div><div>如果遇到冲突了，就返回冲突字符中保存的位置，继续第二步。也可以用hashmap保存已经出现的字符和字符的位置</div><div><br></div><div>3. 说是有一个文本文件，大约有一万行，每行一个词，要求统计出其中最频繁出</div><div>现的前十个词。</div><div>先用哈希，统计每个词出现的次数，然后在用在N个数中找出前K大个数的方法找出出现</div><div>次数最多的前10个词。</div><div><br></div><div>4. 如题3，但是车次文件特别大，没有办法一次读入内存。</div><div>1) 直接排序，写文件时，同时写入字符串及其出现</div><div>次数。</div><div>2) 可以用哈希，比如先根据字符串的第一个字符将字符串换分为多个区域，每个区域的字符串写到一个文件内，然后再用哈希+堆统计每个区域内前10个频率最高的字符串，最后求出所有字符串中前10个频率最高的字符串。</div><div><br></div><div>5. 有一个整数n，将n分解成若干个整数之和，问如何分解能使这些数的乘积最大，输出这个乘积m。例如：n=12</div><div>（1）分解为1+1+1+&#8230;+1，12个1, m=1*1*1&#8230;&#8230;*1=1</div><div>（2）分解为2+2+&#8230;+2，6个2， m=64</div><div>（3）分解为3+3+3+3，4个3， m=81</div><div>（4）大于等于4时分解时只能分解为2和3，且2最多两个</div><div>f(n) = 3*f(n-3) n&gt;4</div><div>f(4) = 2*2</div><div>f(3) = 3</div><div>f(2) = 2分解为4+4+4，3个4， m=64</div><div><br></div><div>6. 求数组n中出现次数超过一半的数</div><div>把数组分成[n/2]组，则至少有一组包含重复的数，因为如果无重复数，则最多只有出现次数等于一半的数。算法如下：</div><div>k&lt;-n;</div><div>while k&gt;3 do</div><div>把数组分成[k/2]组;</div><div>for i=1 to [k/2] do</div><div>&nbsp;&nbsp; &nbsp;if 组内2个数相同，则任取一个数留下;</div><div>&nbsp;&nbsp; &nbsp;else 2个数同时扔掉;</div><div>k&lt;-剩下的数</div><div>if k=3</div><div>&nbsp;&nbsp; &nbsp;then 任取2个数进行比较;</div><div>&nbsp;&nbsp; &nbsp; &nbsp;if 两个数不同，则2个数都扔掉</div><div>&nbsp;&nbsp; &nbsp; &nbsp; else 任取一个数</div><div>&nbsp;&nbsp; &nbsp;if k=2 or 1 then 任取一数</div><div><br></div><div>7. A文件中最多有n个正整数，而且每个数均小于n，n &lt;=10的七次方。不会出现重复的数。</div><div>要求对A文件中的数进行排序，可用内存为1M，磁盘可用空间足够。</div><div>不要把任何问题都往很复杂的算法上靠，最直接最简单的解决问题才是工程师应有的素质，</div><div>题目给的很有分寸：n个数，都小于n，两两不同，1M=10^6byte=10^7bit的内存，n &lt;10^7</div><div>思路：</div><div>把1M内存看作是一个长度为10^7的位数组，每一位都初始化为0</div><div>从头扫描n个数，如果碰到i，就把位数组的第i个位置置为1，</div><div><br></div><div>1M内存有点少， （1M = 8M bits), 可以代表8M整数，现在n &lt;=10的七次方，你可以读2遍文件，就可以完成排序了。第一次排n &lt;8M得数， 第2遍排 8M &lt;n &lt;10的七次方的数。</div><div><br></div><div><br></div><div>8. 有10亿个杂乱无章的数，怎样最快地求出其中前1000大的数。</div><div>1) 建一个1000个数的堆，复杂度为N*(log1000)=10N</div><div>2) 1.用每一个BIT标识一个整数的存在与否，这样一个字节可以标识8个整数的存在与否，对于所有32位的整数，需要512Mb，所以开辟一个512Mb的字符数组A，初始全0</div><div>&nbsp;&nbsp; 2.依次读取每个数n，将A[n&gt;&gt;3]设置为A[n&gt;&gt;3]|(1&lt;&lt;n%8)，相当于将每个数的对应位设置为1</div><div>&nbsp;&nbsp; 3.在A中，从大到小读取1000个值为1的数，就是最大的1000个数了。</div><div>这样读文件就只需要1遍，在不考虑内存开销的情况下，应该是速度最快的方法了。</div><div><br></div><div>9. 一棵树节点1, 2, 3, ... , n. 怎样实现：</div><div>先进行O(n)预处理，然后任给两个节点，用O(1)判断它们的父子关系</div><div>dfs一遍，记录每个结点的开始访问时间Si和结束访问时间Ei</div><div>对于两个节点i,j，若区间[Si,Ei]包含[Sj,Ej]，则i是j的祖先。给每个节点哈夫曼编码也行，但只适合一般的二叉树，而实际问题未必是Binary的，所以编码有局限性</div><div><br></div><div>10. 给定一个二叉树，求其中N（N&gt;=2）个节点的最近公共祖先节点。每个节点只有左右孩</div><div>子指</div><div>针，没有父指针。</div><div>后序递归给每个节点打分，每个节点的分数=左分数+右分数+k，如果某孩子是给定节点则+1</div><div>最深的得分为N的节点就是所求吧，细节上应该不用递归结束就可以得到这个节点</div><div><br></div><div>11. 如何打印如下的螺旋队列：</div><div>21 22 。。。。</div><div>20 7 8 9 10</div><div>19 6 1 2 11</div><div>18 5 4 3 12</div><div>17 16 15 14 13</div><div><br></div><div>#include &lt;stdio.h&gt;</div><div>#define max(a,b) ((a)&lt;(b)?(b):(a))</div><div>#define abs(a) ((a)&gt;0?(a):-(a))</div><div>int foo(int x, int y)</div><div>{</div><div>int t = max(abs(x), abs(y));</div><div>int u = t + t;</div><div>int v = u - 1;</div><div>v = v * v + u;</div><div>if (x == -t)</div><div>&nbsp;&nbsp; &nbsp;v += u + t - y;</div><div>else if (y == -t)</div><div>&nbsp;&nbsp; &nbsp;v += 3 * u + x - t;</div><div>else if (y == t )</div><div>&nbsp;&nbsp; &nbsp;v += t - x;</div><div>else</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;v += y - t;</div><div>return v;</div><div>}</div><div>int main()</div><div>{</div><div>int x, y;</div><div>for (y=-2;y&lt;=2;y++)</div><div>{</div><div>&nbsp;&nbsp; &nbsp;for (x=-2;x&lt;=2;x++)</div><div>&nbsp;&nbsp; &nbsp; &nbsp;printf("%5d", foo(x, y));</div><div>&nbsp;&nbsp; &nbsp;printf("\n");</div><div>}</div><div>return 0;</div><div>}</div><div>第 0 层规定为中间的那个 1，第 1 层为 2 到 9，第 2 层为 10 到 25，&#8230;&#8230;好像看出一点名堂来了？注意到 1、9、25、&#8230;&#8230;不就是平方数吗？而且是连续奇数（1、3、5、&#8230;&#8230;）的平方数。这些数还跟层数相关，推算一下就可以知道第 t 层之内一共有 (2t-1)^2 个数，因而第 t 层会从 [(2t-1)^2] + 1 开始继续往外螺旋。给定坐标 (x,y)，如何知道该点处于第几层？so easy，层数 t = max(|x|,|y|)。</div><div><br></div><div>知道了层数，接下来就好办多了，这时我们就知道所求的那点一定在第 t 层这个圈上，顺着往下数就是了。要注意的就是螺旋队列数值增长方向和坐标轴正方向并不一定相同。我们可以分成四种情况——上、下、左、右——或者——东、南、西、北，分别处于四条边上来分析。</div><div><br></div><div>东|右：x == t，队列增长方向和 y 轴一致，正东方向（y = 0）数值为 (2t-1)^2 + t，所以 v = (2t-1)^2 + t + y</div><div><br></div><div>南|下：y == t，队列增长方向和 x 轴相反，正南方向（x ＝ 0）数值为 (2t-1)^2 + 3t，所以 v ＝ (2t-1)^2 + 3t - x</div><div><br></div><div>西|左：x == -t，队列增长方向和 y 轴相反，正西方向（y ＝ 0）数值为 (2t-1)^2 + 5t，所以 v = (2t-1)^2 + 5t - y</div><div><br></div><div>北|上：y == -t，队列增长方向和 x 轴一致，正北方向（x ＝ 0）数值为 (2t-1)^2 + 7t，所以 v ＝ (2t-1)^2 + 7t + x</div><div><br></div><div>12. 一个整数，知道位数，如何判断它是否能被3整除，不可以使用除法和模运算</div><div>首先 3x=2^n+1时 仅当 n 为奇数才可能 因为2^n = 3x + (-1)^n;所以该问题就转化为了</div><div>找到最后一个为1的位a，看看向前的一个1（b）和这个位的距离，如果为偶数的距离则不能整除，如果是奇数，去除b之后的位继续判断</div><div><br></div><div>13. seq=[a,b,...,z,aa,ab,...,az,ba,bb...,bz,...za,zb,...,zz,aaa...],求[a-z]+(从a到z任意字符组成的字符串)s在seq的位置，即排在第几</div><div>本质就是26进制。</div><div><br></div><div>大家都知道，看一个数是否能被2整除只需要看它的个位能否被2整除即可。可是你想过为什么吗？这是因为10能被2整除，因此一个数10a+b能被2整除当且仅当b能被2整除。大家也知道，看一个数能否被3整除只需要看各位数之和是否能被3整除。这又是为什么呢？答案或多或少有些类似：因为10^n-1总能被3整除。2345可以写成2*(999+1) + 3*(99+1) + 4*(9+1) + 5，展开就是2*999+3*99+4*9 + 2+3+4+5。前面带了数字9的项肯定都能被3整除了，于是要看2345能否被3整除就只需要看2+3+4+5能否被3整除了。当然，这种技巧只能在10进制下使用，不过类似的结论可以推广到任意进制。</div><div>&nbsp;&nbsp; &nbsp; 注意到36是4的整数倍，而ZZZ...ZZ除以7总是得555...55。也就是说，判断一个36进制数能否被4整除只需要看它的个位，而一个36进制数能被7整除当且仅当各位数之和能被7整除。如果一个数同时能被4和7整除，那么这个数就一定能被28整除。于是问题转化为，有多少个连续句子满足各位数字和是7的倍数，同时最后一个数是4的倍数。这样，我们得到了一个O(n)的算法：用P[i]表示前若干个句子除以7的余数为i有多少种情况，扫描整篇文章并不断更新P数组。当某句话的最后一个字能被4整除时，假设以这句话结尾的前缀和除以7余x，则将此时P[x]的值累加到最后的输出结果中（两个前缀的数字和除以7余数相同，则较长的前缀多出来的部分一定整除7）。</div><div>&nbsp;&nbsp; &nbsp; 上述算法是我出这道题的本意，但比赛后我见到了其它各种各样新奇的算法。比如有人注意到36^n mod 28总是等于8，利用这个性质也可以构造出类似的线性算法来。还有人用动态规划（或者说递推）完美地解决了这个问题。我们用f[i,j]表示以句子i结束，除以28余数为j的文本片段有多少个；处理下一句话时我们需要对每一个不同的j进行一次扫描，把f[i-1,j]加进对应的f[i,j']中。最后输出所有的f[i,0]的总和即可。这个动态规划可以用滚动数组，因此它的空间同前面的算法一样也是常数的。</div><div>&nbsp;&nbsp; &nbsp; 如果你完全不知道我在说什么，你可以看看和进位制、同余相关的文章。另外，我之前还曾出过一道很类似的题(VOJ1090)，你可以对比着看一看。</div><div><br></div><div>&nbsp;</div><div><br></div><div>&nbsp;</div><div>有一个整数n,写一个函数f(n),返回0到n之间出现的"1"的个数。比如f(13)=6,现在f(1)=1,问有哪些n能满足f(n)=n？</div><div><br></div><div>例如：f(13)=6, 因为1,2,3,4,5,6,7,8,9,10,11,12,13.数数1的个数，正好是6.</div><div><br></div><div>public class Test {</div><div><br></div><div>public int n = 2;</div><div><br></div><div>public int count = 0;</div><div><br></div><div>public void BigestNumber(int num) {</div><div><br></div><div>for (int i = 1; i &lt;= num; i++) {</div><div>int m = 0;</div><div><br></div><div>int j = i;</div><div>while (j &gt; 0) {</div><div>m = j % 10;</div><div><br></div><div>if (m == 1)</div><div>&nbsp;&nbsp; &nbsp;count++;</div><div>if (j &gt; 0)</div><div>&nbsp;&nbsp; &nbsp;j = j / 10;</div><div><br></div><div>}</div><div><br></div><div>}</div><div><br></div><div>System.out.println("f(" + num + ")=" + count);</div><div><br></div><div><br></div><div>}</div><div><br></div><div>public static void main(String args[]) {</div><div>Test t = new Test();</div><div>long begin = System.currentTimeMillis();</div><div>t.BigestNumber(10000000);</div><div>long end = System.currentTimeMillis();</div><div>System.out.println("总时间" + (end-begin)/1000 + "秒");</div><div>}</div><div>}</div><div><br></div><div><br></div><div>结果：</div><div>f(10000000)=7000001</div><div>总时间5秒</div><div>&nbsp;</div><div>&nbsp;</div><div><br></div><div>1、将一整数逆序后放入一数组中（要求递归实现）</div><div>void convert(int *result, int n) {</div><div>&nbsp;if(n&gt;=10)</div><div>&nbsp;&nbsp;convert(result+1, n/10);</div><div>&nbsp;*result = n%10;</div><div>}</div><div>int main(int argc, char* argv[]) {</div><div>&nbsp;int n = 123456789, result[20]={};</div><div>&nbsp;convert(result, n);</div><div>&nbsp;printf("%d:", n);</div><div>&nbsp;for(int i=0; i&lt;9; i++)</div><div>&nbsp;&nbsp;printf("%d", result);</div><div>}</div><div>2、求高于平均分的学生学号及成绩（学号和成绩人工输入）</div><div>double find(int total, int n) {</div><div>&nbsp;int number, score, &nbsp;average;</div><div>&nbsp;scanf("%d", &amp;number);</div><div>&nbsp;if(number != 0) {</div><div>&nbsp;&nbsp;scanf("%d", &amp;score);</div><div>&nbsp;&nbsp;average = find(total+score, n+1);</div><div>&nbsp;&nbsp;if(score &gt;= average)</div><div>&nbsp;&nbsp; printf("%d:%d\n", number, score);</div><div>&nbsp;&nbsp;return average;</div><div>&nbsp;} else {</div><div>&nbsp;&nbsp;printf("Average=%d\n", total/n);</div><div>&nbsp;&nbsp;return total/n;</div><div>&nbsp;}</div><div>}</div><div>int main(int argc, char* argv[]) {</div><div>&nbsp;find(0, 0);</div><div>}</div><div>3、递归实现回文判断（如：abcdedbca就是回文，判断一个面试者对递归理解的简单程序）</div><div>int find(char *str, int n) {</div><div>&nbsp;if(n&lt;=1) return 1;</div><div>&nbsp;else if(str[0]==str[n-1]) return find(str+1, n-2);</div><div>&nbsp;else &nbsp;return 0;</div><div>}</div><div>int main(int argc, char* argv[]) {</div><div>&nbsp;char *str = "abcdedcba";</div><div>&nbsp;printf("%s: %s\n", str, find(str, strlen(str)) ? "Yes" : "No");</div><div>}</div><div>4、组合问题（从M个不同字符中任取N个字符的所有组合）</div><div>void find(char *source, char *result, int n) {</div><div>&nbsp;if(n==1) {</div><div>&nbsp;&nbsp;while(*source)</div><div>&nbsp;&nbsp; &nbsp; printf("%s%c\n", result, *source++);</div><div>&nbsp;} else {</div><div>&nbsp;&nbsp;int i, j;</div><div>&nbsp;&nbsp;for(i=0; source != 0; i++);</div><div>&nbsp;&nbsp;for(j=0; result[j] != 0; j++);</div><div>&nbsp;&nbsp;for(; i&gt;=n; i--) {</div><div>&nbsp;&nbsp; result[j] = *source++;</div><div>&nbsp;&nbsp; result[j+1] = '\0';</div><div>&nbsp;&nbsp; find(source, result, n-1);</div><div>&nbsp;&nbsp;}</div><div>&nbsp;}</div><div>}</div><div>int main(int argc, char* argv[]) {</div><div>&nbsp;int const n = 3;</div><div>&nbsp;char *source = "ABCDE", result[n+1] = {0};</div><div>&nbsp;if(n&gt;0 &amp;&amp; strlen(source)&gt;0 &amp;&amp; n&lt;=strlen(source))</div><div>&nbsp;&nbsp;find(source, result, 3);</div><div>}</div><div>5、分解成质因数(如435234=251*17*17*3*2，据说是华为笔试题)</div><div>void prim(int m, int n) {</div><div>&nbsp;if(m&gt;n) {</div><div>&nbsp;&nbsp;while(m%n != 0) n++;</div><div>&nbsp;&nbsp;m /= n;</div><div>&nbsp;&nbsp;prim(m, n);</div><div>&nbsp;&nbsp;printf("%d*", n);</div><div>&nbsp;}</div><div>}</div><div>int main(int argc, char* argv[]) {</div><div>&nbsp;int n = 435234;</div><div>&nbsp;printf("%d=", n);</div><div>&nbsp;prim(n, 2);</div><div>}</div><div>6、寻找迷宫的一条出路，o：通路； X：障碍。（大家经常谈到的一个小算法题）</div><div>#define MAX_SIZE &nbsp;8</div><div>int H[4] = {0, 1, 0, -1};</div><div>int V[4] = {-1, 0, 1, 0}; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;</div><div>char Maze[MAX_SIZE][MAX_SIZE] = {{'X','X','X','X','X','X','X','X'},</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {'o','o','o','o','o','X','X','X'},</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {'X','o','X','X','o','o','o','X'},</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {'X','o','X','X','o','X','X','o'},</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {'X','o','X','X','X','X','X','X'},</div><div>{'X','o','X','X','o','o','o','X'},</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; {'X','o','o','o','o','X','o','o'},</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; {'X','X','X','X','X','X','X','X'}};</div><div>void FindPath(int X, int Y) {</div><div>&nbsp;&nbsp; &nbsp;if(X == MAX_SIZE || Y == MAX_SIZE) {</div><div>&nbsp;&nbsp; &nbsp; &nbsp; for(int i = 0; i &lt; MAX_SIZE; i++)</div><div>for(int j = 0; j &lt; MAX_SIZE; j++)</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;printf("%c%c", Maze[j], j &lt; MAX_SIZE-1 ? ' ' : '\n');</div><div>}else for(int k = 0; k &lt; 4; k++)</div><div>if(X &gt;= 0 &amp;&amp; Y &gt;= 0 &amp;&amp; Y &lt; MAX_SIZE &amp;&amp; X &lt; MAX_SIZE &amp;&amp; 'o' == Maze[X][Y]) {</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Maze[X][Y] = ' ';</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; FindPath(X+V[k], Y+H[k]);</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Maze[X][Y] ='o';</div><div>}</div><div>}</div><div>int main(int argc, char* argv[]) {</div><div>&nbsp;&nbsp; &nbsp;FindPath(1,0);</div><div>}</div><div>7、随机分配座位，共50个学生，使学号相邻的同学座位不能相邻(早些时候用C#写的，没有用C改写）。</div><div>static void Main(string[] args)</div><div>{</div><div>&nbsp;int Tmp = 0, Count = 50; &nbsp;</div><div>&nbsp;int[] Seats = new int[Count]; &nbsp;</div><div>&nbsp;bool[] Students = new bool[Count];</div><div>&nbsp;System.Random RandStudent=new System.Random();</div><div>&nbsp;Students[Seats[0]=RandStudent.Next(0,Count)]=true;</div><div>&nbsp;for(int i = 1; i &lt; Count; ) {</div><div>&nbsp;&nbsp; &nbsp; Tmp=(int)RandStudent.Next(0,Count);</div><div>&nbsp;&nbsp; &nbsp; if((!Students[Tmp])&amp;&amp;(Seats[i-1]-Tmp!=1) &amp;&amp; (Seats[i-1] - Tmp) != -1) {</div><div>&nbsp;&nbsp; Seats[i++] = Tmp;</div><div>Students[Tmp] = true;</div><div>&nbsp;&nbsp;}</div><div>&nbsp;}</div><div>&nbsp;foreach(int Student in Seats)</div><div>&nbsp;&nbsp; &nbsp; System.Console.Write(Student + " ");</div><div>&nbsp;System.Console.Read();</div><div>}</div><div>8、求网格中的黑点分布。现有6*7的网格，在某些格子中有黑点，已知各行与各列中有黑点的点数之和，请在这张网格中画出黑点的位置。（这是一网友提出的题目，说是他笔试时遇到算法题）</div><div>#define ROWS 6</div><div>#define COLS 7</div><div>int iPointsR[ROWS] = {2, 0, 4, 3, 4, 0}; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // 各行黑点数和的情况</div><div>int iPointsC[COLS] = {4, 1, 2, 2, 1, 2, 1}; &nbsp; &nbsp; &nbsp; &nbsp;// 各列黑点数和的情况</div><div>int iCount, iFound;</div><div>int iSumR[ROWS], iSumC[COLS], Grid[ROWS][COLS];</div><div>int Set(int iRowNo) {</div><div>if(iRowNo == ROWS) {</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;for(int iColNo=0; iColNo &lt; COLS &amp;&amp; iSumC[iColNo]==iPointsC[iColNo]; iColNo++)</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if(iColNo == COLS-1) {</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; printf("\nNo.%d:\n", ++iCount);</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for(int i=0; i &lt; ROWS; i++)</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;for(int j=0; j &lt; COLS; j++)</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;printf("%d%c", Grid[j], (j+1) % COLS ? ' ' : '\n');</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; iFound = 1; // iFound = 1，有解</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }</div><div>&nbsp;&nbsp; &nbsp;} else {</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;for(int iColNo=0; iColNo &lt; COLS; iColNo++) {</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if(iPointsR[iRowNo] == 0) {</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Set(iRowNo + 1);</div><div>&nbsp;&nbsp; } else if(Grid[iRowNo][iColNo]==0) {</div><div>Grid[iRowNo][iColNo] = 1;</div><div>iSumR[iRowNo]++; iSumC[iColNo]++; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if(iSumR[iRowNo]&lt;iPointsR[iRowNo] &amp;&amp; iSumC[iColNo]&lt;=iPointsC[iColNo])</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Set(iRowNo);</div><div>else if(iSumR[iRowNo]==iPointsR[iRowNo] &amp;&amp; iRowNo &lt; ROWS)</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; Set(iRowNo + 1);</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Grid[iRowNo][iColNo] = 0;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;iSumR[iRowNo]--;</div><div>iSumC[iColNo]--;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;}</div><div>&nbsp;&nbsp; &nbsp;}</div><div>return iFound; &nbsp; &nbsp; // 用于判断是否有解</div><div>}</div><div>int main(int argc, char* argv[]) {</div><div>&nbsp;&nbsp; &nbsp;if(!Set(0))</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;printf("Failure!");</div><div>}</div><div>9、有4种面值的邮票很多枚，这4种邮票面值分别1, 4, 12, 21，现从多张中最多任取5张进行组合，求取出这些邮票的最大连续组合值。（据说是华为2003年校园招聘笔试题）</div><div>#define N 5</div><div>#define M 5</div><div>int k, Found, Flag[N];</div><div>int Stamp[M] = {0, 1, 4, 12, 21};</div><div>// 在剩余张数n中组合出面值和Value</div><div>int Combine(int n, int Value) {</div><div>&nbsp;if(n &gt;= 0 &amp;&amp; Value == 0) {</div><div>&nbsp;&nbsp;Found = 1;</div><div>&nbsp;&nbsp;int Sum = 0;</div><div>&nbsp;&nbsp;for(int i=0; i&lt;N &amp;&amp; Flag != 0; i++) {</div><div>&nbsp;&nbsp; Sum += Stamp[Flag];</div><div>&nbsp;&nbsp; printf("%d ", Stamp[Flag]);</div><div>&nbsp;&nbsp;}</div><div>&nbsp;&nbsp;printf("\tSum=%d\n\n", Sum);</div><div>&nbsp;}else for(int i=1; i&lt;M &amp;&amp; !Found &amp;&amp; n&gt;0; i++)</div><div>&nbsp;&nbsp;if(Value-Stamp &gt;= 0) {</div><div>&nbsp;&nbsp; Flag[k++] = i;</div><div>&nbsp;&nbsp; Combine(n-1, Value-Stamp);</div><div>&nbsp;&nbsp; Flag[--k] = 0;</div><div>&nbsp;&nbsp;}</div><div>&nbsp;return Found;</div><div>}</div><div>int main(int argc, char* argv[]) {</div><div>&nbsp;for(int i=1; Combine(N, i); i++, Found=0);</div><div>}</div><div>10、大整数数相乘的问题。（这是2002年在一考研班上遇到的算法题）</div><div>void Multiple(char A[], char B[], char C[]) {</div><div>&nbsp;&nbsp; &nbsp;int TMP, In=0, LenA=-1, LenB=-1;</div><div>&nbsp;&nbsp; &nbsp;while(A[++LenA] != '\0');</div><div>&nbsp;&nbsp; &nbsp;while(B[++LenB] != '\0');</div><div>&nbsp;&nbsp; &nbsp;int Index, Start = LenA + LenB - 1;</div><div>&nbsp;&nbsp; &nbsp;for(int i=LenB-1; i&gt;=0; i--) {</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;Index = Start--;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;if(B != '0') {</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;for(int In=0, j=LenA-1; j&gt;=0; j--) {</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;TMP = (C[Index]-'0') + (A[j]-'0') * (B - '0') + In;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;C[Index--] = TMP % 10 + '0';</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;In = TMP / 10;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;C[Index] = In + '0';</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;}</div><div>&nbsp;&nbsp; &nbsp;}</div><div>}</div><div>int main(int argc, char* argv[]) {</div><div>&nbsp;&nbsp; &nbsp;char A[] = "21839244444444448880088888889";</div><div>&nbsp;&nbsp; &nbsp;char B[] = "38888888888899999999999999988";</div><div>char C[sizeof(A) + sizeof(B) - 1];</div><div>&nbsp;&nbsp; &nbsp;for(int k=0; k&lt;sizeof(C); k++)</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;C[k] = '0';</div><div>&nbsp;&nbsp; &nbsp;C[sizeof(C)-1] = '\0';</div><div>&nbsp;&nbsp; &nbsp;Multiple(A, B, C);</div><div>&nbsp;&nbsp; &nbsp;for(int i=0; C != '\0'; i++)</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;printf("%c", C);</div><div>}</div><div>11、求最大连续递增数字串（如&#8220;ads3sl456789DF3456ld345AA&#8221;中的&#8220;456789&#8221;）</div><div>int GetSubString(char *strSource, char *strResult) {</div><div>&nbsp;&nbsp; &nbsp;int iTmp=0, iHead=0, iMax=0;</div><div>&nbsp;&nbsp; &nbsp;for(int Index=0, iLen=0; strSource[Index]; Index++) {</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;if(strSource[Index] &gt;= '0' &amp;&amp; strSource[Index] &lt;= '9' &amp;&amp;</div><div>strSource[Index-1] &gt; '0' &amp;&amp; strSource[Index] == strSource[Index-1]+1) {</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;iLen++; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // 连续数字的长度增1</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;} else { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// 出现字符或不连续数字</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if(iLen &gt; iMax) {</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;iMax = iLen; &nbsp;iHead = iTmp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;} &nbsp; &nbsp; &nbsp;&nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;// 该字符是数字，但数字不连续</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if(strSource[Index] &gt;= '0' &amp;&amp; strSource[Index] &lt;= '9') {</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;iTmp = Index;</div><div>iLen = 1;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;} &nbsp;&nbsp;</div><div>&nbsp;&nbsp; &nbsp;}</div><div>&nbsp;&nbsp; &nbsp;for(iTmp=0 ; iTmp &lt; iMax; iTmp++) // 将原字符串中最长的连续数字串赋值给结果串</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;strResult[iTmp] = strSource[iHead++];</div><div>&nbsp;&nbsp; &nbsp;strResult[iTmp]='\0';</div><div>&nbsp;&nbsp; &nbsp;return iMax; &nbsp; &nbsp; // 返回连续数字的最大长度</div><div>}</div><div>int main(int argc, char* argv[]) {</div><div>&nbsp;&nbsp; &nbsp;char strSource[]="ads3sl456789DF3456ld345AA", char strResult[sizeof(strSource)];</div><div>printf("Len=%d, strResult=%s \nstrSource=%s\n",</div><div>GetSubString(strSource, strResult), strResult, strSource);</div><div>}</div><div>12、四个工人，四个任务，每个人做不同的任务需要的时间不同，求任务分配的最优方案。（2005年5月29日全国计算机软件资格水平考试——软件设计师的算法题）。</div><div>#include "stdafx.h"</div><div>#define N 4</div><div>int Cost[N][N] = { {2, 12, 5, 32}, &nbsp;// 行号：任务序号，列号：工人序号</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{8, 15, 7, 11}, &nbsp;// 每行元素值表示这个任务由不同工人完成所需要的时间</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{24, 18, 9, 6},</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;{21, 1, 8, 28}};</div><div>int MinCost=1000;</div><div>int Task[N], TempTask[N], Worker[N];</div><div>void Assign(int k, int cost) {</div><div>&nbsp;if(k == N) {</div><div>&nbsp;&nbsp;MinCost = cost;</div><div>&nbsp;&nbsp;for(int i=0; i&lt;N; i++)</div><div>&nbsp;&nbsp; TempTask = Task;</div><div>&nbsp;} else {</div><div>&nbsp;&nbsp;for(int i=0; i&lt;N; i++) {</div><div>&nbsp;&nbsp; if(Worker==0 &amp;&amp; cost+Cost[k] &lt; MinCost) { // 为提高效率而进行剪枝</div><div>&nbsp;&nbsp; &nbsp;Worker = 1; Task[k] = i;</div><div>&nbsp;&nbsp; &nbsp;Assign(k+1, cost+Cost[k]);</div><div>&nbsp;&nbsp; &nbsp;Worker = 0; Task[k] = 0;</div><div>&nbsp;&nbsp; }</div><div>&nbsp;&nbsp;}</div><div>&nbsp;}</div><div>}</div><div>int main(int argc, char* argv[]) {</div><div>&nbsp;Assign(0, 0);</div><div>&nbsp;printf("最佳方案总费用=%d\n", MinCost);</div><div>&nbsp;for(int i=0; i&lt;N; i++)&nbsp;</div><div>&nbsp;&nbsp;printf("\t任务%d由工人%d来做：%d\n", i, TempTask, Cost[TempTask]);</div><div>}</div><div><br></div><div>&nbsp;</div><div><br></div><div>13、八皇后问题，输出了所有情况，不过有些结果只是旋转了90度而已。（回溯算法的典型例题，是数据结构书上算法的具体实现，大家都亲自动手写过这个程序吗？）</div><div>#define N 8</div><div>int Board[N][N];</div><div>int Valid(int i, int j) { &nbsp;// 判断下棋位置是否有效</div><div>&nbsp;int k = 1;</div><div>&nbsp;for(k=1; i&gt;=k &amp;&amp; j&gt;=k;k++)</div><div>&nbsp;&nbsp;if(Board[i-k][j-k]) return 0;</div><div>&nbsp;for(k=1; i&gt;=k;k++)</div><div>&nbsp;&nbsp;if(Board[i-k][j]) &nbsp;return 0;</div><div>&nbsp;for(k=1; i&gt;=k &amp;&amp; j+k&lt;N;k++)</div><div>&nbsp;&nbsp;if(Board[i-k][j+k]) return 0;</div><div>&nbsp;return 1;</div><div>}</div><div>void Trial(int i, int n) { &nbsp;// 寻找合适下棋位置</div><div>&nbsp;if(i == n) {</div><div>&nbsp;&nbsp;for(int k=0; k&lt;n; k++) {</div><div>&nbsp;&nbsp; for(int m=0; m&lt;n; m++)</div><div>&nbsp;&nbsp; &nbsp;printf("%d ", Board[k][m]);</div><div>&nbsp;&nbsp; printf("\n");</div><div>&nbsp;&nbsp;}</div><div>&nbsp;&nbsp;printf("\n");</div><div>&nbsp;} else {</div><div>&nbsp;&nbsp;for(int j=0; j&lt;n; j++) {</div><div>&nbsp;&nbsp; Board[j] = 1;</div><div>&nbsp;&nbsp; if(Valid(i,j))</div><div>&nbsp;&nbsp; &nbsp;Trial(i+1, n);</div><div>&nbsp;&nbsp; Board[j] = 0;</div><div>&nbsp;&nbsp;}</div><div>&nbsp;}</div><div>}</div><div>int main(int argc, char* argv[]) {</div><div>&nbsp;Trial(0, N);</div><div>}</div><div>14、实现strstr功能，即在父串中寻找子串首次出现的位置。（笔试中常让面试者实现标准库中的一些函数）</div><div>char * strstring(char *ParentString, char *SubString) {</div><div>&nbsp;char *pSubString, *pPareString;</div><div>&nbsp;for(char *pTmp=ParentString; *pTmp; pTmp++) {</div><div>&nbsp;&nbsp;pSubString = SubString;</div><div>&nbsp;&nbsp;pPareString = pTmp;</div><div>&nbsp;&nbsp;while(*pSubString == *pPareString &amp;&amp; *pSubString != '\0') {</div><div>&nbsp;&nbsp; pSubString++;</div><div>&nbsp;&nbsp; pPareString++;</div><div>&nbsp;&nbsp;}</div><div>&nbsp;&nbsp;if(*pSubString == '\0') &nbsp;return pTmp;</div><div>&nbsp;}</div><div>&nbsp;return NULL;</div><div>}</div><div>int main(int argc, char* argv[]) {</div><div>&nbsp;char *ParentString = "happy birthday to you!";</div><div>&nbsp;char *SubString = "birthday";</div><div>&nbsp;printf("%s",strstring(ParentString, SubString));</div><div>}</div><div>15、现在小明一家过一座桥，过桥的时候是黑夜，所以必须有灯。现在小明过桥要1分，小明的弟弟要3分，小明的爸爸要6分，小明的妈妈要8分，小明的爷爷要12分。每次此桥最多可过两人，而过桥的速度依过桥最慢者而定，而且灯在点燃后30分就会熄灭。问小明一家如何过桥时间最短？（原本是个小小智力题，据说是外企的面试题，在这里用程序来求解）</div><div>#include "stdafx.h"</div><div>#define N &nbsp; &nbsp;5</div><div>#define SIZE 64</div><div>// 将人员编号：小明-0，弟弟-1，爸爸-2，妈妈-3，爷爷-4</div><div>// 每个人的当前位置：0--在桥左边， 1--在桥右边</div><div>int Position[N]; &nbsp;&nbsp;</div><div>// 过桥临时方案的数组下标； 临时方案； 最小时间方案；</div><div>int Index, TmpScheme[SIZE], Scheme[SIZE]; &nbsp;</div><div>// 最小过桥时间总和，初始值100；每个人过桥所需要的时间</div><div>int MinTime=100, Time[N]={1, 3, 6, 8, 12};&nbsp;</div><div>// 寻找最佳过桥方案。Remnant:未过桥人数; CurTime:当前已用时间;</div><div>// Direction:过桥方向,1--向右,0--向左</div><div>void Find(int Remnant, int CurTime, int Direction) {</div><div>&nbsp;&nbsp; &nbsp;if(Remnant == 0) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; // 所有人已经过桥，更新最少时间及方案</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;MinTime=CurTime;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;for(int i=0; i&lt;SIZE &amp;&amp; TmpScheme&gt;=0; i++)</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Scheme = TmpScheme;</div><div>&nbsp;&nbsp; &nbsp;} else if(Direction == 1) { &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;// 过桥方向向右，从桥左侧选出两人过桥</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;for(int i=0; i&lt;N; i++) &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if(Position == 0 &amp;&amp; CurTime + Time &lt; MinTime) {</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;TmpScheme[Index++] = i;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Position = 1;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;for(int j=0; j&lt;N; j++) {</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;int TmpMax = (Time &gt; Time[j] ? Time : Time[j]);</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if(Position[j] == 0 &amp;&amp; CurTime + TmpMax &lt; MinTime) {</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;TmpScheme[Index++] = j; &nbsp;&nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Position[j] = 1; &nbsp; &nbsp; &nbsp;&nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Find(Remnant - 2, CurTime + TmpMax, !Direction);</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Position[j] = 0; &nbsp; &nbsp; &nbsp;&nbsp;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;TmpScheme[--Index] = -1;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Position = 0;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;TmpScheme[--Index] = -1;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}</div><div>&nbsp;&nbsp; &nbsp;} else { &nbsp; &nbsp; &nbsp; &nbsp;// 过桥方向向左，从桥右侧选出一个人回来送灯</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;for(int j=0; j&lt;N; j++) {</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if(Position[j] == 1 &amp;&amp; CurTime+Time[j] &lt; MinTime) {</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;TmpScheme[Index++] = j;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Position[j] = 0;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Find(Remnant+1, CurTime+Time[j], !Direction);</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;Position[j] = 1;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;TmpScheme[--Index] = -1;</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;}</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;}</div><div>&nbsp;&nbsp; &nbsp;}</div><div>}</div><div>int main(int argc, char* argv[]) {</div><div>&nbsp;&nbsp; &nbsp;for(int i=0; i&lt;SIZE; i++) &nbsp; // 初始方案内容为负值，避免和人员标号冲突</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;Scheme = TmpScheme = -1;</div><div>Find(N, 0, 1); &nbsp; &nbsp; &nbsp; &nbsp;// 查找最佳方案</div><div>&nbsp;&nbsp; &nbsp;printf("MinTime=%d:", MinTime); // 输出最佳方案</div><div>&nbsp;&nbsp; &nbsp;for(int i=0; i&lt;SIZE &amp;&amp; Scheme&gt;=0; i+=3)</div><div>&nbsp;&nbsp; &nbsp; &nbsp; &nbsp;printf(" &nbsp;%d-%d &nbsp;%d", Scheme, Scheme[i+1], Scheme[i+2]);</div><div>&nbsp;&nbsp; &nbsp;printf("\b\b &nbsp;");</div><div>}</div><div>16、2005年11月金山笔试题。编码完成下面的处理函数。函数将字符串中的字符'*'移到串的前部分，前面的非'*'字符后移，但不能改变非'*'字符的先后顺序，函数返回串中字符'*'的数量。如原始串为：ab**cd**e*12，处理后为*****abcde12，函数并返回值为5。（要求使用尽量少的时间和辅助空间）</div><div>int change(char *str) { &nbsp; &nbsp;</div><div>&nbsp;int count = 0; &nbsp; &nbsp;</div><div>&nbsp;for(int i=0, j=0; str; i++) {&nbsp;</div><div>&nbsp;&nbsp;if(str=='*') { &nbsp;&nbsp;</div><div>&nbsp;&nbsp; for(j=i-1; str[j]!='*'&amp;&amp;j&gt;=0; j--)</div><div>&nbsp;&nbsp; &nbsp;str[j+1]=str[j]; &nbsp; &nbsp;</div><div>&nbsp;&nbsp; str[j+1] = '*';</div><div>&nbsp;&nbsp; count++;</div><div>&nbsp;&nbsp;}</div><div>&nbsp;}</div><div>&nbsp;return count;</div><div>}</div><div>int main(int argc, char* argv[]) {</div><div>&nbsp;char str[] = "ab**cd**e*12";</div><div>&nbsp;printf("str1=%s\n", str);</div><div>&nbsp;printf("str2=%s, count=%d", str, change(str));</div><div>}</div><div>// 终于得到一个比较高效的算法，一个网友提供，估计应该和金山面试官的想法一致。算法如下：</div><div>int change(char *str) {</div><div>&nbsp;int i,j=strlen(str)-1;</div><div>&nbsp;for(i=j; j&gt;=0; j--) {</div><div>&nbsp;&nbsp;if(str!='*') {</div><div>&nbsp;&nbsp; i--;</div><div>&nbsp;&nbsp;} else if(str[j]!='*') {</div><div>&nbsp;&nbsp; str = str[j];</div><div>&nbsp;&nbsp; str[j] = '*';</div><div>&nbsp;&nbsp; i--;</div><div>&nbsp;&nbsp;}</div><div>&nbsp;}</div><div>&nbsp;return i+1;</div><div>}</div><div>17、2005年11月15日华为软件研发笔试题。实现一单链表的逆转。</div><div>#include "stdafx.h"</div><div>typedef char eleType; &nbsp;// 定义链表中的数据类型</div><div>typedef struct listnode &nbsp;{ // 定义单链表结构</div><div>&nbsp;eleType data;</div><div>&nbsp;struct listnode *next;</div><div>}node;</div><div>node *create(int n) { &nbsp;// 创建单链表，n为节点个数</div><div>&nbsp;node *p = (node *)malloc(sizeof(node));</div><div>&nbsp;node *head = p; &nbsp;head-&gt;data = 'A';</div><div>&nbsp;for(int i='B'; i&lt;'A'+n; i++) { &nbsp;&nbsp;</div><div>&nbsp;&nbsp;p = (p-&gt;next = (node *)malloc(sizeof(node)));</div><div>&nbsp;&nbsp;p-&gt;data = i;</div><div>&nbsp;&nbsp;p-&gt;next = NULL;&nbsp;</div><div>&nbsp;}</div><div>&nbsp;return head;</div><div>}</div><div>void print(node *head) { // 按链表顺序输出链表中元素</div><div>&nbsp;for(; head; head = head-&gt;next)</div><div>&nbsp;&nbsp;printf("%c ", head-&gt;data);</div><div>&nbsp;printf("\n");</div><div>}</div><div>node *reverse(node *head, node *pre) { // 逆转单链表函数。这是笔试时需要写的最主要函数</div><div>&nbsp;node *p=head-&gt;next;</div><div>&nbsp;head-&gt;next = pre;</div><div>&nbsp;if(p) return reverse(p, head);</div><div>&nbsp;else &nbsp;return head;</div><div>}</div><div>int main(int argc, char* argv[]) {</div><div>&nbsp;node *head = create(6);</div><div>&nbsp;print(head);</div><div>&nbsp;head = reverse(head, NULL);</div><div>&nbsp;print(head);</div><div>}</div><div>18、编码实现字符串转整型的函数（实现函数atoi的功能），据说是神州数码笔试题。如将字符串 &#8221;+123&#8221;123, &#8221;-0123&#8221;-123, &#8220;123CS45&#8221;123, &#8220;123.45CS&#8221;123, &#8220;CS123.45&#8221;0</div><div>#include "stdafx.h"</div><div>int str2int(const char *str) { &nbsp; &nbsp;// 字符串转整型函数</div><div>&nbsp;int i=0, sign=1, value = 0;</div><div>&nbsp;if(str==NULL) &nbsp;return NULL; &nbsp; &nbsp;// 空串直接返回 NULL</div><div>&nbsp;if(str[0]=='-' || str[0]=='+') { &nbsp; // 判断是否存在符号位</div><div>&nbsp;&nbsp;i = 1;</div><div>&nbsp;&nbsp;sign = (str[0]=='-' ? -1 : 1);</div><div>&nbsp;}</div><div>&nbsp;for(; str&gt;='0' &amp;&amp; str&lt;='9'; i++) // 如果是数字，则继续转换</div><div>&nbsp;&nbsp;value = value * 10 + (str - '0');</div><div>&nbsp;return sign * value;</div><div>}</div><div>int main(int argc, char *argv[]) {</div><div>&nbsp;char *str = "-123.45CS67";</div><div>&nbsp;int &nbsp;val &nbsp;= str2int(str);</div><div>&nbsp;printf("str=%s\tval=%d\n", str, val);</div><div>}</div><div>19、歌德巴赫猜想。任何一个偶数都可以分解为两个素数之和。（其实这是个C二级考试的模拟试题）</div><div>#include "stdafx.h"</div><div>#include "math.h"</div><div>int main(int argc, char* argv[]) {</div><div>&nbsp;int Even=78, Prime1, Prime2, Tmp1, Tmp2;</div><div>&nbsp;for(Prime1=3; Prime1&lt;=Even/2; Prime1+=2) {</div><div>&nbsp;&nbsp;for(Tmp1=2,Tmp2=sqrt(float(Prime1)); Tmp1&lt;=Tmp2 &amp;&amp; Prime1%Tmp1 != 0; Tmp1++);</div><div>&nbsp;&nbsp;if(Tmp1&lt;=Tmp2) continue;</div><div>&nbsp;&nbsp;Prime2 = Even-Prime1;</div><div>&nbsp;&nbsp;for(Tmp1=2,Tmp2=sqrt(float(Prime2)); Tmp1&lt;=Tmp2 &amp;&amp; Prime2%Tmp1 != 0; Tmp1++);</div><div>&nbsp;&nbsp;if(Tmp1&lt;=Tmp2) continue;</div><div>&nbsp;&nbsp;printf("%d=%d+%d\n", Even, Prime1, Prime2);</div><div>&nbsp;}</div><div>}</div><div>20、快速排序（东软喜欢考类似的算法填空题，又如堆排序的算法等）</div><div>#include "stdafx.h"</div><div>#define N 10</div><div>int part(int list[], int low, int high) { &nbsp;// 一趟排序，返回分割点位置</div><div>&nbsp;int tmp = list[low];</div><div>&nbsp;while(low&lt;high) {</div><div>&nbsp;&nbsp;while(low&lt;high &amp;&amp; list[high]&gt;=tmp) --high;</div><div>&nbsp;&nbsp;list[low] = list[high];</div><div>&nbsp;&nbsp;while(low&lt;high &amp;&amp; list[low]&lt;=tmp) &nbsp;++low;</div><div>&nbsp;&nbsp;list[high] = list[low];</div><div>&nbsp;}</div><div>&nbsp;list[low] = tmp;</div><div>&nbsp;return low;</div><div>}</div><div>void QSort(int list[], int low, int high) { // 应用递归进行快速排序</div><div>&nbsp;if(low&lt;high) {</div><div>&nbsp;&nbsp;int mid = part(list, low, high);</div><div>&nbsp;&nbsp;QSort(list, low, mid-1);</div><div>&nbsp;&nbsp;QSort(list, mid+1, high);</div><div>&nbsp;}</div><div>}</div><div>void show(int list[], int n) { &nbsp; &nbsp;// 输出列表中元素</div><div>&nbsp;for(int i=0; i&lt;n; i++)</div><div>&nbsp;&nbsp;printf("%d ", list);</div><div>&nbsp;printf("\n");</div><div>}</div><div>int main(int argc, char* argv[]) {</div><div>&nbsp;int list[N] = {23, 65, 26, 1, 6, 89, 3, 12, 33, 8};</div><div>&nbsp;show(list, N); &nbsp; &nbsp; &nbsp;// 输出排序前序列</div><div>&nbsp;QSort(list, 0, N-1); &nbsp; &nbsp; // 快速排序</div><div>&nbsp;show(list, N); &nbsp; &nbsp; &nbsp;// 输出排序后序列</div><div>}</div><div>21、2005年11月23日慧通笔试题：写一函数判断某个整数是否为回文数，如12321为回文数。可以用判断入栈和出栈是否相同来实现（略微复杂些），这里是将整数逆序后形成另一整数，判断两个整数是否相等来实现的。</div><div>#include "stdafx.h"</div><div>int IsEchoNum(int num) {</div><div>&nbsp;int tmp = 0;</div><div>&nbsp;for(int n = num; n; n/=10)</div><div>&nbsp;&nbsp;tmp = tmp *10 + n%10;</div><div>&nbsp;return tmp==num;</div><div>}</div><div>int main(int argc, char* argv[]) {</div><div>&nbsp;int num = 12321;</div><div>&nbsp;printf("%d &nbsp;%d\n", num, IsEchoNum(num));</div><div>}</div><div>22、删除字符串中的数字并压缩字符串（神州数码以前笔试题），如字符串&#8221;abc123de4fg56&#8221;处理后变为&#8221;abcdefg&#8221;。注意空间和效率。（下面的算法只需要一次遍历，不需要开辟新空间，时间复杂度为O(N)）</div><div>#include "stdafx.h"</div><div>void delNum(char *str) {</div><div>&nbsp;int i, j=0;</div><div>// 找到串中第一个数字的位子</div><div>&nbsp;for(i=j=0; str &amp;&amp; (str&lt;'0' || str&gt;'9'); j=++i);</div><div>&nbsp;</div><div>&nbsp;// 从串中第一个数字的位置开始，逐个放入后面的非数字字符</div><div>&nbsp;for(; str; i++) &nbsp;</div><div>&nbsp;&nbsp;if(str&lt;'0' || str&gt;'9')</div><div>&nbsp;&nbsp; str[j++] = str;</div><div>&nbsp;str[j] = '\0';</div><div>}</div><div>int main(int argc, char* argv[]) {</div><div>&nbsp;char str[] = "abc123ef4g4h5";</div><div>&nbsp;printf("%s\n", str);</div><div>&nbsp;delNum(str);</div><div>&nbsp;printf("%s\n", str);</div><div>}</div><div>23、求两个串中的第一个最长子串（神州数码以前试题）。如"abractyeyt","dgdsaeactyey"的最大子串为"actyet"。</div><div>#include "stdafx.h"</div><div>char *MaxSubString(char *str1, char *str2) {</div><div>&nbsp;int i, j, k, index, max=0;</div><div>&nbsp;for(i=0; str1; i++)</div><div>&nbsp;&nbsp;for(j=0; str2[j]; j++) {</div><div>&nbsp;&nbsp; for(k=0; str1[i+k]==str2[j+k] &amp;&amp; (str2[i+k] || str1[i+k]); k++);</div><div>&nbsp;&nbsp; if(k&gt;max) { &nbsp;// 出现大于当前子串长度的子串，则替换子串位置和程度</div><div>&nbsp;&nbsp; &nbsp;index = j; max = k;</div><div>&nbsp;&nbsp; }</div><div>&nbsp;&nbsp;}</div><div>&nbsp;char *strResult = (char *)calloc(sizeof(char), max+1);</div><div>&nbsp;for(i=0; i&lt;max; i++)&nbsp;</div><div>&nbsp;&nbsp;strResult = str2[index++];</div><div>&nbsp;return strResult;</div><div>}</div><div>int main(int argc, char* argv[]) {</div><div>&nbsp;char str1[] = "abractyeyt", str2[] = "dgdsaeactyey";</div><div>&nbsp;char *strResult = MaxSubString(str1, str2);</div><div>&nbsp;printf("str1=%s\nstr2=%s\nMaxSubString=%s\n", str1, str2, strResult);</div><div>}</div><div>24、不开辟用于交换数据的临时空间，如何完成字符串的逆序(在技术一轮面试中，有些面试官会这样问)</div><div>#include "stdafx.h"</div><div>void change(char *str) {</div><div>&nbsp;for(int i=0,j=strlen(str)-1; i&lt;j; i++, j--){</div><div>&nbsp;&nbsp;str ^= str[j] ^= str ^= str[j];</div><div>&nbsp;}</div><div>}</div><div>int main(int argc, char* argv[]) {</div><div>&nbsp;char str[] = "abcdefg";</div><div>&nbsp;printf("strSource=%s\n", str);</div><div>&nbsp;change(str);</div><div>&nbsp;printf("strResult=%s\n", str);</div><div>&nbsp;return getchar();</div><div>}</div><div>25、删除串中指定的字符（做此题时，千万不要开辟新空间，否则面试官可能认为你不适合做嵌入式开发）</div><div>#include "stdafx.h"</div><div>void delChar(char *str, char c) {</div><div>&nbsp;int i, j=0;</div><div>&nbsp;for(i=0; str; i++)</div><div>&nbsp;&nbsp;if(str!=c) str[j++]=str;</div><div>&nbsp;str[j] = '\0';</div><div>}</div><div>int main(int argc, char* argv[]) {</div><div>&nbsp;char str[] = "abcdefgh"; // 注意，此处不能写成char *str = "abcdefgh";</div><div>&nbsp;printf("%s\n", str);</div><div>&nbsp;delChar(str, 'c');</div><div>&nbsp;printf("%s\n", str);</div><div>}</div><div>26、判断单链表中是否存在环（网上说的笔试题）</div><div>#include "stdafx.h"</div><div>typedef char eleType; &nbsp; &nbsp;// 定义链表中的数据类型</div><div>typedef struct listnode &nbsp;{ &nbsp; // 定义单链表结构</div><div>&nbsp;eleType data;</div><div>&nbsp;struct listnode *next;</div><div>}node;</div><div>node *create(int n) { &nbsp; &nbsp;// 创建单链表，n为节点个数</div><div>&nbsp;node *p = (node *)malloc(sizeof(node));</div><div>&nbsp;node *head = p; &nbsp;head-&gt;data = 'A';</div><div>&nbsp;for(int i='B'; i&lt;'A'+n; i++) {</div><div>&nbsp;&nbsp;p = (p-&gt;next = (node *)malloc(sizeof(node)));</div><div>&nbsp;&nbsp;p-&gt;data = i;</div><div>&nbsp;&nbsp;p-&gt;next = NULL;</div><div>&nbsp;}</div><div>&nbsp;return head;</div><div>}</div><div>void addCircle(node *head, int n) { // 增加环，将链尾指向链中第n个节点</div><div>&nbsp;node *q, *p = head;</div><div>&nbsp;for(int i=1; p-&gt;next; i++) {</div><div>&nbsp;&nbsp;if(i==n) q = p;</div><div>&nbsp;&nbsp;p = p-&gt;next;</div><div>&nbsp;}</div><div>&nbsp;p-&gt;next = q;</div><div>}</div><div>int isCircle(node *head) { &nbsp; // 这是笔试时需要写的最主要函数，其他函数可以不写</div><div>&nbsp;node *p=head,*q=head;</div><div>&nbsp;while( p-&gt;next &amp;&amp; q-&gt;next) {</div><div>&nbsp;&nbsp;p = p-&gt;next;</div><div>&nbsp;&nbsp;if (NULL == (q=q-&gt;next-&gt;next)) return 0;</div><div>&nbsp;&nbsp;if (p == q) return 1;</div><div>&nbsp;}</div><div>&nbsp;return 0;</div><div>}</div><div>int main(int argc, char* argv[]) {</div><div>&nbsp;node *head = create(12);</div><div>&nbsp;addCircle(head, 8); &nbsp; // 注释掉此行，连表就没有环了</div><div>&nbsp;printf("%d\n", isCircle(head));</div><div>}</div><div>from：</div><div>http://blog.chinaunix.net/u2/67780/showart.php?id=2077586</div><div><br></div>
<img src ="http://www.cppblog.com/beautykingdom/aggbug/101050.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2009-11-16 12:18 <a href="http://www.cppblog.com/beautykingdom/archive/2009/11/16/101050.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>ZZ算法101题目&lt;转&gt;</title><link>http://www.cppblog.com/beautykingdom/archive/2009/11/03/100073.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Tue, 03 Nov 2009 12:12:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2009/11/03/100073.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/100073.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2009/11/03/100073.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/100073.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/100073.html</trackback:ping><description><![CDATA[<div style="MARGIN: 15px" id=art width="100%">
<div><font size=3>1. Given a rectangular (cuboidal for the puritans) cake with a rectangular piece removed (any size or orientation), how would you cut the remainder of the cake into two equal halves with one straight cut of a knife ? </font></div>
<div><font size=3>2. You're given an array containing both positive and negative integers and required to find the sub-array with the largest sum (O(N) a la KBL). Write a routine in C for the above. </font></div>
<div><font size=3>3. Given an array of size N in which every number is between 1 and N, determine if there are any duplicates in it. You are allowed to destroy the array if you like. [ I ended up giving about 4 or 5 different solutions for this, each supposedly better than the others ]. </font></div>
<div><font size=3>4. Write a routine to draw a circle (x ** 2 + y ** 2 = r ** 2) without making use of any floating point computations at all. [ This one had me stuck for quite some time and I first gave a solution that did have floating point computations ]. </font></div>
<div><font size=3>5. Given only putchar (no sprintf, itoa, etc.) write a routine putlong that prints out an unsigned long in decimal. [ I gave the obvious solution of taking % 10 and / 10, which gives us the decimal value in reverse order. This requires an array since we need to print it out in the correct order. The interviewer wasn't too pleased and asked me to give a solution which didn't need the array ]. </font></div>
<div><font size=3>6. Give a one-line C expression to test whether a number is a power of 2. [No loops allowed - it's a simple test.] </font></div>
<div><font size=3>7. Given an array of characters which form a sentence of words, give an efficient algorithm to reverse the order of the words (not characters) in it. </font></div>
<div><font size=3>(abc)'=a'b'c' </font></div>
<div><font size=3>8. How many points are there on the globe where by walking one mile south, one mile east and one mile north you reach the place where you started. </font></div>
<div><font size=3>9. Give a very good method to count the number of ones in a "n" (e.g. 32) bit number. </font></div>
<div><font size=3>ANS. Given below are simple solutions, find a solution that does it in log (n) steps. </font></div>
<div><br><font size=3>Iterativefunction iterativecount (unsigned int n)beginint count=0;while (n)begincount += n &amp; 0x1 ;n &gt;&gt;= 1;endreturn count;endSparse Countfunction sparsecount (unsigned int n)beginint count=0;while (n)begincount++;n &amp;= (n-1);endreturn count ;end<br>10. What are the different ways to implement a condition where the value of x can be either a 0 or a 1. Apparently the if then else solution has a jump when written out in assembly. if (x == 0) y=a else y=b There is a logical, arithmetic and a data structure solution to the above problem. </font></div>
<div><font size=3>11. Reverse a linked list. </font></div>
<div><font size=3>12. Insert in a sorted list </font></div>
<div><font size=3>13. In a X's and 0's game (i.e. TIC TAC TOE) if you write a program for this give a fast way to generate the moves by the computer. I mean this should be the fastest way possible. </font></div>
<div><font size=3>The answer is that you need to store all possible configurations of the board and the move that is associated with that. Then it boils down to just accessing the right element and getting the corresponding move for it. Do some analysis and do some more optimization in storage since otherwise it becomes infeasible to get the required storage in a DOS machine. </font></div>
<div><font size=3>14. I was given two lines of assembly code which found the absolute value of a number stored in two's complement form. I had to recognize what the code was doing. Pretty simple if you know some assembly and some fundaes on number representation. </font></div>
<div><font size=3>15. Give a fast way to multiply a number by 7. </font></div>
<div><font size=3>16. How would go about finding out where to find a book in a library. (You don't know how exactly the books are organized beforehand). </font></div>
<div><font size=3>17. Linked list manipulation. </font></div>
<div><font size=3>18. Tradeoff between time spent in testing a product and getting into the market first. </font></div>
<div><font size=3>19. What to test for given that there isn't enough time to test everything you want to. </font></div>
<div><font size=3>20. First some definitions for this problem: a) An ASCII character is one byte long and the most significant bit in the byte is always '0'. b) A Kanji character is two bytes long. The only characteristic of a Kanji character is that in its first byte the most significant bit is '1'. </font></div>
<div><font size=3>Now you are given an array of a characters (both ASCII and Kanji) and, an index into the array. The index points to the start of some character. Now you need to write a function to do a backspace (i.e. delete the character before the given index). </font></div>
<div><font size=3>21. Delete an element from a doubly linked list. </font></div>
<div><font size=3>22. Write a function to find the depth of a binary tree. </font></div>
<div><font size=3>23. Given two strings S1 and S2. Delete from S2 all those characters which occur in S1 also and finally create a clean S2 with the relevant characters deleted. </font></div>
<div><font size=3>24. Assuming that locks are the only reason due to which deadlocks can occur in a system. What would be a foolproof method of avoiding deadlocks in the system. </font></div>
<div><font size=3>25. Reverse a linked list. </font></div>
<div><font size=3>Ans: Possible answers - </font></div>
<div><font size=3>iterative loop <br>curr-&gt;next = prev; <br>prev = curr; <br>curr = next; <br>next = curr-&gt;next <br>endloop </font></div>
<div><font size=3>recursive reverse(ptr) <br>if (ptr-&gt;next == NULL) <br>return ptr; <br>temp = reverse(ptr-&gt;next); <br>temp-&gt;next = ptr; <br>return ptr; <br>end </font></div>
<div><br><font size=3>26. Write a small lexical analyzer - interviewer gave tokens. expressions like "a*b" etc. </font></div>
<div><font size=3>27. Besides communication cost, what is the other source of inefficiency in RPC? (answer : context switches, excessive buffer copying). How can you optimize the communication? (ans : communicate through shared memory on same machine, bypassing the kernel _ A Univ. of Wash. thesis) </font></div>
<div><font size=3>28. Write a routine that prints out a 2-D array in spiral order! </font></div>
<div><font size=3>29. How is the readers-writers problem solved? - using semaphores/ada .. etc. </font></div>
<div><font size=3>30. Ways of optimizing symbol table storage in compilers. </font></div>
<div><font size=3>31. A walk-through through the symbol table functions, lookup() implementation etc. - The interviewer was on the Microsoft C team. </font></div>
<div><font size=3>32. A version of the "There are three persons X Y Z, one of which always lies".. etc.. </font></div>
<div><font size=3>33. There are 3 ants at 3 corners of a triangle, they randomly start moving towards another corner.. what is the probability that they don't collide. </font></div>
<div><font size=3>34. Write an efficient algorithm and C code to shuffle a pack of cards.. this one was a feedback process until we came up with one with no extra storage. </font></div>
<div><font size=3>35. The if (x == 0) y = 0 etc.. </font></div>
<div><font size=3>36. Some more bitwise optimization at assembly level </font></div>
<div><font size=3>37. Some general questions on Lex, Yacc etc. </font></div>
<div><font size=3>38. Given an array t[100] which contains numbers between 1..99. Return the duplicated value. Try both O(n) and O(n-square). </font></div>
<div><font size=3>39. Given an array of characters. How would you reverse it. ? How would you reverse it without using indexing in the array. </font></div>
<div><font size=3>40. Given a sequence of characters. How will you convert the lower case characters to upper case characters. ( Try using bit vector - solutions given in the C lib -typec.h) </font></div>
<div><font size=3>41. Fundamentals of RPC. </font></div>
<div><font size=3>42. Given a linked list which is sorted. How will u insert in sorted way. </font></div>
<div><font size=3>43. Given a linked list How will you reverse it. </font></div>
<div><font size=3>44. Give a good data structure for having n queues ( n not fixed) in a finite memory segment. You can have some data-structure separate for each queue. Try to use at least 90% of the memory space. </font></div>
<div><font size=3>45. Do a breadth first traversal of a tree. </font></div>
<div><font size=3>46. Write code for reversing a linked list. </font></div>
<div><font size=3>47. Write, efficient code for extracting unique elements from a sorted list of array. e.g. (1, 1, 3, 3, 3, 5, 5, 5, 9, 9, 9, 9) -&gt; (1, 3, 5, 9). </font></div>
<div><font size=3>48. Given an array of integers, find the contiguous sub-array with the largest sum. </font></div>
<div><font size=3>ANS. Can be done in O(n) time and O(1) extra space. Scan array from 1 to n. Remember the best sub-array seen so far and the best sub-array ending in i. </font></div>
<div><font size=3>49. Given an array of length N containing integers between 1 and N, determine if it contains any duplicates. </font></div>
<div><font size=3>ANS. [Is there an O(n) time solution that uses only O(1) extra space and does not destroy the original array?] </font></div>
<div><font size=3>50. Sort an array of size n containing integers between 1 and K, given a temporary scratch integer array of size K. </font></div>
<div><font size=3>ANS. Compute cumulative counts of integers in the auxiliary array. Now scan the original array, rotating cycles! [Can someone word this more nicely?] </font></div>
<div><font size=3>* 51. An array of size k contains integers between 1 and n. You are given an additional scratch array of size n. Compress the original array by removing duplicates in it. What if k &lt;&lt; n? </font></div>
<div><font size=3>ANS. Can be done in O(k) time i.e. without initializing the auxiliary array! </font></div>
<div><font size=3>52. An array of integers. The sum of the array is known not to overflow an integer. Compute the sum. What if we know that integers are in 2's complement form? </font></div>
<div><font size=3>ANS. If numbers are in 2's complement, an ordinary looking loop like for(i=total=0;i&lt; n;total+=array[i++]); will do. No need to check for overflows! </font></div>
<div><font size=3>53. An array of characters. Reverse the order of words in it. </font></div>
<div><font size=3>ANS. Write a routine to reverse a character array. Now call it for the given array and for each word in it. </font></div>
<div><font size=3>* 54. An array of integers of size n. Generate a random permutation of the array, given a function rand_n() that returns an integer between 1 and n, both inclusive, with equal probability. What is the expected time of your algorithm? </font></div>
<div><font size=3>ANS. "Expected time" should ring a bell. To compute a random permutation, use the standard algorithm of scanning array from n downto 1, swapping i-th element with a uniformly random element &lt;= i-th. To compute a uniformly random integer between 1 and k (k &lt; n), call rand_n() repeatedly until it returns a value in the desired range. </font></div>
<div><font size=3>55. An array of pointers to (very long) strings. Find pointers to the (lexicographically) smallest and largest strings. </font></div>
<div><font size=3>ANS. Scan array in pairs. Remember largest-so-far and smallest-so-far. Compare the larger of the two strings in the current pair with largest-so-far to update it. And the smaller of the current pair with the smallest-so-far to update it. For a total of &lt;= 3n/2 strcmp() calls. That's also the lower bound. </font></div>
<div><font size=3>56. Write a program to remove duplicates from a sorted array. </font></div>
<div><font size=3>ANS. int remove_duplicates(int * p, int size) <br>{ <br>int current, insert = 1; <br>for (current=1; current &lt; size; current++) <br>if (p[current] != p[insert-1]) <br>{ <br>p[insert] = p[current]; <br>current++; <br>insert++; <br>} else <br>current++; </font></div>
<div><font size=3>return insert; </font></div>
<div><font size=3>} </font></div>
<div><font size=3>57. C++ ( what is virtual function ? what happens if an error occurs in constructor or destructor. Discussion on error handling, templates, unique features of C++. What is different in C++, ( compare with unix). </font></div>
<div><font size=3>58. Given a list of numbers ( fixed list) Now given any other list, how can you efficiently find out if there is any element in the second list that is an element of the first list (fixed list). </font></div>
<div><font size=3>59. Given 3 lines of assembly code : find it is doing. IT was to find absolute value. </font></div>
<div><font size=3>60. If you are on a boat and you throw out a suitcase, Will the level of water increase. </font></div>
<div><font size=3>61. Print an integer using only putchar. Try doing it without using extra storage. </font></div>
<div><font size=3>62. Write C code for (a) deleting an element from a linked list (b) traversing a linked list </font></div>
<div><font size=3>63. What are various problems unique to distributed databases </font></div>
<div><font size=3>64. Declare a void pointer ANS. void *ptr; </font></div>
<div><font size=3>65. Make the pointer aligned to a 4 byte boundary in a efficient manner ANS. Assign the pointer to a long number and the number with 11...1100 add 4 to the number </font></div>
<div><font size=3>66. What is a far pointer (in DOS) </font></div>
<div><font size=3>67. What is a balanced tree </font></div>
<div><font size=3>68. Given a linked list with the following property node2 is left child of node1, if node2 &lt; node1 else, it is the right child. </font></div>
<div><font size=3>&nbsp;O P||O A||O B||O C<br>How do you convert the above linked list to the form without disturbing the property. Write C code for that. </font></div>
<div><font size=3>&nbsp;&nbsp;&nbsp;O P||O B/ \/&nbsp;&nbsp; \/&nbsp;&nbsp;&nbsp;&nbsp; \O ?&nbsp;&nbsp;&nbsp;&nbsp; O ?<br>determine where do A and C go </font></div>
<div><font size=3>69. Describe the file system layout in the UNIX OS </font></div>
<div><font size=3>ANS. describe boot block, super block, inodes and data layout </font></div>
<div><font size=3>70. In UNIX, are the files allocated contiguous blocks of data </font></div>
<div><font size=3>ANS. no, they might be fragmented </font></div>
<div><font size=3>How is the fragmented data kept track of </font></div>
<div><font size=3>ANS. Describe the direct blocks and indirect blocks in UNIX file system </font></div>
<div><font size=3>71. Write an efficient C code for 'tr' program. 'tr' has two command line arguments. They both are strings of same length. tr reads an input file, replaces each character in the first string with the corresponding character in the second string. eg. 'tr abc xyz' replaces all 'a's by 'x's, 'b's by 'y's and so on. ANS. <br>a) have an array of length 26. <br>put 'x' in array element corr to 'a' <br>put 'y' in array element corr to 'b' <br>put 'z' in array element corr to 'c' <br>put 'd' in array element corr to 'd' <br>put 'e' in array element corr to 'e' <br>and so on. </font></div>
<div><font size=3>the code <br>while (!eof) <br>{ <br>c = getc(); <br>putc(array[c - 'a']); <br>} </font></div>
<div><font size=3>72. what is disk interleaving </font></div>
<div><font size=3>73. why is disk interleaving adopted </font></div>
<div><font size=3>74. given a new disk, how do you determine which interleaving is the best a) give 1000 read operations with each kind of interleaving determine the best interleaving from the statistics </font></div>
<div><font size=3>75. draw the graph with performance on one axis and 'n' on another, where 'n' in the 'n' in n-way disk interleaving. (a tricky question, should be answered carefully) </font></div>
<div><font size=3>76. I was a c++ code and was asked to find out the bug in that. The bug was that he declared an object locally in a function and tried to return the pointer to that object. Since the object is local to the function, it no more exists after returning from the function. The pointer, therefore, is invalid outside. </font></div>
<div><font size=3>77. A real life problem - A square picture is cut into 16 squares and they are shuffled. Write a program to rearrange the 16 squares to get the original big square. </font></div>
<div><font size=3>78. <br>int *a; <br>char *c; <br>*(a) = 20; <br>*c = *a; <br>printf("%c",*c); </font></div>
<div><font size=3>what is the output? </font></div>
<div><font size=3>79. Write a program to find whether a given m/c is big-endian or little-endian! </font></div>
<div><font size=3>80. What is a volatile variable? </font></div>
<div><font size=3>81. What is the scope of a static function in C ? </font></div>
<div><font size=3>82. What is the difference between "malloc" and "calloc"? </font></div>
<div><font size=3>83. struct n { int data; struct n* next}node; <br>node *c,*t; <br>c-&gt;data = 10; <br>t-&gt;next = null; <br>*c = *t; <br>what is the effect of the last statement? </font></div>
<div><font size=3>84. If you're familiar with the ? operator x ? y : z <br>you want to implement that in a function: int cond(int x, int y, int z); using only ~, !, ^, &amp;, +, |, &lt;&lt;, &gt;&gt; no if statements, or loops or anything else, just those operators, and the function should correctly return y or z based on the value of x. You may use constants, but only 8 bit constants. You can cast all you want. You're not supposed to use extra variables, but in the end, it won't really matter, using vars just makes things cleaner. You should be able to reduce your solution to a single line in the end though that requires no extra vars. </font></div>
<div><font size=3>85. You have an abstract computer, so just forget everything you know about computers, this one only does what I'm about to tell you it does. You can use as many variables as you need, there are no negative numbers, all numbers are integers. You do not know the size of the integers, they could be infinitely large, so you can't count on truncating at any point. There are NO comparisons allowed, no if statements or anything like that. There are only four operations you can do on a variable. <br>1) You can set a variable to 0. <br>2) You can set a variable = another variable. <br>3) You can increment a variable (only by 1), and it's a post increment. <br>4) You can loop. So, if you were to say loop(v1) and v1 = 10, your loop would execute 10 times, but the value in v1 wouldn't change so the first line in the loop can change value of v1 without changing the number of times you loop. <br>You need to do 3 things. <br>1) Write a function that decrements by 1. <br>2) Write a function that subtracts one variable from another. <br>3) Write a function that divides one variable by another. <br>4) See if you can implement all 3 using at most 4 variables. Meaning, you're not making function calls now, you're making macros. And at most you can have 4 variables. The restriction really only applies to divide, the other 2 are easy to do with 4 vars or less. Division on the other hand is dependent on the other 2 functions, so, if subtract requires 3 variables, then divide only has 1 variable left unchanged after a call to subtract. Basically, just make your function calls to decrement and subtract so you pass your vars in by reference, and you can't declare any new variables in a function, what you pass in is all it gets. </font></div>
<div><font size=3>* 86. Under what circumstances can one delete an element from a singly linked list in constant time? </font></div>
<div><font size=3>ANS. If the list is circular and there are no references to the nodes in the list from anywhere else! Just copy the contents of the next node and delete the next node. If the list is not circular, we can delete any but the last node using this idea. In that case, mark the last node as dummy! </font></div>
<div><font size=3>* 87. Given a singly linked list, determine whether it contains a loop or not. </font></div>
<div><font size=3>ANS. (a) Start reversing the list. If you reach the head, gotcha! there is a loop! <br>But this changes the list. So, reverse the list again. <br>(b) Maintain two pointers, initially pointing to the head. Advance one of them one node at a time. And the other one, two nodes at a time. If the latter overtakes the former at any time, there is a loop! </font></div>
<div><font size=3>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p1 = p2 = head;do {p1 = p1-&gt;next;p2 = p2-&gt;next-&gt;next;} while (p1 != p2);<br>88. Given a singly linked list, print out its contents in reverse order. Can you do it without using any extra space? </font></div>
<div><font size=3>ANS. Start reversing the list. Do this again, printing the contents. </font></div>
<div><font size=3>89. Given a binary tree with nodes, print out the values in pre-order/in-order/post-order without using any extra space. </font></div>
<div><font size=3>90. Reverse a singly linked list recursively. The function prototype is node * reverse (node *) ; </font></div>
<div><font size=3>ANS. </font></div>
<div><font size=3>&nbsp;&nbsp;&nbsp; node * reverse (node * n){node * m ;if (! (n &amp;&amp; n -&gt; next))return n ;m = reverse (n -&gt; next) ;n -&gt; next -&gt; next = n ;n -&gt; next = NULL ;return m ;}<br>91. Given a singly linked list, find the middle of the list. </font></div>
<div><font size=3>HINT. Use the single and double pointer jumping. Maintain two pointers, initially pointing to the head. Advance one of them one node at a time. And the other one, two nodes at a time. When the double reaches the end, the single is in the middle. This is not asymptotically faster but seems to take less steps than going through the list twice. </font></div>
<div><font size=3>92. Reverse the bits of an unsigned integer. </font></div>
<div><font size=3>ANS. </font></div>
<div><font size=3>&nbsp;&nbsp;&nbsp; #define reverse(x)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \(x=x&gt;&gt;16|(0x0000ffff&amp;x)&lt;&lt;16,&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \x=(0xff00ff00&amp;x)&gt;&gt;8|(0x00ff00ff&amp;x)&lt;&lt;8, \x=(0xf0f0f0f0&amp;x)&gt;&gt;4|(0x0f0f0f0f&amp;x)&lt;&lt;4, \x=(0xcccccccc&amp;x)&gt;&gt;2|(0x33333333&amp;x)&lt;&lt;2, \x=(0xaaaaaaaa&amp;x)&gt;&gt;1|(0x55555555&amp;x)&lt;&lt;1)<br>* 93. Compute the number of ones in an unsigned integer. </font></div>
<div><font size=3>ANS. </font></div>
<div><font size=3>&nbsp;&nbsp; #define count_ones(x)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; \(x=(0xaaaaaaaa&amp;x)&gt;&gt;1+(0x55555555&amp;x), \x=(0xcccccccc&amp;x)&gt;&gt;2+(0x33333333&amp;x), \x=(0xf0f0f0f0&amp;x)&gt;&gt;4+(0x0f0f0f0f&amp;x), \x=(0xff00ff00&amp;x)&gt;&gt;8+(0x00ff00ff&amp;x), \x=x&gt;&gt;16+(0x0000ffff&amp;x))<br>94. Compute the discrete log of an unsigned integer. </font></div>
<div><font size=3>ANS. </font></div>
<div><font size=3>#define discrete_log(h) \(h=(h&gt;&gt;1)|(h&gt;&gt;2), \h|=(h&gt;&gt;2), \h|=(h&gt;&gt;4), \h|=(h&gt;&gt;8), \h|=(h&gt;&gt;16), \h=(0xaaaaaaaa&amp;h)&gt;&gt;1+(0x55555555&amp;h), \h=(0xcccccccc&amp;h)&gt;&gt;2+(0x33333333&amp;h), \h=(0xf0f0f0f0&amp;h)&gt;&gt;4+(0x0f0f0f0f&amp;h), \h=(0xff00ff00&amp;h)&gt;&gt;8+(0x00ff00ff&amp;h), \h=(h&gt;&gt;16)+(0x0000ffff&amp;h))<br>If I understand it right, log2(2) =1, log2(3)=1, log2(4)=2..... But this macro does not work out log2(0) which does not exist! How do you think it should be handled? </font></div>
<div><font size=3>* 95. How do we test most simply if an unsigned integer is a power of two? </font></div>
<div><font size=3>ANS. #define power_of_two(x) \ ((x)&amp;&amp;(~(x&amp;(x-1)))) </font></div>
<div><font size=3>96. Set the highest significant bit of an unsigned integer to zero. </font></div>
<div><font size=3>ANS. (from Denis Zabavchik) Set the highest significant bit of an unsigned integer to zero <br>#define zero_most_significant(h) \ <br>(h&amp;=(h&gt;&gt;1)|(h&gt;&gt;2), \ <br>h|=(h&gt;&gt;2), \ <br>h|=(h&gt;&gt;4), \ <br>h|=(h&gt;&gt;8), \ <br>h|=(h&gt;&gt;16)) </font></div>
<div><font size=3>97. Let f(k) = y where k is the y-th number in the increasing sequence of non-negative integers with the same number of ones in its binary representation as y, e.g. f(0) = 1, f(1) = 1, f(2) = 2, f(3) = 1, f(4) = 3, f(5) = 2, f(6) = 3 and so on. Given k &gt;= 0, compute f(k). </font></div>
<div><font size=3>98. A character set has 1 and 2 byte characters. One byte characters have 0 as the first bit. You just keep accumulating the characters in a buffer. Suppose at some point the user types a backspace, how can you remove the character efficiently. (Note: You cant store the last character typed because the user can type in arbitrarily many backspaces) </font></div>
<div><font size=3>99. What is the simples way to check if the sum of two unsigned integers has resulted in an overflow. </font></div>
<div><font size=3>100. How do you represent an n-ary tree? Write a program to print the nodes of such a tree in breadth first order. </font></div>
<div><font size=3>101. Write the 'tr' program of UNIX. Invoked as </font></div>
<div><font size=3>tr -str1 -str2. It reads stdin and prints it out to stdout, replacing every occurance of str1[i] with str2[i]. </font></div>
<div><font size=3>e.g. tr -abc -xyz <br>to be and not to be &lt;- input <br>to ye xnd not to ye &lt;- output</font> </div>
<div>&nbsp;</div>
<div>本文来自CSDN博客，转载请标明出处：<a href="http://blog.csdn.net/clearriver/archive/2009/08/04/4409465.aspx"><u><font color=#0000ff>http://blog.csdn.net/clearriver/archive/2009/08/04/4409465.aspx</font></u></a></div>
</div>
<img src ="http://www.cppblog.com/beautykingdom/aggbug/100073.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2009-11-03 20:12 <a href="http://www.cppblog.com/beautykingdom/archive/2009/11/03/100073.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>最大公约数(Gcd)两种算法(Euclid &amp;&amp; Stein)&lt;转&gt;</title><link>http://www.cppblog.com/beautykingdom/archive/2009/05/31/86299.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Sun, 31 May 2009 11:09:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2009/05/31/86299.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/86299.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2009/05/31/86299.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/86299.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/86299.html</trackback:ping><description><![CDATA[转自：：：：：<a href="http://blog.chinaunix.net/u2/76292/showart_1418158.html">http://blog.chinaunix.net/u2/76292/showart_1418158.html</a><br>1. 欧几里德算法和扩展欧几里德算法
<p>欧几里德算法 <br>欧几里德算法又称辗转相除法，用于计算两个整数a,b的最大公约数。其计算原理依赖于下面的定理： </p>
<p>定理：gcd(a,b) = gcd(b,a mod b) </p>
<p>证明：a可以表示成a = kb + r，则r = a mod b <br>假设d是a,b的一个公约数，则有 <br>d|a, d|b，而r = a - kb，因此d|r <br>因此d是(b,a mod b)的公约数 </p>
<p>假设d 是(b,a mod b)的公约数，则 <br>d | b , d |r ，但是a = kb +r <br>因此d也是(a,b)的公约数 </p>
<p>因此(a,b)和(b,a mod b)的公约数是一样的，其最大公约数也必然相等，得证 </p>
<p>欧几里德算法就是根据这个原理来做的，其算法用C++语言描述为： </p>
<div style="BORDER-RIGHT: rgb(204,204,204) 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: rgb(204,204,204) 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: rgb(204,204,204) 1px solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: rgb(204,204,204) 1px solid; BACKGROUND-COLOR: rgb(238,238,238)"><img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: rgb(0,0,255)">int</span><span style="COLOR: rgb(0,0,0)">&nbsp;Gcd(</span><span style="COLOR: rgb(0,0,255)">int</span><span style="COLOR: rgb(0,0,0)">&nbsp;a,&nbsp;</span><span style="COLOR: rgb(0,0,255)">int</span><span style="COLOR: rgb(0,0,0)">&nbsp;b)<br><img id=Codehighlighter1_22_71_Open_Image onclick="this.style.display='none'; Codehighlighter1_22_71_Open_Text.style.display='none'; Codehighlighter1_22_71_Closed_Image.style.display='inline'; Codehighlighter1_22_71_Closed_Text.style.display='inline';" alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_22_71_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_22_71_Closed_Text.style.display='none'; Codehighlighter1_22_71_Open_Image.style.display='inline'; Codehighlighter1_22_71_Open_Text.style.display='inline';" alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_22_71_Closed_Text style="BORDER-RIGHT: rgb(128,128,128) 1px solid; BORDER-TOP: rgb(128,128,128) 1px solid; DISPLAY: none; BORDER-LEFT: rgb(128,128,128) 1px solid; BORDER-BOTTOM: rgb(128,128,128) 1px solid; BACKGROUND-COLOR: rgb(255,255,255)"><img alt="" src="http://www.cnblogs.com/Images/dot.gif"></span><span id=Codehighlighter1_22_71_Open_Text><span style="COLOR: rgb(0,0,0)">{<br><img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: rgb(0,0,255)">if</span><span style="COLOR: rgb(0,0,0)">(b&nbsp;</span><span style="COLOR: rgb(0,0,0)">==</span><span style="COLOR: rgb(0,0,0)">&nbsp;</span><span style="COLOR: rgb(0,0,0)">0</span><span style="COLOR: rgb(0,0,0)">)<br><img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: rgb(0,0,255)">return</span><span style="COLOR: rgb(0,0,0)">&nbsp;a;<br><img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: rgb(0,0,255)">return</span><span style="COLOR: rgb(0,0,0)">&nbsp;Gcd(b,&nbsp;a&nbsp;</span><span style="COLOR: rgb(0,0,0)">%</span><span style="COLOR: rgb(0,0,0)">&nbsp;b);<br><img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span></div>
<br>当然你也可以写成迭代形式：<br>
<div style="BORDER-RIGHT: rgb(204,204,204) 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: rgb(204,204,204) 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: rgb(204,204,204) 1px solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: rgb(204,204,204) 1px solid; BACKGROUND-COLOR: rgb(238,238,238)"><img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: rgb(0,0,255)">int</span><span style="COLOR: rgb(0,0,0)">&nbsp;Gcd(</span><span style="COLOR: rgb(0,0,255)">int</span><span style="COLOR: rgb(0,0,0)">&nbsp;a,&nbsp;</span><span style="COLOR: rgb(0,0,255)">int</span><span style="COLOR: rgb(0,0,0)">&nbsp;b)<br><img id=Codehighlighter1_22_91_Open_Image onclick="this.style.display='none'; Codehighlighter1_22_91_Open_Text.style.display='none'; Codehighlighter1_22_91_Closed_Image.style.display='inline'; Codehighlighter1_22_91_Closed_Text.style.display='inline';" alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_22_91_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_22_91_Closed_Text.style.display='none'; Codehighlighter1_22_91_Open_Image.style.display='inline'; Codehighlighter1_22_91_Open_Text.style.display='inline';" alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_22_91_Closed_Text style="BORDER-RIGHT: rgb(128,128,128) 1px solid; BORDER-TOP: rgb(128,128,128) 1px solid; DISPLAY: none; BORDER-LEFT: rgb(128,128,128) 1px solid; BORDER-BOTTOM: rgb(128,128,128) 1px solid; BACKGROUND-COLOR: rgb(255,255,255)"><img alt="" src="http://www.cnblogs.com/Images/dot.gif"></span><span id=Codehighlighter1_22_91_Open_Text><span style="COLOR: rgb(0,0,0)">{<br><img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: rgb(0,0,255)">while</span><span style="COLOR: rgb(0,0,0)">(b&nbsp;</span><span style="COLOR: rgb(0,0,0)">!=</span><span style="COLOR: rgb(0,0,0)">&nbsp;</span><span style="COLOR: rgb(0,0,0)">0</span><span style="COLOR: rgb(0,0,0)">)<br><img id=Codehighlighter1_40_78_Open_Image onclick="this.style.display='none'; Codehighlighter1_40_78_Open_Text.style.display='none'; Codehighlighter1_40_78_Closed_Image.style.display='inline'; Codehighlighter1_40_78_Closed_Text.style.display='inline';" alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_40_78_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_40_78_Closed_Text.style.display='none'; Codehighlighter1_40_78_Open_Image.style.display='inline'; Codehighlighter1_40_78_Open_Text.style.display='inline';" alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_40_78_Closed_Text style="BORDER-RIGHT: rgb(128,128,128) 1px solid; BORDER-TOP: rgb(128,128,128) 1px solid; DISPLAY: none; BORDER-LEFT: rgb(128,128,128) 1px solid; BORDER-BOTTOM: rgb(128,128,128) 1px solid; BACKGROUND-COLOR: rgb(255,255,255)"><img alt="" src="http://www.cnblogs.com/Images/dot.gif"></span><span id=Codehighlighter1_40_78_Open_Text><span style="COLOR: rgb(0,0,0)">{<br><img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: rgb(0,0,255)">int</span><span style="COLOR: rgb(0,0,0)">&nbsp;r&nbsp;</span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)">&nbsp;b;<br><img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;b&nbsp;</span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)">&nbsp;a&nbsp;</span><span style="COLOR: rgb(0,0,0)">%</span><span style="COLOR: rgb(0,0,0)">&nbsp;b;<br><img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;a&nbsp;</span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)">&nbsp;r;<br><img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: rgb(0,0,0)"><br><img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: rgb(0,0,255)">return</span><span style="COLOR: rgb(0,0,0)">&nbsp;a;<br><img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span></div>
<br>本质上都是用的上面那个原理。<br><br><strong>补充:</strong> 扩展欧几里德算法是用来在已知a, b求解一组p，q使得p * a+q&nbsp; * b = Gcd(a, b)&nbsp; (解一定存在，根据数论中的相关定理)。扩展欧几里德常用在求解模线性方程及方程组中。下面是一个使用C++的实现：<br>
<div style="BORDER-RIGHT: rgb(204,204,204) 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: rgb(204,204,204) 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: rgb(204,204,204) 1px solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: rgb(204,204,204) 1px solid; BACKGROUND-COLOR: rgb(238,238,238)"><img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: rgb(0,0,255)">int</span><span style="COLOR: rgb(0,0,0)">&nbsp;exGcd(</span><span style="COLOR: rgb(0,0,255)">int</span><span style="COLOR: rgb(0,0,0)">&nbsp;a,&nbsp;</span><span style="COLOR: rgb(0,0,255)">int</span><span style="COLOR: rgb(0,0,0)">&nbsp;b,&nbsp;</span><span style="COLOR: rgb(0,0,255)">int</span><span style="COLOR: rgb(0,0,0)">&nbsp;</span><span style="COLOR: rgb(0,0,0)">&amp;</span><span style="COLOR: rgb(0,0,0)">x,&nbsp;</span><span style="COLOR: rgb(0,0,255)">int</span><span style="COLOR: rgb(0,0,0)">&nbsp;</span><span style="COLOR: rgb(0,0,0)">&amp;</span><span style="COLOR: rgb(0,0,0)">y)<br><img id=Codehighlighter1_40_174_Open_Image onclick="this.style.display='none'; Codehighlighter1_40_174_Open_Text.style.display='none'; Codehighlighter1_40_174_Closed_Image.style.display='inline'; Codehighlighter1_40_174_Closed_Text.style.display='inline';" alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_40_174_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_40_174_Closed_Text.style.display='none'; Codehighlighter1_40_174_Open_Image.style.display='inline'; Codehighlighter1_40_174_Open_Text.style.display='inline';" alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_40_174_Closed_Text style="BORDER-RIGHT: rgb(128,128,128) 1px solid; BORDER-TOP: rgb(128,128,128) 1px solid; DISPLAY: none; BORDER-LEFT: rgb(128,128,128) 1px solid; BORDER-BOTTOM: rgb(128,128,128) 1px solid; BACKGROUND-COLOR: rgb(255,255,255)"><img alt="" src="http://www.cnblogs.com/Images/dot.gif"></span><span id=Codehighlighter1_40_174_Open_Text><span style="COLOR: rgb(0,0,0)">{<br><img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: rgb(0,0,255)">if</span><span style="COLOR: rgb(0,0,0)">(b&nbsp;</span><span style="COLOR: rgb(0,0,0)">==</span><span style="COLOR: rgb(0,0,0)">&nbsp;</span><span style="COLOR: rgb(0,0,0)">0</span><span style="COLOR: rgb(0,0,0)">)<br><img id=Codehighlighter1_55_88_Open_Image onclick="this.style.display='none'; Codehighlighter1_55_88_Open_Text.style.display='none'; Codehighlighter1_55_88_Closed_Image.style.display='inline'; Codehighlighter1_55_88_Closed_Text.style.display='inline';" alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockStart.gif" align=top><img id=Codehighlighter1_55_88_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_55_88_Closed_Text.style.display='none'; Codehighlighter1_55_88_Open_Image.style.display='inline'; Codehighlighter1_55_88_Open_Text.style.display='inline';" alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedSubBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span id=Codehighlighter1_55_88_Closed_Text style="BORDER-RIGHT: rgb(128,128,128) 1px solid; BORDER-TOP: rgb(128,128,128) 1px solid; DISPLAY: none; BORDER-LEFT: rgb(128,128,128) 1px solid; BORDER-BOTTOM: rgb(128,128,128) 1px solid; BACKGROUND-COLOR: rgb(255,255,255)"><img alt="" src="http://www.cnblogs.com/Images/dot.gif"></span><span id=Codehighlighter1_55_88_Open_Text><span style="COLOR: rgb(0,0,0)">{<br><img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;x&nbsp;</span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)">&nbsp;</span><span style="COLOR: rgb(0,0,0)">1</span><span style="COLOR: rgb(0,0,0)">;<br><img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;y&nbsp;</span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)">&nbsp;</span><span style="COLOR: rgb(0,0,0)">0</span><span style="COLOR: rgb(0,0,0)">;<br><img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: rgb(0,0,255)">return</span><span style="COLOR: rgb(0,0,0)">&nbsp;a;<br><img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedSubBlockEnd.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;}</span></span><span style="COLOR: rgb(0,0,0)"><br><img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: rgb(0,0,255)">int</span><span style="COLOR: rgb(0,0,0)">&nbsp;r&nbsp;</span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)">&nbsp;exGcd(b,&nbsp;a&nbsp;</span><span style="COLOR: rgb(0,0,0)">%</span><span style="COLOR: rgb(0,0,0)">&nbsp;b,&nbsp;x,&nbsp;y);<br><img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: rgb(0,0,255)">int</span><span style="COLOR: rgb(0,0,0)">&nbsp;t&nbsp;</span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)">&nbsp;x;<br><img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;x&nbsp;</span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)">&nbsp;y;<br><img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;y&nbsp;</span><span style="COLOR: rgb(0,0,0)">=</span><span style="COLOR: rgb(0,0,0)">&nbsp;t&nbsp;</span><span style="COLOR: rgb(0,0,0)">-</span><span style="COLOR: rgb(0,0,0)">&nbsp;a&nbsp;</span><span style="COLOR: rgb(0,0,0)">/</span><span style="COLOR: rgb(0,0,0)">&nbsp;b&nbsp;</span><span style="COLOR: rgb(0,0,0)">*</span><span style="COLOR: rgb(0,0,0)">&nbsp;y;<br><img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top><br><img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: rgb(0,0,255)">return</span><span style="COLOR: rgb(0,0,0)">&nbsp;r;<br><img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span></div>
<br>把这个实现和Gcd的递归实现相比，发现多了下面的x,y赋值过程，这就是扩展欧几里德算法的精髓。<br>可以这样思考:<br>对于a' = b, b' = a % b 而言，我们求得 x, y使得 a'x + b'y = Gcd(a', b')<br>由于b' = a % b = a - a / b * b (注：这里的/是程序设计语言中的除法)<br>那么可以得到:<br>a'x + b'y = Gcd(a', b')&nbsp; ===&gt;<br>bx + (a - a / b * b)y = Gcd(a', b') = Gcd(a, b)&nbsp; ===&gt;<br>ay +b(x - a / b*y) = Gcd(a, b)<br>因此对于a和b而言，他们的相对应的p，q分别是&nbsp;y和(x-a/b*y)<br><br>2. Stein算法 <br>欧几里德算法是计算两个数最大公约数的传统算法，他无论从理论还是从效率上都是很好的。但是他有一个致命的缺陷，这个缺陷只有在大素数时才会显现出来。 <br><br>考虑现在的硬件平台，一般整数最多也就是64位，对于这样的整数，计算两个数之间的模是很简单的。对于字长为32位的平台，计算两个不超过32位的整数的模，只需要一个指令周期，而计算64位以下的整数模，也不过几个周期而已。但是对于更大的素数，这样的计算过程就不得不由用户来设计，为了计算两个超过 64位的整数的模，用户也许不得不采用类似于多位数除法手算过程中的试商法，这个过程不但复杂，而且消耗了很多CPU时间。对于现代密码算法，要求计算 128位以上的素数的情况比比皆是，设计这样的程序迫切希望能够<span style="COLOR: red">抛弃除法和取模</span>。 （<strong>注：</strong>说到抛弃除法和取模，其实辗转相除法可以写成减法的形式)<br><br>Stein算法由J. Stein 1961年提出，这个方法也是计算两个数的最大公约数。和欧几里德算法 算法不同的是，Stein算法只有整数的移位和加减法，这对于程序设计者是一个福音。 <br><br>为了说明Stein算法的正确性，首先必须注意到以下结论： <br><br>gcd(a,a) = a，也就是一个数和他自身的公约数是其自身 <br>gcd(ka,kb) = k gcd(a,b)，也就是最大公约数运算和倍乘运算可以交换，特殊的，当k=2时，说明两个偶数的最大公约数必然能被2整除。<br><br>
<p>有了上述规律就可以给出Stein算法如下： </p>
<p>如果A=0，B是最大公约数，算法结束 <br>如果B=0，A是最大公约数，算法结束 <br>设置A1 = A、B1=B和C1 = 1 <br>如果An和Bn都是偶数，则An+1 =An /2，Bn+1 =Bn /2，Cn+1 =Cn *2(注意，乘2只要把整数左移一位即可，除2只要把整数右移一位即可) <br>如果An是偶数，Bn不是偶数，则An+1 =An /2，Bn+1 =Bn ，Cn+1 =Cn (很显然啦，2不是奇数的约数) <br>如果Bn是偶数，An不是偶数，则Bn+1 =Bn /2，An+1 =An ，Cn+1 =Cn (很显然啦，2不是奇数的约数) <br>如果An和Bn都不是偶数，则An+1 =|An -Bn|，Bn+1 =min(An,Bn)，Cn+1 =Cn <br>n++，转4 <br>这个算法的原理很显然，所以就不再证明了。现在考察一下该算法和欧几里德方法效率上的差别。 <br></p>
<p>给出一个C++的实现:<br></p>
<div style="BORDER-RIGHT: rgb(204,204,204) 1px solid; PADDING-RIGHT: 5px; BORDER-TOP: rgb(204,204,204) 1px solid; PADDING-LEFT: 4px; FONT-SIZE: 13px; PADDING-BOTTOM: 4px; BORDER-LEFT: rgb(204,204,204) 1px solid; WIDTH: 98%; PADDING-TOP: 4px; BORDER-BOTTOM: rgb(204,204,204) 1px solid; BACKGROUND-COLOR: rgb(238,238,238)"><img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/None.gif" align=top><span style="COLOR: rgb(0,0,255)">int</span><span style="COLOR: rgb(0,0,0)">&nbsp;Gcd(</span><span style="COLOR: rgb(0,0,255)">int</span><span style="COLOR: rgb(0,0,0)">&nbsp;a,&nbsp;</span><span style="COLOR: rgb(0,0,255)">int</span><span style="COLOR: rgb(0,0,0)">&nbsp;b)<br><img id=Codehighlighter1_22_260_Open_Image onclick="this.style.display='none'; Codehighlighter1_22_260_Open_Text.style.display='none'; Codehighlighter1_22_260_Closed_Image.style.display='inline'; Codehighlighter1_22_260_Closed_Text.style.display='inline';" alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockStart.gif" align=top><img id=Codehighlighter1_22_260_Closed_Image style="DISPLAY: none" onclick="this.style.display='none'; Codehighlighter1_22_260_Closed_Text.style.display='none'; Codehighlighter1_22_260_Open_Image.style.display='inline'; Codehighlighter1_22_260_Open_Text.style.display='inline';" alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ContractedBlock.gif" align=top></span><span id=Codehighlighter1_22_260_Closed_Text style="BORDER-RIGHT: rgb(128,128,128) 1px solid; BORDER-TOP: rgb(128,128,128) 1px solid; DISPLAY: none; BORDER-LEFT: rgb(128,128,128) 1px solid; BORDER-BOTTOM: rgb(128,128,128) 1px solid; BACKGROUND-COLOR: rgb(255,255,255)"><img alt="" src="http://www.cnblogs.com/Images/dot.gif"></span><span id=Codehighlighter1_22_260_Open_Text><span style="COLOR: rgb(0,0,0)">{<br><img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: rgb(0,0,255)">if</span><span style="COLOR: rgb(0,0,0)">(a&nbsp;</span><span style="COLOR: rgb(0,0,0)">==</span><span style="COLOR: rgb(0,0,0)">&nbsp;</span><span style="COLOR: rgb(0,0,0)">0</span><span style="COLOR: rgb(0,0,0)">)&nbsp;</span><span style="COLOR: rgb(0,0,255)">return</span><span style="COLOR: rgb(0,0,0)">&nbsp;b;<br><img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: rgb(0,0,255)">if</span><span style="COLOR: rgb(0,0,0)">(b&nbsp;</span><span style="COLOR: rgb(0,0,0)">==</span><span style="COLOR: rgb(0,0,0)">&nbsp;</span><span style="COLOR: rgb(0,0,0)">0</span><span style="COLOR: rgb(0,0,0)">)&nbsp;</span><span style="COLOR: rgb(0,0,255)">return</span><span style="COLOR: rgb(0,0,0)">&nbsp;a;<br><img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: rgb(0,0,255)">if</span><span style="COLOR: rgb(0,0,0)">(a&nbsp;</span><span style="COLOR: rgb(0,0,0)">%</span><span style="COLOR: rgb(0,0,0)">&nbsp;</span><span style="COLOR: rgb(0,0,0)">2</span><span style="COLOR: rgb(0,0,0)">&nbsp;</span><span style="COLOR: rgb(0,0,0)">==</span><span style="COLOR: rgb(0,0,0)">&nbsp;</span><span style="COLOR: rgb(0,0,0)">0</span><span style="COLOR: rgb(0,0,0)">&nbsp;</span><span style="COLOR: rgb(0,0,0)">&amp;&amp;</span><span style="COLOR: rgb(0,0,0)">&nbsp;b&nbsp;</span><span style="COLOR: rgb(0,0,0)">%</span><span style="COLOR: rgb(0,0,0)">&nbsp;</span><span style="COLOR: rgb(0,0,0)">2</span><span style="COLOR: rgb(0,0,0)">&nbsp;</span><span style="COLOR: rgb(0,0,0)">==</span><span style="COLOR: rgb(0,0,0)">&nbsp;</span><span style="COLOR: rgb(0,0,0)">0</span><span style="COLOR: rgb(0,0,0)">)&nbsp;</span><span style="COLOR: rgb(0,0,255)">return</span><span style="COLOR: rgb(0,0,0)">&nbsp;</span><span style="COLOR: rgb(0,0,0)">2</span><span style="COLOR: rgb(0,0,0)">&nbsp;</span><span style="COLOR: rgb(0,0,0)">*</span><span style="COLOR: rgb(0,0,0)">&nbsp;gcd(a&nbsp;</span><span style="COLOR: rgb(0,0,0)">&gt;&gt;</span><span style="COLOR: rgb(0,0,0)">&nbsp;</span><span style="COLOR: rgb(0,0,0)">1</span><span style="COLOR: rgb(0,0,0)">,&nbsp;b&nbsp;</span><span style="COLOR: rgb(0,0,0)">&gt;&gt;</span><span style="COLOR: rgb(0,0,0)">&nbsp;</span><span style="COLOR: rgb(0,0,0)">1</span><span style="COLOR: rgb(0,0,0)">);<br><img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: rgb(0,0,255)">else</span><span style="COLOR: rgb(0,0,0)">&nbsp;</span><span style="COLOR: rgb(0,0,255)">if</span><span style="COLOR: rgb(0,0,0)">(a&nbsp;</span><span style="COLOR: rgb(0,0,0)">%</span><span style="COLOR: rgb(0,0,0)">&nbsp;</span><span style="COLOR: rgb(0,0,0)">2</span><span style="COLOR: rgb(0,0,0)">&nbsp;</span><span style="COLOR: rgb(0,0,0)">==</span><span style="COLOR: rgb(0,0,0)">&nbsp;</span><span style="COLOR: rgb(0,0,0)">0</span><span style="COLOR: rgb(0,0,0)">)&nbsp;&nbsp;</span><span style="COLOR: rgb(0,0,255)">return</span><span style="COLOR: rgb(0,0,0)">&nbsp;gcd(a&nbsp;</span><span style="COLOR: rgb(0,0,0)">&gt;&gt;</span><span style="COLOR: rgb(0,0,0)">&nbsp;</span><span style="COLOR: rgb(0,0,0)">1</span><span style="COLOR: rgb(0,0,0)">,&nbsp;b);<br><img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: rgb(0,0,255)">else</span><span style="COLOR: rgb(0,0,0)">&nbsp;</span><span style="COLOR: rgb(0,0,255)">if</span><span style="COLOR: rgb(0,0,0)">(b&nbsp;</span><span style="COLOR: rgb(0,0,0)">%</span><span style="COLOR: rgb(0,0,0)">&nbsp;</span><span style="COLOR: rgb(0,0,0)">2</span><span style="COLOR: rgb(0,0,0)">&nbsp;</span><span style="COLOR: rgb(0,0,0)">==</span><span style="COLOR: rgb(0,0,0)">&nbsp;</span><span style="COLOR: rgb(0,0,0)">0</span><span style="COLOR: rgb(0,0,0)">)&nbsp;</span><span style="COLOR: rgb(0,0,255)">return</span><span style="COLOR: rgb(0,0,0)">&nbsp;gcd(a,&nbsp;b&nbsp;</span><span style="COLOR: rgb(0,0,0)">&gt;&gt;</span><span style="COLOR: rgb(0,0,0)">&nbsp;</span><span style="COLOR: rgb(0,0,0)">1</span><span style="COLOR: rgb(0,0,0)">);<br><img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/InBlock.gif" align=top>&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="COLOR: rgb(0,0,255)">else</span><span style="COLOR: rgb(0,0,0)">&nbsp;</span><span style="COLOR: rgb(0,0,255)">return</span><span style="COLOR: rgb(0,0,0)">&nbsp;gcd(abs(a&nbsp;</span><span style="COLOR: rgb(0,0,0)">-</span><span style="COLOR: rgb(0,0,0)">&nbsp;b),&nbsp;Min(a,&nbsp;b));<br><img alt="" src="http://www.cnblogs.com/Images/OutliningIndicators/ExpandedBlockEnd.gif" align=top>}</span></span></div>
<br>考虑欧几里德算法，最恶劣的情况是，每次迭代a = 2b -1,这样，迭代后，r= b-1。如果a小于2N，这样大约需要 4N次迭代。而考虑Stein算法，每次迭代后，显然AN+1BN+1&#8804; ANBN/2，最大迭代次数也不超过4N次。也就是说，迭代次数几乎是相等的。但是，需要注意的是，对于大素数，试商法将使每次迭代都更复杂，因此<span style="COLOR: red">对于大素数Stein将更有优势</span><br><br><strong>练习:<br></strong>OJ上面的赤裸裸的Gcd算法的题不多，大多都是套了一个外壳。<br>找了两道，可以试试看<br><a href="http://acm.hdu.edu.cn/showproblem.php?pid=2028"><u><font color=#0000ff>HDOJ 2028 Lowest Common Multiple Plus</font></u></a>&nbsp;&nbsp;&nbsp;这个是求n个数的最小公倍数(有了最大公约数，最小公倍数应该很容易了）<br><a href="http://acm.zju.edu.cn/show_problem.php?pid=2678"><u><font color=#0000ff>ZJU 2678 Bishops on a Toral Board&nbsp; </font></u></a>这个题目要发现规律，不错的题目很老的东东了，其实也没啥好整理的，网上很多资料了，就当备用把:-)<br>
<img src ="http://www.cppblog.com/beautykingdom/aggbug/86299.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2009-05-31 19:09 <a href="http://www.cppblog.com/beautykingdom/archive/2009/05/31/86299.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>二叉树基本算法《转载》</title><link>http://www.cppblog.com/beautykingdom/archive/2009/03/19/77088.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Wed, 18 Mar 2009 16:09:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2009/03/19/77088.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/77088.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2009/03/19/77088.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/77088.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/77088.html</trackback:ping><description><![CDATA[//二叉树先序遍历非递归<br>void InOrderTraverse(BiTree T,SqStack s)<br>{<br>&nbsp;<br>&nbsp;&nbsp;&nbsp; InitStack(s);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //初始化栈<br>&nbsp;BiTree p = T;<br>&nbsp;Push(s,p);&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //树根进栈<br>&nbsp;while(!StackEmpty(s) || !p)<br>&nbsp;{//当栈空或结点为空时结束<br>&nbsp;&nbsp;if(p)<br>&nbsp;&nbsp;{//P非空访问结点，结点进栈，访问该结点左子树<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; printf("%d ",p-&gt;data);<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; Push(s,p);<br>&nbsp;&nbsp;&nbsp;p = p-&gt;lchild ;<br>&nbsp;&nbsp;}<br>&nbsp;&nbsp;else <br>&nbsp;&nbsp;{//P空结点出栈，访问右子树<br>&nbsp;&nbsp;&nbsp;Pop(s,p);<br>&nbsp;&nbsp;&nbsp;p=p-&gt;rchild ;<br>&nbsp;&nbsp;}<br>&nbsp;}<br>}<br><br>
<p>int SumYe(BiTree T)<br>{//求二叉树叶结点数之和<br>&nbsp;if(!T) return 0;<br>&nbsp;if(!T-&gt;lchild &amp;&amp; !T-&gt;rchild ) return 1;<br>&nbsp;return SumYe(T-&gt;lchild)+SumYe(T-&gt;rchild);<br>}</p>
<p>int HightTree(BiTree T)<br>{//求二叉树高<br>&nbsp;int hl = 0;//记录左子树高<br>&nbsp;int hr = 0;//记录右子树高<br>&nbsp;if(!T)&nbsp; return 0;<br>&nbsp;hl = HightTree(T-&gt;lchild);<br>&nbsp;hr = HightTree(T-&gt;rchild);<br>&nbsp;return (hl&gt;hr) ? hl+1 : hr+1 ;<br>}</p>
<img src ="http://www.cppblog.com/beautykingdom/aggbug/77088.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2009-03-19 00:09 <a href="http://www.cppblog.com/beautykingdom/archive/2009/03/19/77088.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>power函数写法《转》</title><link>http://www.cppblog.com/beautykingdom/archive/2009/03/07/75842.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Sat, 07 Mar 2009 13:01:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2009/03/07/75842.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/75842.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2009/03/07/75842.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/75842.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/75842.html</trackback:ping><description><![CDATA[来自百度知道的湛蓝水晶，源代码如下：
<pre>//////////////////////////////////////////////////////////////////////<br>//                用自己写的函数实现c++的pow()的功能                //<br>//                        制作 初学者蒲骏逸                         //<br>//           水平有限，错漏在所难免，欢迎交流，如有任何意见，       //<br>//              请email到：pjy.studio@gmail.com  Thank you!         //<br>////////////////////////////////////////////////////////////////////// <br>#include&lt;iostream&gt;<br>#include&lt;cmath&gt;<br>using namespace std;<br>double pow_i(double num,int n);//计算num的n次幂，其中n为整数<br>double pow_f(double num,double m);//计算num的m次幂，num和m可为双精度，num大于零小于2 <br>double pow_ff(double num,double m);//调用pow_f()和pow_i(),计算num的m次幂,是计算幂的入口<br>;<br>int main()<br>{<br>  double num,m;<br>  cout&lt;&lt;"输入底数num和指数m:"&lt;&lt;endl; <br>  cin&gt;&gt;num&gt;&gt;m;<br>  cout&lt;&lt;"c++ 's answer:"&lt;&lt;pow(num,m)&lt;&lt;endl;<br>  cout&lt;&lt;"my     answer:"&lt;&lt;pow_ff(num,m)&lt;&lt;endl;<br>  }<br><br>double pow_i(double num,int n)//计算num的n次幂，其中n为整数 <br>{<br>   double powint=1;<br>   int i;<br>   for(i=1;i&lt;=n;i++) powint*=num;<br>   return powint;<br>}<br>double pow_f(double num,double m)//计算num的m次幂，num和m可为双精度，num大于零 <br>{<br>    int i,j;<br>    double powf=0,x,tmpm=1;<br>    x=num-1;<br>    for(i=1;tmpm&gt;1e-12 || tmpm&lt;-1e-12;i++)//当tmpm不在次范围时，停止循环,范围可改 <br>           {<br>	       for(j=1,tmpm=1;j&lt;=i;j++) <br>	            tmpm*=(m-j+1)*x/j;<br>	            powf+=tmpm;<br>           }<br>    return powf+1;<br>}<br>double pow_ff(double num,double m)//调用pow_f()和pow_i(),计算num的m次幂,是计算幂的入口<br>{<br>    if(num==0 &amp;&amp; m!=0) return 0;//若num为0，则返回0<br>	else if(num==0 &amp;&amp; m==0) return 1;// 若num和m都为0，则返回1<br>    else if(num&lt;0 &amp;&amp; m-int(m)!=0) return 0;//若num为负，且m不为整数数，则出错，返回0 <br>    if(num&gt;2)//把底数大于2的情况转为(1/num)^-m计算<br>	{<br>	    num=1/num;<br>		m=-m;<br>		}<br>	if(m&lt;0) return 1/pow_ff(num,-m);//把指数小于0的情况转为1/num^-m计算<br>    if(m-int(m)==0) return pow_i(num,m);/*当指数为浮点数是，分成整数和小数分别求<br>	                                    幂，这是因为但底数较小式，用pow_f直接求幂<br>										误差大，所以分为指数的整数部分用pow_i,小<br>										数部分用pow_f求.*/ <br>    else return pow_f(num,m-int(m))*pow_i(num,int(m));<br>    return pow_f(num,m);<br>}<br></pre><img src ="http://www.cppblog.com/beautykingdom/aggbug/75842.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2009-03-07 21:01 <a href="http://www.cppblog.com/beautykingdom/archive/2009/03/07/75842.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一个关于单向链表的面试题</title><link>http://www.cppblog.com/beautykingdom/archive/2008/09/14/61826.html</link><dc:creator>chatler</dc:creator><author>chatler</author><pubDate>Sun, 14 Sep 2008 15:29:00 GMT</pubDate><guid>http://www.cppblog.com/beautykingdom/archive/2008/09/14/61826.html</guid><wfw:comment>http://www.cppblog.com/beautykingdom/comments/61826.html</wfw:comment><comments>http://www.cppblog.com/beautykingdom/archive/2008/09/14/61826.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/beautykingdom/comments/commentRss/61826.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/beautykingdom/services/trackbacks/61826.html</trackback:ping><description><![CDATA[<img  src="file:///C:/DOCUME%7E1/ADMINI%7E1/LOCALS%7E1/Temp/moz-screenshot-13.jpg" alt=""><img  src="file:///C:/DOCUME%7E1/ADMINI%7E1/LOCALS%7E1/Temp/moz-screenshot-14.jpg" alt=""><br><font id="zoom" class="f14">题目：给你一个单向链表的头指针，可能最后不是NULL终止，而是循环链表。题目问你怎么找出这个链表循环部分的第一个节点。比如下面的链表：
<pre>0&nbsp;-&gt;&nbsp;1&nbsp;-&gt;&nbsp;2&nbsp;-&gt;&nbsp;3&nbsp;-&gt;&nbsp;4&nbsp;-&gt;&nbsp;5&nbsp;-&gt;&nbsp;6&nbsp;-&gt;&nbsp;7&nbsp;-&gt;&nbsp;8&nbsp;-&gt;&nbsp;(3)&nbsp;循环<br>当然尽量用少的空间和时间是题目的要求。 </pre>
</font>(1).判断指针A和B在环内首次相遇：<br>有两个指针A和B，从链表的头节点出发，A的步长是1，B的步长是2，那么当他们在环内相遇时，设a是链表头到环节点的位置，b是环的周长，c是A和B在环上首次相遇时与环节点的距离，m和n分别是第一次相遇时A和B走过的环数，那么：A经历的路程是a+(m*b+c),B经历的路程是a+(n*b+c),这时2*A经历的路程=B经历的路程，所以得到2*(a+m*b+c)=a+(n*b+c),即a+2mb+c=nb,即<br>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; a+c=(n-2m)b=k*b,k=n-2m -----(1)式.<br>(2).判断A和B在环节点相遇：<br>指针A和B相遇后，如果需要二者相遇在循环链表的环节点，则指针A以步长1前进，需要路程b-c+x*b=(x+1)b-c,由1可知，a=kb-c,那么也就是说：指针A要到达环节点还需要走的路程kb-c正好等于a。这样问题就解决了：A从首次相遇的位置步长为1走到环节点需要kb-c，那么B只需从头节点步长为一走a个节点，就到达了环节点。这时A和B相遇。<br>大功告成也！！！！！！！！！！！时间复杂度O(n),空间复杂度O(1)！！！！！！！！！！！！！！！！！！！！！！！！！<br><img src ="http://www.cppblog.com/beautykingdom/aggbug/61826.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/beautykingdom/" target="_blank">chatler</a> 2008-09-14 23:29 <a href="http://www.cppblog.com/beautykingdom/archive/2008/09/14/61826.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>