<?xml version="1.0" encoding="utf-8"?>
<feed xmlns="http://www.w3.org/2005/Atom">
  <title>Frank</title>
  <subtitle>去探索更大的世界</subtitle>
  <link href="/atom.xml" rel="self"/>
  
  <link href="http://skills.frankge.me/"/>
  <updated>2017-01-11T12:33:09.166Z</updated>
  <id>http://skills.frankge.me/</id>
  
  <author>
    <name>Frank</name>
    
  </author>
  
  <generator uri="http://hexo.io/">Hexo</generator>
  
  <entry>
    <title>浅谈动态规划（四）——巧用递归</title>
    <link href="http://skills.frankge.me/getting-start-to-dynamic-programming-part-4-using-recursion-in-a-smart-way/"/>
    <id>http://skills.frankge.me/getting-start-to-dynamic-programming-part-4-using-recursion-in-a-smart-way/</id>
    <published>2017-01-10T16:25:10.000Z</published>
    <updated>2017-01-11T12:33:09.166Z</updated>
    
    <content type="html"><![CDATA[<p style="text-align: justify;">从lintcode做题的角度来说，递归往往会开销较大。不过在做动态规划的时候，我们能发现递归是个不错的工具，对于解决问题的代码量能够缩小很多。同时，如果使用了带有备忘的递归，能够减少很大的开销。这次列举几个典型的使用带备忘的递归的例子，来总结一下带备忘的递归的使用。这篇文章中的三个题目均是<span style="color: #3366ff;"><a href="http://skills.frankge.me/getting-start-to-dynamic-programming-part-3-find-the-optimal-solution/">上篇博客</a></span>中出现过的，便于比较。<br><br>首先我们来看第一题。</p>

<h2 id="1-钢条切割"><a href="#1-钢条切割" class="headerlink" title="1.钢条切割"></a>1.钢条切割</h2><p>题目描述：</p>
<p></p><p style="text-align: justify;">一家公司有一根固定长度的钢条，要切割为短的钢条出售。切割工序本身没有成本。公司希望知道最佳的切割方案（即如何切割能够获得价格的最大值）。假设钢条的长度为<code>n</code>（此处假设<code>n &lt;= 10</code>），不同长度<code>i</code>的钢条的价格如下表。</p>
<p><table><thead><tr><th style="text-align:center">长度j</th><th style="text-align:center">1</th><th style="text-align:center">2</th><th style="text-align:center">3</th><th style="text-align:center">4</th><th style="text-align:center">5</th><th style="text-align:center">6</th><th style="text-align:center">7</th><th style="text-align:center">8</th><th style="text-align:center">9</th><th style="text-align:center">10</th></tr></thead><thead><tr><th style="text-align:center">价格p</th><th style="text-align:center">1</th><th style="text-align:center">5</th><th style="text-align:center">8</th><th style="text-align:center">9</th><th style="text-align:center">10</th><th style="text-align:center">17</th><th style="text-align:center">17</th><th style="text-align:center">20</th><th style="text-align:center">24</th><th style="text-align:center">30</th></tr></thead></table></p><br>假设长度为<code>i</code>时，最佳切割方案时的价格总和为$r[i]$$(0 &lt;= i&lt;= n)$，根据<span style="color: #3366ff;"><a href="http://skills.frankge.me/getting-start-to-dynamic-programming-part-3-find-the-optimal-solution/">上篇博客</a></span>所说，此题目的状态转移方程为：<p></p>
<p><center>$r[i+1] = max(p[j] + r[i+1-j]),1&lt;= j&lt;= i+1$</center><br>这样，便很容易写出递归的代码：<br><figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// 不带备忘的递归版本</span></div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">cutRod</span><span class="params">(<span class="built_in">vector</span>&lt;<span class="keyword">int</span>&gt; &amp;p, <span class="keyword">int</span> n)</span></span></div><div class="line">&#123;</div><div class="line">	<span class="keyword">if</span> (n == <span class="number">0</span>) <span class="comment">// 递归出口，当n == 0的时候收益为0</span></div><div class="line">		<span class="keyword">return</span> <span class="number">0</span>;</div><div class="line"></div><div class="line">	<span class="keyword">int</span> q = INT_MIN;</div><div class="line">	<span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>; i &lt;= n; i++)</div><div class="line">		q = max(q, p[i<span class="number">-1</span>] + cutRod2(p, n-i)); <span class="comment">// 状态转移，递归找出每次的最大值</span></div><div class="line"></div><div class="line">	<span class="keyword">return</span> q;</div><div class="line">&#125;</div></pre></td></tr></table></figure></p>
<p>大家都知道，使用递归时，往往会因为不断的求解之间已经解决过的问题而使用更多的空间，那么有没有好办法能解决这个问题呢？那么用备忘来记录中间求解过的值就能够解决。代码如下：<br><figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// 使用备忘的递归版本。使用备忘之后能减少很多开销</span></div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">cutRod</span><span class="params">(<span class="built_in">vector</span>&lt;<span class="keyword">int</span>&gt; &amp;p, <span class="keyword">int</span> n)</span></span></div><div class="line">&#123;</div><div class="line">	<span class="built_in">vector</span>&lt;<span class="keyword">int</span>&gt; r(n+<span class="number">1</span>, INT_MIN); <span class="comment">// 增加一个数组，记录中间已经求解过的结果</span></div><div class="line">	r[<span class="number">0</span>] = <span class="number">0</span>;</div><div class="line"></div><div class="line">	<span class="keyword">return</span> cutRodAux(p, r, n);</div><div class="line">&#125;</div><div class="line"> </div><div class="line"><span class="comment">// 辅助函数</span></div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">cutRodAux</span><span class="params">(<span class="built_in">vector</span>&lt;<span class="keyword">int</span>&gt; &amp;p, <span class="built_in">vector</span>&lt;<span class="keyword">int</span>&gt; &amp;r, <span class="keyword">int</span> index)</span></span></div><div class="line">&#123;</div><div class="line">	<span class="keyword">if</span> (r[index] != INT_MIN) <span class="comment">// 递归出口。如果此时数组中的元素不为INT_MIN，意味着已经求解，直接返回即可。</span></div><div class="line">		<span class="keyword">return</span> r[index];</div><div class="line"></div><div class="line">	<span class="comment">// 如果数组中的元素是INT_MIN，那么需要递归求解</span></div><div class="line">	<span class="keyword">int</span> q = INT_MIN;</div><div class="line">	<span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>; i &lt;= index; i++)</div><div class="line">		q = max(q, p[i<span class="number">-1</span>] + cutRodAux(p, r, index-i));</div><div class="line">	r[index] = q; <span class="comment">// 将递归求解的结果记录到数组</span></div><div class="line"></div><div class="line">	<span class="keyword">return</span> q;</div><div class="line">&#125;</div></pre></td></tr></table></figure></p>
<p>接下来再看下一题。</p>
<h2 id="2-最长公共子序列"><a href="#2-最长公共子序列" class="headerlink" title="2.最长公共子序列"></a>2.最长公共子序列</h2><p>题目描述：</p>
<p>给定两个序列X = {$x_1$, $x_2$, $x_3$, …, $x_m$ }, 和Y = {$y_1$, $y_2$, …, $y_n$}，求<code>X</code>和<code>Y</code>长度最长的公共子序列。公共子序列的定义为，给定两个序列<code>X</code>，<code>Y</code>，如果<code>Z</code>即是<code>X</code>的子序列，也是<code>Y</code>的子序列，我们称它是<code>X</code>和<code>Y</code>的公共子序列。</p>
<p>例如：X = {A, B, C, D, A, B}，Y = {B, D, C, B, A}，那么序列｛B, C, A｝就是X和Y的公共子序列，但不是最长公共子序列。X和Y的最长公共子序列是{B, C, A, B}，其长度为<code>4</code>。</p>
<p>根据<span style="color: #3366ff;"><a href="http://skills.frankge.me/getting-start-to-dynamic-programming-part-3-find-the-optimal-solution/">上篇文章</a></span>，状态转移方程为：</p>
<p>情况1:  $i==0$ 或者 $j== 0$时，$c[i][j] = 0$;<br>情况2:  $i,  j &gt; 0$且$x_i$ == $y_j$时， $c[i][j] = c[i-1][j-1] + 1$;<br>情况3:  $i，j &gt; 0$且$x_i != y_j$时， $c[i][j] = max(c[i][j-1], c[i-1][j])$;</p>
<p>那么直接用递归实现如下：</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">LCS</span><span class="params">(<span class="built_in">string</span> A, <span class="built_in">string</span> B)</span></span></div><div class="line">&#123;</div><div class="line">	<span class="keyword">int</span> len1 = A.length();</div><div class="line">	<span class="keyword">int</span> len2 = B.length();</div><div class="line"></div><div class="line">	<span class="keyword">return</span> LCS_AUX(A, B, len1, len2);</div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">LCS_AUX</span><span class="params">(<span class="built_in">string</span> A, <span class="built_in">string</span> B, <span class="keyword">int</span> idx1, <span class="keyword">int</span> idx2)</span></span></div><div class="line">&#123;</div><div class="line">	<span class="keyword">if</span> (idx1 == <span class="number">0</span> || idx2 == <span class="number">0</span>) <span class="comment">// 递归出口，情况1</span></div><div class="line">		<span class="keyword">return</span> <span class="number">0</span>;</div><div class="line"></div><div class="line">	<span class="keyword">if</span> (A[idx1<span class="number">-1</span>] == B[idx2<span class="number">-1</span>])</div><div class="line">		<span class="keyword">return</span> LCS_AUX(A, B, idx1<span class="number">-1</span>, idx2<span class="number">-1</span>) + <span class="number">1</span>; <span class="comment">// 情况2</span></div><div class="line">	<span class="keyword">else</span></div><div class="line">		<span class="keyword">return</span> max(LCS_AUX(A, B, idx1<span class="number">-1</span>, idx2), LCS_AUX(A, B, idx1, idx2<span class="number">-1</span>)); <span class="comment">// 情况3</span></div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p>同样，加入备忘，记录过程中的求解的值，就可以节省很多开销。代码如下：</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">LCS</span><span class="params">(<span class="built_in">string</span> A, <span class="built_in">string</span> B)</span></span></div><div class="line">&#123;</div><div class="line">	<span class="keyword">int</span> len1 = A.length();</div><div class="line">	<span class="keyword">int</span> len2 = B.length();</div><div class="line"></div><div class="line">	<span class="built_in">vector</span>&lt;<span class="built_in">vector</span>&lt;<span class="keyword">int</span>&gt; &gt; c(len1+<span class="number">1</span>, <span class="built_in">vector</span>&lt;<span class="keyword">int</span>&gt;(len2+<span class="number">1</span>, INT_MAX));</div><div class="line">	<span class="comment">//for (int i = 0; i &lt;= len1; i++)</span></div><div class="line">	<span class="comment">//	c[i][0] = 0;</span></div><div class="line">	<span class="comment">//for (int j = 0; j &lt;= len2; j++)</span></div><div class="line">	<span class="comment">//	c[0][j] = 0;</span></div><div class="line"></div><div class="line">	<span class="keyword">return</span> LCS_AUX(A, B, c, len1, len2);</div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">LCS_AUX</span><span class="params">(<span class="built_in">string</span> A, <span class="built_in">string</span> B, <span class="built_in">vector</span>&lt;<span class="built_in">vector</span>&lt;<span class="keyword">int</span>&gt; &gt; &amp;c, <span class="keyword">int</span> idx1, <span class="keyword">int</span> idx2)</span></span></div><div class="line">&#123;</div><div class="line">	<span class="keyword">if</span> (idx1 == <span class="number">0</span> || idx2 == <span class="number">0</span>) <span class="comment">// 递归出口，情况1</span></div><div class="line">		<span class="keyword">return</span> <span class="number">0</span>;</div><div class="line"></div><div class="line">	<span class="keyword">if</span> (c[idx1][idx2] != INT_MAX) <span class="comment">// 如果已经求解过，那么直接调出之前的结果</span></div><div class="line">		<span class="keyword">return</span> c[idx1][idx2];</div><div class="line"></div><div class="line">	<span class="keyword">if</span> (A[idx1<span class="number">-1</span>] == B[idx2<span class="number">-1</span>]) <span class="comment">// 情况2</span></div><div class="line">		c[idx1][idx2] =  LCS_AUX(A, B, c, idx1<span class="number">-1</span>, idx2<span class="number">-1</span>) + <span class="number">1</span>; <span class="comment">// 更新辅助数组中此处的值，便于以后调出</span></div><div class="line">	<span class="keyword">else</span></div><div class="line">		c[idx1][idx2] =  max(LCS_AUX(A, B, c, idx1<span class="number">-1</span>, idx2), LCS_AUX(A, B, c, idx1, idx2<span class="number">-1</span>)); <span class="comment">// 情况3</span></div><div class="line"></div><div class="line">	<span class="keyword">return</span> c[idx1][idx2];</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<h2 id="3-Minimum-Adjustment-Cost"><a href="#3-Minimum-Adjustment-Cost" class="headerlink" title="3.Minimum Adjustment Cost"></a>3.<a href="http://www.lintcode.com/en/problem/minimum-adjustment-cost/" target="_blank" rel="external">Minimum Adjustment Cost</a></h2><p>题目描述：</p>
<p>Given an integer array, adjust each integers so that the difference of every adjacent integers are not greater than a given number target.If the array before adjustment is <code>A</code>, the array after adjustment is <code>B</code>, you should minimize the sum of <code>|A[i]-B[i]|</code></p>
<p>Notice: You can assume each number in the array is a positive integer and not greater than <code>100</code>.</p>
<p>Example: Given <code>[1,4,2,3]</code> and <code>target = 1</code>, one of the solutions is <code>[2,3,2,3]</code>, the adjustment cost is <code>2</code> and it’s minimal.</p>
<p>第三题有点难度，是深度优先搜索的思想，解释的话有些太费时间，不过如果手动着算一下，结合我代码的注释，也能比较容易就看懂，所以直接上代码，具体的解析见<span style="color: #3366ff;"><a href="http://skills.frankge.me/getting-start-to-dynamic-programming-part-3-find-the-optimal-solution/">上篇博客</a></span>。</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// 深度优先查找，用递归。此方法比之前类似广度查找的方法的好处是，可以查找所有可能的情况</span></div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">MinAdjustmentCost</span><span class="params">(<span class="built_in">vector</span>&lt;<span class="keyword">int</span>&gt; A, <span class="keyword">int</span> target)</span></span></div><div class="line">&#123;</div><div class="line">	<span class="keyword">if</span> (A.size() == <span class="number">0</span>)</div><div class="line">		<span class="keyword">return</span> <span class="number">0</span>;</div><div class="line"></div><div class="line">	<span class="comment">// 找到最小值和最大值</span></div><div class="line">	<span class="keyword">int</span> minVal = INT_MAX;</div><div class="line">	<span class="keyword">int</span> maxVal = INT_MIN;</div><div class="line">	<span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; A.size(); i++)</div><div class="line">	&#123;</div><div class="line">		minVal = min(minVal, A[i]);</div><div class="line">		maxVal = max(maxVal, A[i]);</div><div class="line">	&#125;</div><div class="line"></div><div class="line">	<span class="comment">// 初始化辅助数组，每个位置记录从后到前调整的代价</span></div><div class="line">	<span class="built_in">vector</span>&lt;<span class="built_in">vector</span>&lt;<span class="keyword">int</span>&gt; &gt; M(A.size(), <span class="built_in">vector</span>&lt;<span class="keyword">int</span>&gt;(maxVal - minVal + <span class="number">1</span>, INT_MAX));</div><div class="line"></div><div class="line">	<span class="built_in">vector</span>&lt;<span class="keyword">int</span>&gt; B(A); <span class="comment">// 数组B记录了每次尝试的结果</span></div><div class="line"></div><div class="line">	<span class="comment">// 调用辅助函数</span></div><div class="line">	<span class="keyword">return</span> MinAdjustmentCostAux(A, B, target, <span class="number">0</span>, M, minVal, maxVal);</div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="comment">// 辅助函数，实现带有表格的递归，从而减少运行次数</span></div><div class="line"><span class="comment">// 返回下标为index时，与前一个数字在target限定范围内的最小调整代价</span></div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">MinAdjustmentCostAux</span><span class="params">(<span class="built_in">vector</span>&lt;<span class="keyword">int</span>&gt; A, <span class="built_in">vector</span>&lt;<span class="keyword">int</span>&gt; B, <span class="keyword">int</span> target, <span class="keyword">int</span> index, <span class="built_in">vector</span>&lt;<span class="built_in">vector</span>&lt;<span class="keyword">int</span>&gt; &gt; &amp;M, <span class="keyword">int</span> minValue, <span class="keyword">int</span> maxValue)</span></span></div><div class="line">&#123;</div><div class="line">	<span class="keyword">int</span> n = A.size();</div><div class="line">	<span class="keyword">if</span> (index &gt;= n)</div><div class="line">		<span class="keyword">return</span> <span class="number">0</span>;</div><div class="line"></div><div class="line">	<span class="keyword">int</span> dif = <span class="number">0</span>;</div><div class="line">	<span class="keyword">int</span> minCost = INT_MAX;</div><div class="line"></div><div class="line">	<span class="keyword">for</span> (<span class="keyword">int</span> i = minValue; i &lt;= maxValue; i++)</div><div class="line">	&#123;</div><div class="line">		<span class="keyword">if</span> (index != <span class="number">0</span> &amp;&amp; <span class="built_in">abs</span>(i - B[index<span class="number">-1</span>]) &gt; target)</div><div class="line">			<span class="keyword">continue</span>;</div><div class="line"></div><div class="line">		<span class="comment">// 如果查找时发现此位置已经有结果，那么直接返回</span></div><div class="line">		<span class="keyword">if</span> (M[index][i-minValue] != INT_MAX)</div><div class="line">		&#123;</div><div class="line">			dif = M[index][i-minValue];</div><div class="line">			minCost = min(minCost, dif);</div><div class="line">			<span class="keyword">continue</span>;</div><div class="line">		&#125;</div><div class="line"></div><div class="line">		<span class="comment">// 此时index位置的值尝试为i</span></div><div class="line">		B[index] = i;</div><div class="line">		dif = <span class="built_in">abs</span>(i - A[index]); <span class="comment">// 计算此位置调整的代价</span></div><div class="line">		dif += MinAdjustmentCostAux(A, B, target, index + <span class="number">1</span>, M, minValue, maxValue); <span class="comment">// 加上后面所有数调整的代价，得到的是总代价</span></div><div class="line">		minCost = min(minCost, dif); <span class="comment">// 找到每个数字调整的最小代价</span></div><div class="line"></div><div class="line">		M[index][i-minValue] = dif; <span class="comment">// 记录到辅助数组M中，实现减少运行次数</span></div><div class="line"></div><div class="line">		B[index] = A[index]; <span class="comment">// 用于回溯</span></div><div class="line">	&#125;</div><div class="line"></div><div class="line">	<span class="keyword">return</span> minCost;</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p>比较一下，是不是使用带有备忘的递归会使得程序简单很多呢？</p>
]]></content>
    
    <summary type="html">
    
      &lt;p style=&quot;text-align: justify;&quot;&gt;从lintcode做题的角度来说，递归往往会开销较大。不过在做动态规划的时候，我们能发现递归是个不错的工具，对于解决问题的代码量能够缩小很多。同时，如果使用了带有备忘的递归，能够减少很大的开销。这次列举几个典型的使用
    
    </summary>
    
      <category term="编程学习" scheme="http://skills.frankge.me/categories/%E7%BC%96%E7%A8%8B%E5%AD%A6%E4%B9%A0/"/>
    
    
      <category term="算法" scheme="http://skills.frankge.me/tags/%E7%AE%97%E6%B3%95/"/>
    
  </entry>
  
  <entry>
    <title>浅谈动态规划（三）——找到最优时的解</title>
    <link href="http://skills.frankge.me/getting-start-to-dynamic-programming-part-3-find-the-optimal-solution/"/>
    <id>http://skills.frankge.me/getting-start-to-dynamic-programming-part-3-find-the-optimal-solution/</id>
    <published>2016-12-04T12:23:26.000Z</published>
    <updated>2017-01-11T12:21:47.971Z</updated>
    
    <content type="html"><![CDATA[<p>前两次动态规划的博客中，介绍了动态规划最基础的两个特点以及列举了几个我在做lintcode中遇到的接触动态规划初期相对比较适合做的题目。这次结合几道题目来总结一下动态规划的另一个特点——找到最优时的解。</p>
<p>同样，还是以题目来说明。</p>
<h2 id="1-Minimum-Adjustment-Cost"><a href="#1-Minimum-Adjustment-Cost" class="headerlink" title="1.Minimum Adjustment Cost"></a>1.<span style="color: #3366ff;"><a href="http://www.lintcode.com/en/problem/minimum-adjustment-cost/" target="_blank" rel="external">Minimum Adjustment Cost</a></span></h2><p>题目描述：<br>Given an integer array, adjust each integers so that the difference of every adjacent integers are not greater than a given number target.If the array before adjustment is <code>A</code>, the array after adjustment is <code>B</code>, you should minimize the sum of <code>|A[i]-B[i]|</code></p>
<p>Notice: You can assume each number in the array is a positive integer and not greater than <code>100</code>.</p>
<p>Example: Given <code>[1,4,2,3]</code> and <code>target = 1</code>, one of the solutions is <code>[2,3,2,3]</code>, the adjustment cost is <code>2</code> and it’s minimal.</p>
<p>题目给出了一个数组<code>A</code>，并且给出了一个目标数字<code>target</code>。要求调整数组中每个位置的数字得到数组B，使得数组B中相邻元素的差值的绝对值小于等于<code>target</code>，且$sum(|A[i] - B[i]|)$最小。求得到最终结果时每个位置调整的和最小为多少。</p>
<p>题目只要求找出最小的调整开销的和，我这里再加一问：在调整和为最小值时，找出一个可能的数组<code>B</code>。</p>
<p>先来解决lintcode要求的问题。</p>
<p>Minimum Adjustment Cost题解:</p>
<p>我们应该能够想通一个问题，调整后的每个位置的数字都是在A数组中出现的最小值与最大值之间的数字。假设最小值是<code>minVal</code>，最大值是<code>maxVal</code>，所以数组B的每个位置上可选择的数字的个数为$count = maxVal - minVal + 1$。</p>
<p>构造一个二维数组$cost[n+1][count]$，<code>n</code>表示数组<code>A</code>中的个数。$cost[loop][j]$$(0 &lt;= loop &lt;= n, minVal &lt;= j &lt;= maxVal)$表示<code>B</code>数组中第<code>loop</code>个位置上（此时<code>B</code>的下标为<code>loop-1</code>）调整为数字j时的调整总和（包括<code>loop</code>之前的所有位置的调整的和）。那么当调整下一个位置<code>loop+1</code>时，调整为数字i的调整总和为$cost[loop+1][i] = min(cost[loop][j] + | i - A[loop] |)$,$|i - j| &lt;= target$。这里<code>j</code>是上一个位置时调整的结果，因为有限制条件相邻的两个元素差的绝对值小于<code>target</code>，所以要用到上一个位置的数组；<code>|i - A[i]|</code>是此位置（数组<code>B</code>中第<code>loop+1</code>个数字，下标为<code>loop</code>）调整为i时调整的代价。最后的结果是$cost[n][i]$$(minVal &lt;= i &lt;= maxVal)$中最小的值。</p>
<p>可能我的表述不太清楚，加注释的代码可能表达的更清楚些：<br><figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">MinAdjustmentCost</span><span class="params">(<span class="built_in">vector</span>&lt;<span class="keyword">int</span>&gt; A, <span class="keyword">int</span> target)</span></span></div><div class="line">&#123;</div><div class="line">	<span class="keyword">int</span> n = A.size();</div><div class="line"></div><div class="line">	<span class="keyword">if</span> (n &lt;= <span class="number">0</span> || n == <span class="number">1</span>)</div><div class="line">		<span class="keyword">return</span> <span class="number">0</span>;</div><div class="line"></div><div class="line">	<span class="keyword">int</span> minVal = INT_MAX; <span class="comment">// 记录数组中最小值</span></div><div class="line">	<span class="keyword">int</span> maxVal = INT_MIN; <span class="comment">// 记录数组中最大值</span></div><div class="line">			</div><div class="line">	<span class="keyword">int</span> loop, i, j;</div><div class="line">	</div><div class="line">	<span class="comment">// 找出数组A中出现的最小值和最大值</span></div><div class="line">	<span class="keyword">for</span> (i = <span class="number">0</span>; i &lt; n; i++)</div><div class="line">	&#123;</div><div class="line">		<span class="keyword">if</span> (A[i] &gt; maxVal)</div><div class="line">			maxVal = A[i];</div><div class="line">		<span class="keyword">if</span> (A[i] &lt; minVal)</div><div class="line">			minVal = A[i];</div><div class="line">	&#125;</div><div class="line">	</div><div class="line">	<span class="keyword">int</span> count = maxVal - minVal + <span class="number">1</span>; <span class="comment">// 每次需要动态规划的个数</span></div><div class="line">	<span class="comment">// 辅助数组。记录每个位置上B调整为不同数字的最小开销。</span></div><div class="line">	<span class="comment">// 即，当B数组第loop个数字调整为i的时候的最小开销为cost[loop][i]</span></div><div class="line">	<span class="built_in">vector</span>&lt;<span class="built_in">vector</span>&lt;<span class="keyword">int</span>&gt; &gt; cost(n+<span class="number">1</span>, <span class="built_in">vector</span>&lt;<span class="keyword">int</span>&gt;(count, INT_MAX)); </div><div class="line">	<span class="comment">// 初始化</span></div><div class="line">	<span class="keyword">for</span> (i = <span class="number">0</span>; i &lt; count; i++)</div><div class="line">		cost[<span class="number">0</span>][i] = <span class="number">0</span>; </div><div class="line"></div><div class="line">	<span class="comment">// 动态规划步骤</span></div><div class="line">	<span class="keyword">for</span> (loop = <span class="number">1</span>; loop &lt;= n; loop++)</div><div class="line">	&#123;</div><div class="line">		<span class="comment">// 找出数组B中，第loop个位置（下标为loop-1），选择数字i的最小调整代价</span></div><div class="line">		<span class="comment">// 即，找出cost[loop][i]。它记录了到loop位置时，调整为i数字的最小开销</span></div><div class="line">		<span class="keyword">for</span> (i = minVal; i &lt;= maxVal; i++)</div><div class="line">		&#123;</div><div class="line">			<span class="keyword">for</span> (j = minVal; j &lt;= maxVal; j++)</div><div class="line">			&#123;</div><div class="line">				<span class="keyword">if</span> (<span class="built_in">abs</span>(i-j) &lt;= target)</div><div class="line">				&#123;</div><div class="line">					<span class="keyword">int</span> temp = cost[loop<span class="number">-1</span>][j-minVal] + <span class="built_in">abs</span>(i-A[loop<span class="number">-1</span>]); <span class="comment">// 当第loop-1个数字选择j时，第loop个数字选择（调整到）i时的改变量</span></div><div class="line">					<span class="keyword">if</span> (temp &lt; cost[loop][i-minVal]) <span class="comment">// 找出最小的调整代价</span></div><div class="line">						cost[loop][i-minVal] = temp;</div><div class="line">				&#125;</div><div class="line">			&#125;</div><div class="line">		&#125;</div><div class="line">	&#125;</div><div class="line"></div><div class="line">	<span class="comment">// 找出最后一个位置改变结束时最小的改变代价</span></div><div class="line">	<span class="keyword">int</span> minCost = INT_MAX;</div><div class="line">	<span class="keyword">for</span> (i = <span class="number">0</span>; i &lt; count; i++)</div><div class="line">		minCost = min(cost[n][i], minCost);</div><div class="line"></div><div class="line">	<span class="keyword">return</span> minCost;</div><div class="line">&#125;</div></pre></td></tr></table></figure></p>
<p>我们发现，在每次比较找出最小开销的时候，可以在加一个辅助数组$record[n+1][count]$,记录每个位置时最小调整开销时选择的数字，最后得到了完整的cost列表之后，$cost[n][i]（minVal &lt;= i &lt;= maxVal）$中最小时i的值就是<code>B[n-1]</code>中的值，然后$record[n][i]$中记录的即使上一个位置对应的<code>B</code>中的值，一次类推，便能找到<code>B</code>数组一个可能的结果。同样，看代码可能更清楚点:<br><figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div><div class="line">66</div><div class="line">67</div><div class="line">68</div><div class="line">69</div><div class="line">70</div><div class="line">71</div><div class="line">72</div><div class="line">73</div><div class="line">74</div><div class="line">75</div><div class="line">76</div><div class="line">77</div><div class="line">78</div><div class="line">79</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// 实现了记录每次选择数字的功能</span></div><div class="line"><span class="function"><span class="keyword">void</span> <span class="title">MinAdjustmentCost</span><span class="params">(<span class="built_in">vector</span>&lt;<span class="keyword">int</span>&gt; A, <span class="keyword">int</span> target)</span></span></div><div class="line">&#123;</div><div class="line">	<span class="keyword">int</span> n = A.size();</div><div class="line"></div><div class="line">	<span class="keyword">if</span> (n &lt;= <span class="number">0</span> || n == <span class="number">1</span>)</div><div class="line">		<span class="keyword">return</span>;</div><div class="line"></div><div class="line">	<span class="keyword">int</span> minVal = INT_MAX; <span class="comment">// 记录数组中最小值</span></div><div class="line">	<span class="keyword">int</span> maxVal = INT_MIN; <span class="comment">// 记录数组中最大值</span></div><div class="line">			</div><div class="line">	<span class="keyword">int</span> loop, i, j;</div><div class="line">			</div><div class="line">	<span class="keyword">for</span> (i = <span class="number">0</span>; i &lt; n; i++)</div><div class="line">	&#123;</div><div class="line">		<span class="keyword">if</span> (A[i] &gt; maxVal)</div><div class="line">			maxVal = A[i];</div><div class="line">		<span class="keyword">if</span> (A[i] &lt; minVal)</div><div class="line">			minVal = A[i];</div><div class="line">	&#125;</div><div class="line">	</div><div class="line">	<span class="keyword">int</span> count = maxVal - minVal + <span class="number">1</span>; <span class="comment">// 每次需要动态规划的个数</span></div><div class="line">	<span class="built_in">vector</span>&lt;<span class="built_in">vector</span>&lt;<span class="keyword">int</span>&gt; &gt; cost(n+<span class="number">1</span>, <span class="built_in">vector</span>&lt;<span class="keyword">int</span>&gt;(count, INT_MAX)); <span class="comment">// 辅助数组</span></div><div class="line">	<span class="built_in">vector</span>&lt;<span class="built_in">vector</span>&lt;<span class="keyword">int</span>&gt; &gt; record(n+<span class="number">1</span>, <span class="built_in">vector</span>&lt;<span class="keyword">int</span>&gt;(count, <span class="number">0</span>));</div><div class="line">	<span class="built_in">vector</span>&lt;<span class="keyword">int</span>&gt; B(n);</div><div class="line">	<span class="comment">// 初始化</span></div><div class="line">	<span class="keyword">for</span> (i = <span class="number">0</span>; i &lt; count; i++)</div><div class="line">		cost[<span class="number">0</span>][i] = <span class="number">0</span>; </div><div class="line"></div><div class="line">	<span class="comment">// 动态规划步骤</span></div><div class="line">	<span class="keyword">for</span> (loop = <span class="number">1</span>; loop &lt;= n; loop++)</div><div class="line">	&#123;</div><div class="line">		<span class="comment">// 找出第loop个位置，选择数字i的最小调整代价</span></div><div class="line">		<span class="keyword">for</span> (i = minVal; i &lt;= maxVal; i++)</div><div class="line">		&#123;</div><div class="line">			<span class="keyword">for</span> (j = minVal; j &lt;= maxVal; j++)</div><div class="line">			&#123;</div><div class="line">				<span class="keyword">if</span> (<span class="built_in">abs</span>(i-j) &lt;= target)</div><div class="line">				&#123;</div><div class="line">					<span class="keyword">int</span> temp = cost[loop<span class="number">-1</span>][j-minVal] + <span class="built_in">abs</span>(i-A[loop<span class="number">-1</span>]); <span class="comment">// 当第loop-1个数字选择j时，第loop个数字选择（调整到）i时的改变量</span></div><div class="line">					<span class="keyword">if</span> (temp &lt; cost[loop][i-minVal]) <span class="comment">// 找出最小的调整代价</span></div><div class="line">					&#123;</div><div class="line">						cost[loop][i-minVal] = temp;</div><div class="line">						record[loop][i-minVal] = j; <span class="comment">// record中记录的是第loop个数字取i最优时，上一个数字最优时对应的值</span></div><div class="line">					&#125;</div><div class="line">				&#125;</div><div class="line">			&#125;</div><div class="line">		&#125;</div><div class="line">	&#125;</div><div class="line"></div><div class="line">	<span class="comment">// 找出最后一个位置改变结束时最小的改变代价</span></div><div class="line">	<span class="keyword">int</span> minCost = INT_MAX;</div><div class="line">	<span class="keyword">int</span> backtrack; <span class="comment">// 用于回溯之前的一个位置应该调整为哪个数值</span></div><div class="line">	<span class="keyword">for</span> (i = minVal; i &lt;= maxVal; i++)</div><div class="line">	&#123;</div><div class="line">		<span class="keyword">if</span> (cost[n][i-minVal] &lt; minCost)</div><div class="line">		&#123;</div><div class="line">			minCost = cost[n][i-minVal];</div><div class="line">			backtrack = i; <span class="comment">// 找到最后一个调整好的数值对应的前一个数值</span></div><div class="line">		&#125;</div><div class="line">	&#125;</div><div class="line"></div><div class="line">	<span class="built_in">cout</span> &lt;&lt; minCost &lt;&lt; <span class="built_in">endl</span>; <span class="comment">// 输出最小的调整代价</span></div><div class="line"></div><div class="line">	<span class="keyword">int</span> loc = n - <span class="number">1</span>; <span class="comment">// 对应数组B每个下标</span></div><div class="line">	<span class="keyword">int</span> sum = <span class="number">0</span>; <span class="comment">// 用于核对回溯的每个位置的值是否正确，minCost == sum时正确</span></div><div class="line">	<span class="keyword">while</span> (n &gt; <span class="number">0</span>)</div><div class="line">	&#123;</div><div class="line">		B[loc--] = backtrack;</div><div class="line">		sum += <span class="built_in">abs</span>(A[n<span class="number">-1</span>] - backtrack);</div><div class="line">		backtrack = record[n--][backtrack-minVal]; <span class="comment">// 因为每次找到的调整好的数值，所以索引要调整</span></div><div class="line">	&#125;</div><div class="line">	<span class="built_in">cout</span> &lt;&lt; sum &lt;&lt; <span class="built_in">endl</span>; <span class="comment">// 比较sum是否等于minCost</span></div><div class="line"></div><div class="line">	<span class="comment">// 输出调整之后的数组B</span></div><div class="line">	<span class="keyword">for</span> (i = <span class="number">0</span>; i &lt; A.size(); i++)</div><div class="line">		<span class="built_in">cout</span> &lt;&lt; B[i] &lt;&lt; <span class="string">' '</span>;</div><div class="line">	<span class="built_in">cout</span> &lt;&lt; <span class="built_in">endl</span>;</div><div class="line">&#125;</div></pre></td></tr></table></figure></p>
<h2 id="2-钢条切割问题"><a href="#2-钢条切割问题" class="headerlink" title="2.钢条切割问题"></a>2.钢条切割问题</h2><p>接下来我们再来看一下《算法导论》上给的一道经典题目，钢条切割问题。</p>
<p>题目描述：</p>
<p>一家公司有一根固定长度的钢条，要切割为短的钢条出售。切割工序本身没有成本。公司希望知道最佳的切割方案（即如何切割能够获得价格的最大值）。假设钢条的长度为<code>n</code>（此处假设<code>n &lt;= 10</code>），不同长度<code>i</code>的钢条的价格如下表。</p>
<p><table><thead><tr><th style="text-align:center">长度j</th><th style="text-align:center">1</th><th style="text-align:center">2</th><th style="text-align:center">3</th><th style="text-align:center">4</th><th style="text-align:center">5</th><th style="text-align:center">6</th><th style="text-align:center">7</th><th style="text-align:center">8</th><th style="text-align:center">9</th><th style="text-align:center">10</th></tr></thead><thead><tr><th style="text-align:center">价格p</th><th style="text-align:center">1</th><th style="text-align:center">5</th><th style="text-align:center">8</th><th style="text-align:center">9</th><th style="text-align:center">10</th><th style="text-align:center">17</th><th style="text-align:center">17</th><th style="text-align:center">20</th><th style="text-align:center">24</th><th style="text-align:center">30</th></tr></thead></table><br>应用动态规划的思想，我们可以这样考虑问题：假设长度为i时，最佳切割方案时的价格总和为$r[i]$$(0 &lt;= i&lt;= n)$，那么当长度为<code>i+1</code>时，最佳的方案是$r[i+1] = max(p[j] + r[i+1-j]), 1&lt;= j &lt;= i+1$。所以状态转移方程即是：</p>
<p><center>$r[i+1] = max(p[j] + r[i+1-j]),1&lt;= j&lt;= i+1$</center><br>同样，看代码可能思路更清晰：<br><figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// 自底向上实现</span></div><div class="line"><span class="comment">// 数组p记录不同长度的价格，n是所求最大的长度</span></div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">cutRodBottomUp</span><span class="params">(<span class="built_in">vector</span>&lt;<span class="keyword">int</span>&gt; <span class="keyword">const</span> &amp;p, <span class="keyword">int</span> n)</span></span></div><div class="line">&#123;</div><div class="line">	<span class="built_in">vector</span>&lt;<span class="keyword">int</span>&gt; r(n+<span class="number">1</span>, INT_MIN); <span class="comment">// 辅助数组，记录每个长度不同切割方法的最大值。以整型最小值初始化</span></div><div class="line">	r[<span class="number">0</span>] = <span class="number">0</span>; </div><div class="line"></div><div class="line">	<span class="comment">// 动态规划每个长度不同切割方法的最大值</span></div><div class="line">	<span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>; i &lt;= n; i++)</div><div class="line">	&#123;</div><div class="line">		<span class="keyword">int</span> q = INT_MIN;</div><div class="line">		<span class="keyword">for</span> (<span class="keyword">int</span> j = <span class="number">1</span>; j &lt;= i; j++)</div><div class="line">		&#123;</div><div class="line">			q = max(q, p[j<span class="number">-1</span>] + r[i-j]);  <span class="comment">// 找到每个长度切割的最大值。上述解释中的j是长度，j-1对应其下标</span></div><div class="line">		&#125;</div><div class="line">		r[i] = q;</div><div class="line">	&#125;</div><div class="line"></div><div class="line">	<span class="keyword">return</span> r[n];</div><div class="line">&#125;</div></pre></td></tr></table></figure></p>
<p>这时函数返回的是最大的长度，再加一个辅助数组，在每次找出最大价值的时候记录切割位置，就可以找出切割方案了。代码如下：<br><br><figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// 带有输出分割情况功能的版本</span></div><div class="line"><span class="function"><span class="keyword">void</span> <span class="title">cutRodExtended</span><span class="params">(<span class="built_in">vector</span>&lt;<span class="keyword">int</span>&gt; <span class="keyword">const</span> &amp;p, <span class="keyword">int</span> n)</span></span></div><div class="line">&#123;</div><div class="line">	<span class="built_in">vector</span>&lt;<span class="keyword">int</span>&gt; r(n+<span class="number">1</span>, INT_MIN); <span class="comment">// 辅助数组，记录每个长度不同切割方法的最大值</span></div><div class="line">	r[<span class="number">0</span>] = <span class="number">0</span>;</div><div class="line">	<span class="built_in">vector</span>&lt;<span class="keyword">int</span>&gt; s(n+<span class="number">1</span>, <span class="number">0</span>); <span class="comment">// 记录每个长度最大收益时的切割位置</span></div><div class="line">	</div><div class="line">	<span class="keyword">int</span> i, j;</div><div class="line"></div><div class="line">	<span class="comment">// 动态规划步骤</span></div><div class="line">	<span class="keyword">for</span> (i = <span class="number">1</span>; i &lt;= n; i++)</div><div class="line">	&#123;</div><div class="line">		<span class="keyword">int</span> q = INT_MIN;</div><div class="line">		<span class="keyword">for</span> (j = <span class="number">1</span>; j &lt;= i; j++)</div><div class="line">		&#123;</div><div class="line">			<span class="keyword">if</span> (q &lt; p[j<span class="number">-1</span>] + r[i-j])</div><div class="line">			&#123;</div><div class="line">				q = p[j<span class="number">-1</span>] + r[i-j];</div><div class="line">				s[i] = j; <span class="comment">// 记录每个长度最大收益时的切割位置</span></div><div class="line">			&#125;</div><div class="line">			r[i] = q;</div><div class="line">		&#125;</div><div class="line">	&#125;</div><div class="line"></div><div class="line">	<span class="built_in">cout</span> &lt;&lt; r[n] &lt;&lt; <span class="built_in">endl</span>;</div><div class="line">	<span class="comment">// 输出结果</span></div><div class="line">	<span class="keyword">while</span> (n &gt; <span class="number">0</span>)</div><div class="line">	&#123;</div><div class="line">		<span class="built_in">cout</span> &lt;&lt; s[n] &lt;&lt; <span class="string">'\t'</span>;</div><div class="line">		n = n - s[n];</div><div class="line">	&#125;</div><div class="line">	<span class="built_in">cout</span> &lt;&lt; <span class="built_in">endl</span>;</div><div class="line">&#125;</div></pre></td></tr></table></figure></p>
<p>这样，就找到最佳切割方案了。</p>
<h2 id="3-最长公共子序列"><a href="#3-最长公共子序列" class="headerlink" title="3.最长公共子序列"></a>3.最长公共子序列</h2><p>最后，再来看另一道《算法导论》里面的经典问题——最长公共子序列，这到题目也非常适合用辅助数组来记录最优解。</p>
<p>题目描述：</p>
<p>给定两个序列X = {$x_1$, $x_2$, $x_3$, …, $x_m$ }, 和Y = {$y_1$, $y_2$, …, $y_n$}，求<code>X</code>和<code>Y</code>长度最长的公共子序列。公共子序列的定义为，给定两个序列<code>X</code>，<code>Y</code>，如果<code>Z</code>即是<code>X</code>的子序列，也是<code>Y</code>的子序列，我们称它是<code>X</code>和<code>Y</code>的公共子序列。</p>
<p>例如：X = {A, B, C, D, A, B}，Y = {B, D, C, B, A}，那么序列｛B, C, A｝就是X和Y的公共子序列，但不是最长公共子序列。X和Y的最长公共子序列是{B, C, A, B}，其长度为4。</p>
<p>解题思路：</p>
<p>我们假设Z = {$z_1$, …, $z_k$}是X和Y的一个最长公共子序列。1）如果$x_m$ == $y_n$，那么有$z_k$ == $x_m$ == $y_n$，所以$Z_{k-1}$是$X_{m-1}$和$Y_{n-1}$的一个最长公共子序列；2）如果$x_m$ != $y_n$且$x_m$ != $z_k$，那么Z是$X_{m-1}$和Y的一个最长公共子序列；3）如果$x_m$ != $y_n$且$z_k$ != $y_n$，那么Z是X和$Y_{n-1}$的一个最长公共子序列。</p>
<p>我们令$c[i][j]$表示$X_i$和$Y_j$的最长公共子序列的长度，那么可以得到以下关系：</p>
<p>情况1:  $i==0$ 或者 $j== 0$时，$[i][j] = 0$;<br>情况2:  $i,  j &gt; 0$且$x_i$ == $y_j$时， $c[i][j] = c[i-1][j-1] + 1$;<br>情况3:  $i，j &gt; 0$且$x_i$ != $y_j$时， $c[i][j] = max(c[i][j-1], c[i-1][j])$;</p>
<p>这也就是状态转移方程了。</p>
<p>同样，给出带有注释的代码可能更好理解，这里第一个版本返回的是最长公共子序列的长度。<br><figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// 自底向上动态规划</span></div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">LCS</span><span class="params">(<span class="built_in">vector</span>&lt;<span class="keyword">char</span>&gt; &amp;X, <span class="built_in">vector</span>&lt;<span class="keyword">char</span>&gt; &amp;Y)</span></span></div><div class="line">&#123;</div><div class="line">	<span class="keyword">int</span> len1 = X.size();</div><div class="line">	<span class="keyword">int</span> len2 = Y.size();</div><div class="line">	<span class="keyword">int</span> i, j;</div><div class="line"></div><div class="line">	<span class="built_in">vector</span>&lt;<span class="built_in">vector</span>&lt;<span class="keyword">int</span>&gt; &gt; c(len1+<span class="number">1</span>, <span class="built_in">vector</span>&lt;<span class="keyword">int</span>&gt;(len2+<span class="number">1</span>)); <span class="comment">// 辅助二维数组，记录$X_i$, $Y_j$的最长公共子序列</span></div><div class="line">	</div><div class="line">	<span class="comment">// 初始化</span></div><div class="line">	<span class="keyword">for</span> (i = <span class="number">0</span>; i &lt;= len1; i++)</div><div class="line">		c[i][<span class="number">0</span>] = <span class="number">0</span>;</div><div class="line">	<span class="keyword">for</span> (j = <span class="number">0</span>; j &lt;= len2; j++)</div><div class="line">		c[<span class="number">0</span>][j] = <span class="number">0</span>;</div><div class="line"></div><div class="line">	<span class="comment">// 动态规划过程</span></div><div class="line">	<span class="keyword">for</span> (i = <span class="number">1</span>; i &lt;= len1; i++)</div><div class="line">	&#123;</div><div class="line">		<span class="keyword">for</span> (j = <span class="number">1</span>; j &lt;= len2; j++)</div><div class="line">		&#123;</div><div class="line">			<span class="keyword">if</span> (X[i<span class="number">-1</span>] == Y[j<span class="number">-1</span>]) <span class="comment">// 对应状态转移方程中情况2</span></div><div class="line">				c[i][j] = c[i<span class="number">-1</span>][j<span class="number">-1</span>] + <span class="number">1</span>;</div><div class="line">			<span class="keyword">else</span> <span class="keyword">if</span> (c[i<span class="number">-1</span>][j] &gt; c[i][j<span class="number">-1</span>]) <span class="comment">// 对应状态转移方程中情况3</span></div><div class="line">				c[i][j] = c[i<span class="number">-1</span>][j];</div><div class="line">			<span class="keyword">else</span> <span class="comment">// 对应情况3</span></div><div class="line">				c[i][j] = c[i][j<span class="number">-1</span>];</div><div class="line">		&#125;</div><div class="line">	&#125;</div><div class="line"></div><div class="line">	<span class="keyword">return</span> c[len1][len2];</div><div class="line">&#125;</div></pre></td></tr></table></figure></p>
<p>在情况2和情况3的判断中，可以加入判断结果，将结果记录到一个辅助数组，这样就能回溯结果了，代码如下：<br><figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// 自底向上动态规划。path二维数组记录对应X_i, Y_j的最长公共子序列的选择情况。</span></div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">LCS2</span><span class="params">(<span class="built_in">vector</span>&lt;<span class="keyword">char</span>&gt; &amp;X, <span class="built_in">vector</span>&lt;<span class="keyword">char</span>&gt; &amp;Y,<span class="built_in">vector</span>&lt;<span class="built_in">vector</span>&lt;<span class="built_in">string</span>&gt; &gt; &amp;path)</span></span></div><div class="line">&#123;</div><div class="line">	<span class="keyword">int</span> len1 = X.size();</div><div class="line">	<span class="keyword">int</span> len2 = Y.size();</div><div class="line">	<span class="keyword">int</span> i, j;</div><div class="line"></div><div class="line">	<span class="built_in">vector</span>&lt;<span class="built_in">vector</span>&lt;<span class="keyword">int</span>&gt; &gt; c(len1+<span class="number">1</span>, <span class="built_in">vector</span>&lt;<span class="keyword">int</span>&gt;(len2+<span class="number">1</span>)); <span class="comment">// 记录对应位置的结果</span></div><div class="line">	</div><div class="line">	<span class="comment">// 初始化</span></div><div class="line">	path.resize(len1+<span class="number">1</span>);</div><div class="line">	<span class="keyword">for</span> (i = <span class="number">0</span>; i &lt;= len1; i++)</div><div class="line">		path[i].resize(len2+<span class="number">1</span>);</div><div class="line"></div><div class="line">	<span class="keyword">for</span> (i = <span class="number">0</span>; i &lt;= len1; i++)</div><div class="line">		c[i][<span class="number">0</span>] = <span class="number">0</span>;</div><div class="line">	<span class="keyword">for</span> (j = <span class="number">0</span>; j &lt;= len2; j++)</div><div class="line">		c[<span class="number">0</span>][j] = <span class="number">0</span>;</div><div class="line"></div><div class="line">	<span class="comment">// 动态规划过程</span></div><div class="line">	<span class="keyword">for</span> (i = <span class="number">1</span>; i &lt;= len1; i++)</div><div class="line">	&#123;</div><div class="line">		<span class="keyword">for</span> (j = <span class="number">1</span>; j &lt;= len2; j++)</div><div class="line">		&#123;</div><div class="line">			<span class="keyword">if</span> (X[i<span class="number">-1</span>] == Y[j<span class="number">-1</span>])</div><div class="line">			&#123;</div><div class="line">				c[i][j] = c[i<span class="number">-1</span>][j<span class="number">-1</span>] + <span class="number">1</span>;</div><div class="line">				path[i][j] = <span class="string">"left-top"</span>; <span class="comment">// 上一个位置在左上位置</span></div><div class="line">			&#125;</div><div class="line">			<span class="keyword">else</span> <span class="keyword">if</span> (c[i<span class="number">-1</span>][j] &gt; c[i][j<span class="number">-1</span>])</div><div class="line">			&#123;</div><div class="line">				c[i][j] = c[i<span class="number">-1</span>][j];</div><div class="line">				path[i][j] = <span class="string">"up"</span>; <span class="comment">// 上一个位置在上方</span></div><div class="line">			&#125;</div><div class="line">			<span class="keyword">else</span></div><div class="line">			&#123;</div><div class="line">				c[i][j] = c[i][j<span class="number">-1</span>];</div><div class="line">				path[i][j] = <span class="string">"left"</span>; <span class="comment">// 上一个位置在左边</span></div><div class="line">			&#125;</div><div class="line">		&#125;</div><div class="line">	&#125;</div><div class="line"></div><div class="line">	<span class="keyword">return</span> c[len1][len2];</div><div class="line">&#125;</div></pre></td></tr></table></figure></p>
<p>这里配合下图更好理解。<br><img src="http://blog.frankge.me/wp-content/uploads/2016/12/getting-start-to-dynamic-programming-part3-find-the-optimal-solution_001-768x538.png" alt=""></p>
<p>这里的根据路径输出的函数为：<br><figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">void</span> <span class="title">Print_LCS</span><span class="params">(<span class="built_in">vector</span>&lt;<span class="keyword">char</span>&gt; &amp;X, <span class="built_in">vector</span>&lt;<span class="built_in">vector</span>&lt;<span class="built_in">string</span>&gt; &gt; &amp;path, <span class="keyword">int</span> i, <span class="keyword">int</span> j)</span></span></div><div class="line">&#123;</div><div class="line">	<span class="keyword">if</span> (i == <span class="number">0</span> || j == <span class="number">0</span>)</div><div class="line">		<span class="keyword">return</span>;</div><div class="line"></div><div class="line">	<span class="keyword">if</span> (path[i][j] == <span class="string">"left-top"</span>) <span class="comment">// 左上位置</span></div><div class="line">	&#123;</div><div class="line">		Print_LCS_test(X, path, i<span class="number">-1</span>, j<span class="number">-1</span>);</div><div class="line">		<span class="built_in">cout</span> &lt;&lt; X[i<span class="number">-1</span>];</div><div class="line">	&#125;</div><div class="line">	<span class="keyword">else</span> <span class="keyword">if</span> (path[i][j] == <span class="string">"up"</span>) <span class="comment">// 上方</span></div><div class="line">		Print_LCS_test(X, path, i<span class="number">-1</span>, j);</div><div class="line">	<span class="keyword">else</span> <span class="keyword">if</span> (path[i][j] == <span class="string">"left"</span>) <span class="comment">// 左边</span></div><div class="line">		Print_LCS_test(X, path, i, j<span class="number">-1</span>);</div><div class="line">&#125;</div></pre></td></tr></table></figure></p>
<p>参考文献：<br>1.lintcode <a href="http://www.lintcode.com/en/problem/minimum-adjustment-cost/" target="_blank" rel="external">Minimum Adjustment Cost</a>。<br>2.《算法导论（第三版）》，15章，动态规划内容。</p>
]]></content>
    
    <summary type="html">
    
      &lt;p&gt;前两次动态规划的博客中，介绍了动态规划最基础的两个特点以及列举了几个我在做lintcode中遇到的接触动态规划初期相对比较适合做的题目。这次结合几道题目来总结一下动态规划的另一个特点——找到最优时的解。&lt;/p&gt;
&lt;p&gt;同样，还是以题目来说明。&lt;/p&gt;
&lt;h2 id=&quot;1-M
    
    </summary>
    
      <category term="编程学习" scheme="http://skills.frankge.me/categories/%E7%BC%96%E7%A8%8B%E5%AD%A6%E4%B9%A0/"/>
    
    
      <category term="算法" scheme="http://skills.frankge.me/tags/%E7%AE%97%E6%B3%95/"/>
    
  </entry>
  
  <entry>
    <title>wordpress站点迁移方法</title>
    <link href="http://skills.frankge.me/the-way-to-migrate-your-wordpress-website/"/>
    <id>http://skills.frankge.me/the-way-to-migrate-your-wordpress-website/</id>
    <published>2016-11-22T17:08:37.000Z</published>
    <updated>2016-12-01T16:48:37.761Z</updated>
    
    <content type="html"><![CDATA[<p style="text-align: justify;"><br>本文总结了将wordpress从一个站点迁移至另一个站点的过程。<br><br>最早我的博客地址是<span style="color: #3366ff;"><a href="http://blog.frankge.me/" target="_blank" rel="external">frankge.me</a></span>，中间遇到一点问题，所以将博客迁移到了<span style="color: #3366ff;"><a href="http://frankge.me/blog-old-site" target="_blank" rel="external">frankge.me/blog</a></span>，当时有很多内容不清楚，所以才搞到了前一个站点。最近学会了在<span style="color: #3366ff;"><a href="http://blog.frankge.me/install-wordpress-on-a-subdomain-using-cpanel/" target="_blank" rel="external">子域名下安装wordpress</a></span>，所以想把站点从<span style="color: #3366ff;"><a href="http://frankge.me/blog-old-site" target="_blank" rel="external">frankge.me/blog</a></span>迁移到<span style="color: #3366ff;"><a href="http://blog.frankge.me" target="_blank" rel="external">blog.frankge.me</a></span>下。<br><br>这里以我博客的迁移为例，来总结一下不同站点迁移wordpress的步骤。<br></p>

<p style="text-align: justify;">1.原站点的备份。备份包括wordpress以及数据库。wordpress的备份可以通过BackUpWordPress插件来解决，数据库的备份用wordpress自带的工具就可以了。都在<code>控制台</code>-&gt;<code>工具下</code>。<br>2.开通子域名。这里就不详述了，可以参见我的前一篇博文《<span style="color: #3366ff;"><a href="http://blog.frankge.me/install-wordpress-on-a-subdomain-using-cpanel/" target="_blank" rel="external">子域名下安装wordpress</a></span>》。<br>3.迁移站点。<br>1）新建数据库。具体方法参见我的博文《<span style="color: #3366ff;"><a href="http://blog.frankge.me/the-timeline-of-my-blog/" target="_blank" rel="external">博客时间轴</a></span>》中安装wordpress那一节。<br>2）上传备份并解压。将步骤1中备份的wordpress上传到步骤2中新建的文件夹下，并将wordpress解压到此文件夹下。然后你发现自己的站点可以访问了，但是还是有问题。<br>3） 删除<code>wp-config.php</code>文件。删除wordpress安装路径下的<code>wp-config.php</code>文件，此时再进入站点，就出现重新安装wordpress的界面了。这时候填你新建的数据库。其实这里可以不删除<code>wp-config.php</code>文件的，如果你仔细看文件中的内容，会发现只要更改其中的部分设置就可以了。不过直接删除还是挺便捷的。这时候你进入站点发现什么都没了，不过不要急，之前wordpress中都内容都在，只要按照原来的界面给重新设置（主题（你主题中修改的代码都没变）、插件的设置都存在）就好。<br>4） 导入数据。将步骤1中备份的数据库给导入到新的wordpress中，这样博文和评论就恢复了。<br>4.恢复之前的主题等设置。</p>

<p style="text-align: justify;">完成上述的步骤，很多问题就都解决了。</p>

<p style="text-align: justify;">在迁移站点时，遇到了一些问题，现在罗列一下。</p>

<p style="text-align: justify;">1.以前的图片不显示。这个参见<span style="color: #3366ff;"><a href="http://blog.mimvp.com/2015/01/wordpress-replace-the-article-image-is-not-displayed-when-the-domain-name-solutions/" target="_blank" rel="external">这篇博文</a></span>。同时，可能还不能解决，那可能就是因为之前的图片使用的是中文命名。我的博客也出现了这样的问题，以后不要用中文命名了。<br>2.记得更改一下底部的链接。</p>]]></content>
    
    <summary type="html">
    
      &lt;p style=&quot;text-align: justify;&quot;&gt;&lt;br&gt;本文总结了将wordpress从一个站点迁移至另一个站点的过程。&lt;br&gt;&lt;br&gt;最早我的博客地址是&lt;span style=&quot;color: #3366ff;&quot;&gt;&lt;a href=&quot;http://blog.fran
    
    </summary>
    
      <category term="建站相关" scheme="http://skills.frankge.me/categories/%E5%BB%BA%E7%AB%99%E7%9B%B8%E5%85%B3/"/>
    
    
      <category term="我的博客" scheme="http://skills.frankge.me/tags/%E6%88%91%E7%9A%84%E5%8D%9A%E5%AE%A2/"/>
    
  </entry>
  
  <entry>
    <title>子域名下安装wordpress总结</title>
    <link href="http://skills.frankge.me/install-wordpress-on-a-subdomain-using-cpanel/"/>
    <id>http://skills.frankge.me/install-wordpress-on-a-subdomain-using-cpanel/</id>
    <published>2016-11-22T03:48:59.000Z</published>
    <updated>2016-12-01T15:04:09.010Z</updated>
    
    <content type="html"><![CDATA[<p style="text-align: justify;">最近折腾博客，把<span style="color: #3366ff;"><a href="http://frankge.me/blog-old-site/" target="_blank" rel="external">frankge.me/blog</a></span>迁移到了<span style="color: #3366ff;"><a href="http://blog.frankge.me" target="_blank" rel="external">blog.frankge.me</a></span>。这样就要在子域名下安装wordpress。现在把步骤总结一下。</p>

<p style="text-align: justify;">0.你付费的主机可以建立多个站点。有些主机你付费的时候只是给予一个站点的配额，这应该是不能开通子域名的好像。<br><br>1.创建子域。打开cPanel表盘，找到<code>域</code>-&gt;<code>子域</code>，选择<code>创建子域（此处以growth为例）</code>，点击<code>生成邮件列表</code>（图1）。发现下面多了一个条目（图2）。</p>

<p><img src="http://blog.frankge.me/wp-content/uploads/2016/11/install-wordpress-on-a-subdomain-using-cpanel-01-1024x423.png" alt="图1"> </p>
<p><img src="http://blog.frankge.me/wp-content/uploads/2016/11/install-wordpress-on-a-subdomain-using-cpanel-02.png" alt="图2"> </p>
<p style="text-align: justify;">2.上传wordpress。把wordpress上传到刚才<code>生成的文件夹中（/public_html/growth）</code>。<br><br>3.新建一个数据库，用于新站点。创建方法参见《<span style="color: #3366ff;"><a href="http://blog.frankge.me/the-timeline-of-my-blog/" target="_blank" rel="external">博客时间轴</a></span>》中安装wordpress部分。<br><br>4.解析域名。参见《<span style="color: #3366ff;"><a href="http://blog.frankge.me/the-timeline-of-my-blog/" target="_blank" rel="external">博客时间轴</a></span>》中域名解析部分。在根站点下添加<code>A记录</code>。画红线的位置填你主机的ip地址（图3）。</p>

<p><img src="http://blog.frankge.me/wp-content/uploads/2016/11/install-wordpress-on-a-subdomain-using-cpanel-03-1024x430.png" alt="图3"> </p>
<p style="text-align: justify;">5.访问站点，安装wordpress，设置成对应的数据库即可。</p>]]></content>
    
    <summary type="html">
    
      &lt;p style=&quot;text-align: justify;&quot;&gt;最近折腾博客，把&lt;span style=&quot;color: #3366ff;&quot;&gt;&lt;a href=&quot;http://frankge.me/blog-old-site/&quot; target=&quot;_blank&quot; rel=&quot;extern
    
    </summary>
    
      <category term="建站相关" scheme="http://skills.frankge.me/categories/%E5%BB%BA%E7%AB%99%E7%9B%B8%E5%85%B3/"/>
    
    
      <category term="我的博客" scheme="http://skills.frankge.me/tags/%E6%88%91%E7%9A%84%E5%8D%9A%E5%AE%A2/"/>
    
  </entry>
  
  <entry>
    <title>浅谈动态规划（二）——进阶题</title>
    <link href="http://skills.frankge.me/getting-start-to-dynamic-programming-part-2-some-exercises-slightly-difficult-from-lintcode-2/"/>
    <id>http://skills.frankge.me/getting-start-to-dynamic-programming-part-2-some-exercises-slightly-difficult-from-lintcode-2/</id>
    <published>2016-11-15T16:44:43.000Z</published>
    <updated>2016-11-30T16:30:43.130Z</updated>
    
    <content type="html"><![CDATA[<p style="text-align: justify;">上一次的动态规划的文章中（<span style="color: #0000ff;"><a href="http://frankge.me/blog/2016/10/24/getting-start-to-dynamic-programming-part1-some-exercises-from-lintcode/" target="_blank" rel="external">浅谈动态规划（一）——从lintcode刷题入门</a></span>），借助lintcode上两个简单且典型的例子（Triangle和Climbing Stairs），阐述了动态规划的两个特点：1）最优子结构，和2）子问题重叠。这回来讲讲最近做lintcode上的几个难度稍微大一些的题目。这些题目也很符合动态规划的那两个特点。</p>

<p>先来看看第一个题目。</p>
<p>1.<span style="color: #0000ff;"><a href="http://www.lintcode.com/en/problem/paint-fence/" target="_blank" rel="external">Paint Fence（栅栏染色）</a></span></p>
<p>题目描述：</p>
<p style="text-align: justify;">There is a fence with n posts, each post can be painted with one of the k colors. You have to paint all the posts such that no more than two adjacent fence posts have the same color. Return the total number of ways you can paint the fence.<br>Notice: <code>n</code> and <code>k</code> are non-negative integers.</p>

<p>例子：<br>Given <code>n=3</code>, <code>k=2</code> return <code>6</code></p>
<table>
<thead>
<tr>
<th style="text-align:center">item</th>
<th style="text-align:center">post 1</th>
<th style="text-align:center">post 2</th>
<th style="text-align:center">post 3</th>
</tr>
</thead>
<tbody>
<tr>
<td style="text-align:center">way1</td>
<td style="text-align:center">0</td>
<td style="text-align:center">0</td>
<td style="text-align:center">1</td>
</tr>
<tr>
<td style="text-align:center">way2</td>
<td style="text-align:center">0</td>
<td style="text-align:center">1</td>
<td style="text-align:center">0</td>
</tr>
<tr>
<td style="text-align:center">way3</td>
<td style="text-align:center">0</td>
<td style="text-align:center">1</td>
<td style="text-align:center">1</td>
</tr>
<tr>
<td style="text-align:center">way4</td>
<td style="text-align:center">1</td>
<td style="text-align:center">0</td>
<td style="text-align:center">0</td>
</tr>
<tr>
<td style="text-align:center">way5</td>
<td style="text-align:center">1</td>
<td style="text-align:center">0</td>
<td style="text-align:center">1</td>
</tr>
<tr>
<td style="text-align:center">way6</td>
<td style="text-align:center">1</td>
<td style="text-align:center">1</td>
<td style="text-align:center">0</td>
</tr>
</tbody>
</table>
<p>题目中要求给<code>n</code>个栅栏涂颜色，有k种颜色可以选择，限制条件是最多可以有两个相邻的栅栏颜色相同。</p>
<p>解题思路：</p>
<p style="text-align: justify;">令<code>ways[i]( n = 1, 2, 3, ..., n )</code>表示涂到第i个栅栏时的所有的方法数。这样，题目就符合动态规划的两个特征（参考之前的那篇文章分析），就可以用动态规划求解。那么我们在涂第i个栅栏的时候，有两种涂色方式：1）和第<code>i-1</code>个栅栏的颜色相同；2）和第<code>i-1</code>个栅栏的颜色不同。在1）方式下，因为要保证最多只有两个相邻的栅栏颜色相同，所以第i个栅栏的颜色和第i-2个栅栏的颜色必然是不同的，那么此时有<code>ways[i-2] * (k-1)</code>中填涂的方式。在2）方式下，不需要考虑之前的栅栏的颜色，只要保证和<code>i-1</code>个栅栏颜色不同即可，此时有<code>ways[i-1] * (k-1）</code>种方法。所以有状态转移方程：</p>

<p><code>ways[i] = ways[i-2] * (k-1) + ways[i-1] * (k-1)</code></p>
<p style="text-align: justify;">同时发现，每次只要用到相邻的3个栅栏的方法数就可以了，这样可以减少空间的使用。所以代码为：</p>

<figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">numWays</span><span class="params">(<span class="keyword">int</span> n, <span class="keyword">int</span> k)</span> </span>&#123;</div><div class="line">	<span class="comment">// Write your code here</span></div><div class="line">	<span class="keyword">if</span> (n == <span class="number">0</span> || k == <span class="number">0</span>)</div><div class="line">		<span class="keyword">return</span> <span class="number">0</span>;</div><div class="line">		</div><div class="line">	<span class="keyword">if</span> (n == <span class="number">1</span>)</div><div class="line">		<span class="keyword">return</span> k;</div><div class="line">	<span class="keyword">if</span> (n == <span class="number">2</span>)</div><div class="line">		<span class="keyword">return</span> k * k;</div><div class="line">		</div><div class="line">	<span class="keyword">int</span> ways[<span class="number">3</span>] = &#123;<span class="number">0</span>&#125;; <span class="comment">// 辅助数组，只使用3个变量即可</span></div><div class="line">	ways[<span class="number">0</span>] = k;</div><div class="line">	ways[<span class="number">1</span>] = k * k;</div><div class="line">		</div><div class="line">	<span class="comment">// 动态规划步骤</span></div><div class="line">	<span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">2</span>; i &lt; n; i++)</div><div class="line">	&#123;</div><div class="line">		ways[<span class="number">2</span>] = (k<span class="number">-1</span>) * (ways[<span class="number">0</span>] + ways[<span class="number">1</span>]); <span class="comment">// 依据相邻的两个栅栏的填涂方法数来求解第3个栅栏的填涂方法数</span></div><div class="line">		ways[<span class="number">0</span>] = ways[<span class="number">1</span>];</div><div class="line">		ways[<span class="number">1</span>] = ways[<span class="number">2</span>];</div><div class="line">	&#125;</div><div class="line">		</div><div class="line">	<span class="keyword">return</span> ways[<span class="number">2</span>];</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p style="text-align: justify;">这道题虽然也是简单的，但是因为限制条件的运用比较巧妙，所以给贴出来了。接下来看看下一题。</p>

<p>2.<span style="color: #0000ff;"><a href="http://www.lintcode.com/en/problem/house-robber/" target="_blank" rel="external">House Robber（打劫房屋）</a></span></p>
<p>题目描述：</p>
<p style="text-align: justify;">You are a professional robber planning to rob houses along a street. Each house has a certain amount of money stashed, the only constraint stopping you from robbing each of them is that adjacent houses have security system connected and it will automatically contact the police if two adjacent houses were broken into on the same night.</p>

<p style="text-align: justify;">Given a list of non-negative integers representing the amount of money of each house, determine the maximum amount of money you can rob tonight without alerting the police.</p>

<p>例子：<br>Given <code>[3, 8, 4]</code>, return <code>8</code>.</p>
<p style="text-align: justify;">题目要求从<code>n</code>个房屋中找出一些房屋取走里面财产，找到财产最大的总值，限制条件是不能有相邻的房屋同时被偷盗。</p>

<p style="text-align: justify;">这道题虽然是道中等题，不过思路也很清晰，动态规划的两个特征也非常明显。令<code>money[i]( i = 1, 2, ..., n )</code>表示在偷第i个房屋时的最大值，那么在偷第i个房屋时，需要比较的只是<code>money[i-1]</code>和<code>money[i-2] + A[i]</code>值的大小(<code>A[i]</code>是第i个房屋的财产值)，因为相邻的两个房屋不可能同时被偷。所以，状态转移方程为：</p>

<p><code>money[i] = max(money[i-1], money[i-2] + A[i])</code></p>
<p style="text-align: justify;">同样，我们发现每次比较时，只需要保留最近两次的最大值即可，那么优化后的代码为：</p>

<figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">long</span> <span class="keyword">long</span> <span class="title">houseRobber</span><span class="params">(<span class="built_in">vector</span>&lt;<span class="keyword">int</span>&gt; A)</span> </span>&#123;</div><div class="line">	<span class="comment">// write your code here</span></div><div class="line">	<span class="keyword">int</span> n = A.size();</div><div class="line"></div><div class="line">	<span class="keyword">if</span> (n == <span class="number">0</span>)</div><div class="line">		<span class="keyword">return</span> <span class="number">0</span>;</div><div class="line">	</div><div class="line">	<span class="keyword">if</span> (n == <span class="number">1</span>)</div><div class="line">		<span class="keyword">return</span> A[<span class="number">0</span>];</div><div class="line">	</div><div class="line">	<span class="comment">// 辅助数组</span></div><div class="line">	<span class="keyword">long</span> <span class="keyword">long</span> money[<span class="number">3</span>] = &#123;<span class="number">0</span>&#125;;</div><div class="line">	money[<span class="number">0</span>] = <span class="number">0</span>;</div><div class="line">	money[<span class="number">1</span>] = A[<span class="number">0</span>];</div><div class="line">	</div><div class="line">	<span class="comment">// 动态规划步骤</span></div><div class="line">	<span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">2</span>; i &lt;= n; i++)</div><div class="line">	&#123;</div><div class="line">		money[<span class="number">2</span>] = max(A[i<span class="number">-1</span>] + money[<span class="number">0</span>], money[<span class="number">1</span>]);</div><div class="line">		money[<span class="number">0</span>] = money[<span class="number">1</span>];</div><div class="line">		money[<span class="number">1</span>] = money[<span class="number">2</span>];</div><div class="line">	&#125;</div><div class="line">	</div><div class="line">	<span class="keyword">return</span> money[<span class="number">2</span>];</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p>最后来看第3题。</p>
<p>3.<span style="color: #0000ff;"><a href="http://www.lintcode.com/en/problem/paint-house/" target="_blank" rel="external">Paint House（房屋染色）</a></span></p>
<p>题目描述：</p>
<p style="text-align: justify;">There are a row of n houses, each house can be painted with one of the three colors: <code>red</code>, <code>blue</code> or <code>green</code>. The cost of painting each house with a certain color is different. You have to paint all the houses such that no two adjacent houses have the same color.</p>

<p style="text-align: justify;">The cost of painting each house with a certain color is represented by a <code>n x 3</code> cost matrix. For example, <code>costs[0][0]</code> is the cost of painting house 0 with color red; <code>costs[1][2]</code> is the cost of painting house 1 with color green, and so on… Find the minimum cost to paint all houses.</p>

<p>Notice: All costs are positive integers.</p>
<p>例子：</p>
<p>Given <code>costs = [[14,2,11],[11,14,5],[14,3,10]]</code> return <code>10</code></p>
<p>house <code>0</code> is blue, house <code>1</code> is green, house <code>2</code> is blue, <code>2 + 5 + 3 = 10</code></p>
<p style="text-align: justify;">题目要求给n个房子粉刷颜色，找到最小的费用。粉刷时有3种颜色可供选择，而粉刷不同的颜色的费用是不同的，限制条件是相邻的两个房子的颜色不能相同。这道题目其实和上一道题目有点类似，均为相邻的两个有限制，不过这个在动态规划的时候，比较的是粉刷的不同的颜色。同样的方法，令<code>value[i][j](i = 1, 2, ..., n; j = 1, 2, 3)</code>表示正在粉刷第i个房子的时候颜色为j时的总费用（之前粉刷的位置均保证了费用最小）。为了避免相邻的两个房子粉刷的颜色相同，在粉刷每一层的时候，还要和前一层粉刷的颜色比较。那么在粉刷第i个房屋颜色为j时的状态转移方程为：</p>

<p><code>value[i][j] = min(costs[i][j] + value[i-1][k]), k = 1, 2, 3; k != j</code></p>
<p style="text-align: justify;">上式中<code>k</code>是上一层粉刷不同颜色到达最小值时的不同颜色。在粉刷时要保证相邻的两层颜色不相同，所以<code>k != j</code>。</p>

<p>有了状态转移方程，题目的代码就好写了：</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">minCost2</span><span class="params">(<span class="built_in">vector</span>&lt;<span class="built_in">vector</span>&lt;<span class="keyword">int</span>&gt; &gt; &amp;costs)</span></span></div><div class="line">&#123;</div><div class="line">	<span class="keyword">int</span> n = costs.size();</div><div class="line"></div><div class="line">	<span class="keyword">if</span> (n == <span class="number">0</span>)</div><div class="line">		<span class="keyword">return</span> <span class="number">0</span>;</div><div class="line">	</div><div class="line">	<span class="keyword">int</span> i, j, k;</div><div class="line">	<span class="keyword">int</span> temp;</div><div class="line">	<span class="keyword">int</span> minValue = INT_MAX;</div><div class="line">			</div><div class="line">	<span class="keyword">for</span> (j = <span class="number">0</span>; j &lt; <span class="number">3</span>; j++) </div><div class="line">            <span class="keyword">if</span> (minValue &gt; costs[<span class="number">0</span>][j])</div><div class="line">	        minValue = costs[<span class="number">0</span>][j];</div><div class="line">					   </div><div class="line">	<span class="keyword">if</span> (n == <span class="number">1</span>)</div><div class="line">		<span class="keyword">return</span> minValue;</div><div class="line"></div><div class="line">	<span class="built_in">vector</span>&lt;<span class="built_in">vector</span>&lt;<span class="keyword">int</span>&gt; &gt; value(n, <span class="built_in">vector</span>&lt;<span class="keyword">int</span>&gt;(<span class="number">3</span>, INT_MAX)); <span class="comment">// 辅助数组，初始化时每个位置均为INT_MAX</span></div><div class="line"></div><div class="line">	<span class="comment">// 动态规划步骤</span></div><div class="line">	<span class="keyword">for</span> (i = <span class="number">0</span>; i &lt; n; i++)</div><div class="line">	&#123;</div><div class="line">		<span class="keyword">if</span> (i == <span class="number">0</span>)</div><div class="line">		&#123;</div><div class="line">			<span class="keyword">for</span> (j = <span class="number">0</span>; j &lt; <span class="number">3</span>; j++)</div><div class="line">				value[i][j] = costs[i][j];</div><div class="line"></div><div class="line">			<span class="keyword">continue</span>;</div><div class="line">		&#125;</div><div class="line"></div><div class="line">		<span class="comment">// 找出相邻两层不相同时，粉刷不同颜色的最小值</span></div><div class="line">		<span class="keyword">for</span> (j = <span class="number">0</span>; j &lt; <span class="number">3</span>; j++)</div><div class="line">		&#123;</div><div class="line">			minValue = INT_MAX;</div><div class="line">			<span class="keyword">for</span> (k = <span class="number">0</span>; k &lt; <span class="number">3</span>; k++) <span class="comment">// 上一层粉刷不同颜色时对应的最小值</span></div><div class="line">			&#123;</div><div class="line">				<span class="keyword">if</span> (k == j) <span class="comment">// 跳过相同颜色</span></div><div class="line">					<span class="keyword">continue</span>;</div><div class="line">				<span class="comment">// 找出最小值</span></div><div class="line">				temp = costs[i][j] + value[i<span class="number">-1</span>][k];</div><div class="line">				<span class="keyword">if</span> (temp &lt; minValue)</div><div class="line">					minValue = temp;</div><div class="line">			&#125;</div><div class="line">			value[i][j] = minValue;</div><div class="line">		&#125;</div><div class="line">	&#125;</div><div class="line"></div><div class="line">	<span class="comment">// 找出粉刷完最后一个房屋时的最小费用</span></div><div class="line">	minValue = INT_MAX;</div><div class="line">	<span class="keyword">for</span> (j = <span class="number">0</span>; j &lt; <span class="number">3</span>; j++) </div><div class="line">            <span class="keyword">if</span> (minValue &gt; value[n<span class="number">-1</span>][j])</div><div class="line">		minValue = value[n<span class="number">-1</span>][j];</div><div class="line"></div><div class="line">	<span class="keyword">return</span> minValue;</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p style="text-align: justify;">同样，代码也可以优化以减少空间消耗，在这里就不再将最后结果贴出来了。</p>

<p style="text-align: justify;">好了，这就是这次的全部内容。这些题目是我在刷lintcode中遇到的动态规划特征比较明显的题目，且比《<span style="color: #0000ff;"><a href="http://frankge.me/blog/2016/10/24/getting-start-to-dynamic-programming-part1-some-exercises-from-lintcode/" target="_blank" rel="external">浅谈动态规划（一）——从lintcode刷题入门</a></span>》里面的一些题目稍微难点。希望能够给初接触动态规划的童鞋一点参考。</p>

<p>参考资料：<br>lintcode<br>1.<span style="color: #0000ff;"><a href="http://www.lintcode.com/en/problem/paint-fence/" target="_blank" rel="external">Paint Fence（栅栏染色）</a></span><br>2.<span style="color: #0000ff;"><a href="http://www.lintcode.com/en/problem/house-robber/" target="_blank" rel="external">House Robber（打劫房屋）</a></span><br>3.<span style="color: #0000ff;"><a href="http://www.lintcode.com/en/problem/paint-house/" target="_blank" rel="external">Paint House（房屋染色）</a></span></p>
]]></content>
    
    <summary type="html">
    
      &lt;p style=&quot;text-align: justify;&quot;&gt;上一次的动态规划的文章中（&lt;span style=&quot;color: #0000ff;&quot;&gt;&lt;a href=&quot;http://frankge.me/blog/2016/10/24/getting-start-to-dynam
    
    </summary>
    
      <category term="编程学习" scheme="http://skills.frankge.me/categories/%E7%BC%96%E7%A8%8B%E5%AD%A6%E4%B9%A0/"/>
    
    
      <category term="算法" scheme="http://skills.frankge.me/tags/%E7%AE%97%E6%B3%95/"/>
    
  </entry>
  
  <entry>
    <title>windows下MatConvNet深度学习框架的搭建</title>
    <link href="http://skills.frankge.me/matconvnet-installation-in-windows-system/"/>
    <id>http://skills.frankge.me/matconvnet-installation-in-windows-system/</id>
    <published>2016-10-25T08:28:07.000Z</published>
    <updated>2016-12-03T06:27:47.684Z</updated>
    
    <content type="html"><![CDATA[<p><br></p>
<h3 id="16-11-29更新"><a href="#16-11-29更新" class="headerlink" title="16.11.29更新"></a>16.11.29更新</h3><p style="text-align: justify;"><br>1.添加beta23版本安装出现的问题。<br><br>最近安装beta23版本，出现<code>vl_compilenn()</code>函数运行时报错如下：</p>

<figure class="highlight matlab"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div><div class="line">66</div><div class="line">67</div><div class="line">68</div><div class="line">69</div><div class="line">70</div><div class="line">71</div><div class="line">72</div><div class="line">73</div><div class="line">74</div><div class="line">75</div><div class="line">76</div><div class="line">77</div><div class="line">78</div><div class="line">79</div><div class="line">80</div><div class="line">81</div><div class="line">82</div><div class="line">83</div><div class="line">84</div><div class="line">85</div><div class="line">86</div><div class="line">87</div><div class="line">88</div><div class="line">89</div><div class="line">90</div><div class="line">91</div><div class="line">92</div><div class="line">93</div><div class="line">94</div><div class="line">95</div><div class="line">96</div><div class="line">97</div><div class="line">98</div><div class="line">99</div><div class="line">100</div><div class="line">101</div><div class="line">102</div><div class="line">103</div><div class="line">104</div><div class="line">105</div><div class="line">106</div><div class="line">107</div><div class="line">108</div><div class="line">109</div><div class="line">110</div><div class="line">111</div><div class="line">112</div><div class="line">113</div><div class="line">114</div><div class="line">115</div><div class="line">116</div><div class="line">117</div><div class="line">118</div></pre></td><td class="code"><pre><div class="line">错误使用 mex</div><div class="line">roipooling_cpu.cpp</div><div class="line">E:\postgraduate\project\Machine Learning\Deep</div><div class="line">Learning\CNN\matconvnet<span class="number">-1.0</span>-beta23\matlab\src\bits\impl\roipooling_cpu.cpp(<span class="number">120</span>) : warning C4244:</div><div class="line">“初始化”: 从“const double”转换到“float”，可能丢失数据</div><div class="line">        E:\postgraduate\project\Machine Learning\Deep</div><div class="line">        Learning\CNN\matconvnet<span class="number">-1.0</span>-beta23\matlab\src\bits\impl\roipooling_cpu.cpp(<span class="number">324</span>): 参见对正在编</div><div class="line">        译的函数 模板 实例化“void roipooling_forward_cpu&lt;type,acc_sum&lt;type&gt;&gt;(type *,const type</div><div class="line">        *,size_t,size_t,size_t,size_t,const type *,size_t,const int [],const double [])”的引用</div><div class="line">        with</div><div class="line">        [</div><div class="line">            type=float</div><div class="line">        ]</div><div class="line">        E:\postgraduate\project\Machine Learning\Deep</div><div class="line">        Learning\CNN\matconvnet<span class="number">-1.0</span>-beta23\matlab\src\bits\impl\roipooling_cpu.cpp(<span class="number">320</span>): 编译类 模板</div><div class="line">        成员函数“vl::ErrorCode vl::impl::roipooling_average&lt;dev,type&gt;::forward(type *,const type</div><div class="line">        *,size_t,size_t,size_t,size_t,const type *,size_t,const int [],const double [])”时</div><div class="line">        with</div><div class="line">        [</div><div class="line">            dev=VLDT_CPU,</div><div class="line">            type=float</div><div class="line">        ]</div><div class="line">        E:\postgraduate\project\Machine Learning\Deep</div><div class="line">        Learning\CNN\matconvnet<span class="number">-1.0</span>-beta23\matlab\src\bits\impl\roipooling_cpu.cpp(<span class="number">350</span>): 参见对正在编</div><div class="line">        译的类 模板 实例化“vl::impl::roipooling_average&lt;dev,type&gt;”的引用</div><div class="line">        with</div><div class="line">        [</div><div class="line">            dev=VLDT_CPU,</div><div class="line">            type=float</div><div class="line">        ]</div><div class="line">E:\postgraduate\project\Machine Learning\Deep</div><div class="line">Learning\CNN\matconvnet<span class="number">-1.0</span>-beta23\matlab\src\bits\impl\roipooling_cpu.cpp(<span class="number">121</span>) : warning C4244:</div><div class="line">“初始化”: 从“const double”转换到“float”，可能丢失数据</div><div class="line">E:\postgraduate\project\Machine Learning\Deep</div><div class="line">Learning\CNN\matconvnet<span class="number">-1.0</span>-beta23\matlab\src\bits\impl\roipooling_cpu.cpp(<span class="number">122</span>) : warning C4244:</div><div class="line">“初始化”: 从“const double”转换到“float”，可能丢失数据</div><div class="line">E:\postgraduate\project\Machine Learning\Deep</div><div class="line">Learning\CNN\matconvnet<span class="number">-1.0</span>-beta23\matlab\src\bits\impl\roipooling_cpu.cpp(<span class="number">123</span>) : warning C4244:</div><div class="line">“初始化”: 从“const double”转换到“float”，可能丢失数据</div><div class="line">E:\postgraduate\project\Machine Learning\Deep</div><div class="line">Learning\CNN\matconvnet<span class="number">-1.0</span>-beta23\matlab\src\bits\impl\roipooling_cpu.cpp(<span class="number">128</span>) : error C3861:</div><div class="line">“<span class="built_in">round</span>”: 找不到标识符</div><div class="line">E:\postgraduate\project\Machine Learning\Deep</div><div class="line">Learning\CNN\matconvnet<span class="number">-1.0</span>-beta23\matlab\src\bits\impl\roipooling_cpu.cpp(<span class="number">129</span>) : error C3861:</div><div class="line">“<span class="built_in">round</span>”: 找不到标识符</div><div class="line">E:\postgraduate\project\Machine Learning\Deep</div><div class="line">Learning\CNN\matconvnet<span class="number">-1.0</span>-beta23\matlab\src\bits\impl\roipooling_cpu.cpp(<span class="number">130</span>) : error C3861:</div><div class="line">“<span class="built_in">round</span>”: 找不到标识符</div><div class="line">E:\postgraduate\project\Machine Learning\Deep</div><div class="line">Learning\CNN\matconvnet<span class="number">-1.0</span>-beta23\matlab\src\bits\impl\roipooling_cpu.cpp(<span class="number">131</span>) : error C3861:</div><div class="line">“<span class="built_in">round</span>”: 找不到标识符</div><div class="line">E:\postgraduate\project\Machine Learning\Deep</div><div class="line">Learning\CNN\matconvnet<span class="number">-1.0</span>-beta23\matlab\src\bits\impl\roipooling_cpu.cpp(<span class="number">167</span>) : warning C4267:</div><div class="line">“初始化”: 从“size_t”转换到“const int”，可能丢失数据</div><div class="line">E:\postgraduate\project\Machine Learning\Deep</div><div class="line">Learning\CNN\matconvnet<span class="number">-1.0</span>-beta23\matlab\src\bits\impl\roipooling_cpu.cpp(<span class="number">208</span>) : warning C4244:</div><div class="line">“初始化”: 从“const double”转换到“float”，可能丢失数据</div><div class="line">        E:\postgraduate\project\Machine Learning\Deep</div><div class="line">        Learning\CNN\matconvnet<span class="number">-1.0</span>-beta23\matlab\src\bits\impl\roipooling_cpu.cpp(<span class="number">342</span>): 参见对正在编</div><div class="line">        译的函数 模板 实例化“void roipooling_backward_cpu&lt;type,acc_sum&lt;type&gt;&gt;(type *,const type</div><div class="line">        *,size_t,size_t,size_t,size_t,const type *,size_t,const type *,const int [],const double</div><div class="line">        [])”的引用</div><div class="line">        with</div><div class="line">        [</div><div class="line">            type=float</div><div class="line">        ]</div><div class="line">        E:\postgraduate\project\Machine Learning\Deep</div><div class="line">        Learning\CNN\matconvnet<span class="number">-1.0</span>-beta23\matlab\src\bits\impl\roipooling_cpu.cpp(<span class="number">337</span>): 编译类 模板</div><div class="line">        成员函数“vl::ErrorCode vl::impl::roipooling_average&lt;dev,type&gt;::backward(type *,const type</div><div class="line">        *,size_t,size_t,size_t,size_t,const type *,size_t,const type *,const int [],const double</div><div class="line">        [])”时</div><div class="line">        with</div><div class="line">        [</div><div class="line">            dev=VLDT_CPU,</div><div class="line">            type=float</div><div class="line">        ]</div><div class="line">E:\postgraduate\project\Machine Learning\Deep</div><div class="line">Learning\CNN\matconvnet<span class="number">-1.0</span>-beta23\matlab\src\bits\impl\roipooling_cpu.cpp(<span class="number">209</span>) : warning C4244:</div><div class="line">“初始化”: 从“const double”转换到“float”，可能丢失数据</div><div class="line">E:\postgraduate\project\Machine Learning\Deep</div><div class="line">Learning\CNN\matconvnet<span class="number">-1.0</span>-beta23\matlab\src\bits\impl\roipooling_cpu.cpp(<span class="number">210</span>) : warning C4244:</div><div class="line">“初始化”: 从“const double”转换到“float”，可能丢失数据</div><div class="line">E:\postgraduate\project\Machine Learning\Deep</div><div class="line">Learning\CNN\matconvnet<span class="number">-1.0</span>-beta23\matlab\src\bits\impl\roipooling_cpu.cpp(<span class="number">211</span>) : warning C4244:</div><div class="line">“初始化”: 从“const double”转换到“float”，可能丢失数据</div><div class="line">E:\postgraduate\project\Machine Learning\Deep</div><div class="line">Learning\CNN\matconvnet<span class="number">-1.0</span>-beta23\matlab\src\bits\impl\roipooling_cpu.cpp(<span class="number">216</span>) : error C3861:</div><div class="line">“<span class="built_in">round</span>”: 找不到标识符</div><div class="line">E:\postgraduate\project\Machine Learning\Deep</div><div class="line">Learning\CNN\matconvnet<span class="number">-1.0</span>-beta23\matlab\src\bits\impl\roipooling_cpu.cpp(<span class="number">217</span>) : error C3861:</div><div class="line">“<span class="built_in">round</span>”: 找不到标识符</div><div class="line">E:\postgraduate\project\Machine Learning\Deep</div><div class="line">Learning\CNN\matconvnet<span class="number">-1.0</span>-beta23\matlab\src\bits\impl\roipooling_cpu.cpp(<span class="number">218</span>) : error C3861:</div><div class="line">“<span class="built_in">round</span>”: 找不到标识符</div><div class="line">E:\postgraduate\project\Machine Learning\Deep</div><div class="line">Learning\CNN\matconvnet<span class="number">-1.0</span>-beta23\matlab\src\bits\impl\roipooling_cpu.cpp(<span class="number">219</span>) : error C3861:</div><div class="line">“<span class="built_in">round</span>”: 找不到标识符</div><div class="line">E:\postgraduate\project\Machine Learning\Deep</div><div class="line">Learning\CNN\matconvnet<span class="number">-1.0</span>-beta23\matlab\src\bits\impl\roipooling_cpu.cpp(<span class="number">227</span>) : warning C4244:</div><div class="line">“初始化”: 从“double”转换到“const float”，可能丢失数据</div><div class="line">E:\postgraduate\project\Machine Learning\Deep</div><div class="line">Learning\CNN\matconvnet<span class="number">-1.0</span>-beta23\matlab\src\bits\impl\roipooling_cpu.cpp(<span class="number">228</span>) : warning C4244:</div><div class="line">“初始化”: 从“double”转换到“const float”，可能丢失数据</div><div class="line">E:\postgraduate\project\Machine Learning\Deep</div><div class="line">Learning\CNN\matconvnet<span class="number">-1.0</span>-beta23\matlab\src\bits\impl\roipooling_cpu.cpp(<span class="number">250</span>) : warning C4267:</div><div class="line">“初始化”: 从“size_t”转换到“const int”，可能丢失数据</div><div class="line"></div><div class="line"></div><div class="line"></div><div class="line">出错 vl_compilenn&gt;mex_compile (line <span class="number">529</span>)</div><div class="line">mex(mopts&#123;:&#125;) ;</div><div class="line"></div><div class="line">出错 vl_compilenn (line <span class="number">490</span>)</div><div class="line">    mex_compile(opts, srcs&#123;i&#125;, objfile, flags.mexcc) ;</div><div class="line"></div><div class="line">出错 compile (line <span class="number">2</span>)</div><div class="line"></div><div class="line">vl_compilenn;</div></pre></td></tr></table></figure>
<p style="text-align: justify;">解决方案是在<code>matconvnet-1.0-beta23\matlab\src\bits\impl</code>文件夹下的<code>roipooling_cpu.cpp</code>文件中添加如下代码：</p>

<figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">double</span> <span class="title">round</span><span class="params">(<span class="keyword">double</span> r)</span></span></div><div class="line">&#123;</div><div class="line"><span class="keyword">return</span> (r &gt; <span class="number">0.0</span>) ? <span class="built_in">floor</span>(r + <span class="number">0.5</span>) : <span class="built_in">ceil</span>(r - <span class="number">0.5</span>);</div><div class="line"></div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p style="text-align: justify;">对比一下之前的cpp文件，添加后前几行代码如下：</p>

<figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// @author Abishek Dutta</span></div><div class="line"><span class="comment">// @author Andrea Vedaldi</span></div><div class="line"></div><div class="line"><span class="comment">/*</span></div><div class="line">Copyright (C) 2016 Hakan Bilen, Abishek Dutta, and Andrea Vedaldi.</div><div class="line">All rights reserved.</div><div class="line"></div><div class="line">This file is part of the VLFeat library and is made available under</div><div class="line">the terms of the BSD license (see the COPYING file).</div><div class="line">*/</div><div class="line"></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">"matrix.h"</span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">"../data.hpp"</span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">"roipooling.hpp"</span></span></div><div class="line"></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;limits&gt;</span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;algorithm&gt;</span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;cmath&gt;</span></span></div><div class="line"></div><div class="line"><span class="keyword">using</span> <span class="built_in">std</span>::max ;</div><div class="line"><span class="keyword">using</span> <span class="built_in">std</span>::min ;</div><div class="line"></div><div class="line"><span class="comment">/* ---------------------------------------------------------------- */</span></div><div class="line"><span class="comment">/*                                            max roipooling helper */</span></div><div class="line"><span class="comment">/* ---------------------------------------------------------------- */</span></div><div class="line"></div><div class="line"><span class="comment">/*************16.11.29添加*******************/</span></div><div class="line"><span class="comment">// @Frank</span></div><div class="line"><span class="comment">// from https://github.com/vlfeat/matconvnet/issues/722</span></div><div class="line"><span class="function"><span class="keyword">double</span> <span class="title">round</span><span class="params">(<span class="keyword">double</span> r)</span></span></div><div class="line">&#123;</div><div class="line"><span class="keyword">return</span> (r &gt; <span class="number">0.0</span>) ? <span class="built_in">floor</span>(r + <span class="number">0.5</span>) : <span class="built_in">ceil</span>(r - <span class="number">0.5</span>);</div><div class="line">&#125;</div><div class="line"><span class="comment">/*************16.11.29添加*******************/</span></div><div class="line"></div><div class="line"><span class="keyword">template</span> &lt;<span class="keyword">typename</span> type&gt;</div><div class="line"><span class="keyword">struct</span> acc_max</div><div class="line"><span class="comment">// 以下代码省略</span></div></pre></td></tr></table></figure>
<h3 id="博客原文"><a href="#博客原文" class="headerlink" title="博客原文"></a>博客原文</h3><p style="text-align: justify;"><span style="color: #3366ff;"><a href="http://www.vlfeat.org/matconvnet/" target="_blank" rel="external">MatConvNet</a></span>是Matlab下用于机器视觉的一个工具包，主要应用是CNN网络，当然其他的网络也涉及到了。MatConvNet简洁、高效，可以用于图片分类、分割和人脸识别等等深度学习的功能。具体的可以参见官网的介绍。</p>

<p style="text-align: justify;">在搭建环境的过程中，发现如今网上对其的资源不太多，所以在这做一个总结。以beta22版本为例。</p>

<p>过程分为下面几个步骤：<br>1.MatConvNet的下载<br>2.GPU模式的使用<br>3.测试</p>
<p>1.MatConvNet的下载</p>
<p style="text-align: justify;">在其<span style="color: #3366ff;"><a href="http://www.vlfeat.org/matconvnet/" target="_blank" rel="external">官网的页面</a></span>进行下载，解压到适当的位置。</p>

<p style="text-align: justify;">运行其中<code>matconvnet-1.0-beta22\examples\vggfaces</code>路径下的<code>cnn_vgg_faces.m</code>文件，会出现下面的结果，那么说明已经可以使用了。在运行前最好把其中要下载的一些内容给放到对应的文件夹下，这样可以节省一点等待的时间。</p>

<p><img src="http://blog.frankge.me/wp-content/uploads/2016/10/matconvnet-installation-in-windows-system-01.png" alt="matconvnet-installation-in-windows-system-01"></p>
<p>2.GPU模式的使用</p>
<p style="text-align: justify;">官网的<span style="color: #3366ff;"><a href="http://www.vlfeat.org/matconvnet/install/" target="_blank" rel="external">这个页面</a></span>中，提到了搭建GPU的方式。</p>

<p style="text-align: justify;">首先，安装CUDA，在<span style="color: #3366ff;"><a href="https://developer.nvidia.com/cuda-downloads" target="_blank" rel="external">这个页面</a></span>有下载。记得下载和自己系统以及显卡支持的CUDA。</p>

<p style="text-align: justify;">接下来，要下载cuDNN(The NVIDIA CUDA Deep Neural Network library)。cuDNN是用于GPU加速的一个库函数。在<span style="color: #3366ff;"><a href="https://developer.nvidia.com/cudnn" target="_blank" rel="external">这个页面</a></span>有下载。</p>

<p style="text-align: justify;">然后把解压好的<code>cuDNN</code>放在合适的文件夹下，建议在<code>MatConvNet</code>下建立<code>local</code>文件夹，同时把<code>cuDNN</code>文件夹中<code>bin</code>文件夹下的<code>cudnn64_5.dll</code>文件复制到<code>matconvnet-1.0-beta22\matlab\mex</code>文件夹下。</p>

<p style="text-align: justify;">最后，在MatConvNet文件夹下建立<code>compileGPU.m</code>文件，其中内容如下。记得把对应的路径给改成自己电脑中的路径。</p>

<figure class="highlight matlab"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line">addpath matlab;</div><div class="line"></div><div class="line"><span class="comment">%% with cudnn</span></div><div class="line">vl_compilenn(<span class="string">'enableGpu'</span>, true, ...</div><div class="line">                <span class="string">'cudaRoot'</span>, <span class="string">'C:\Program Files\NVIDIA GPU Computing Toolkit\CUDA\v8.0'</span>, ...  <span class="comment">% CUDA的安装路径</span></div><div class="line">                <span class="string">'cudaMethod'</span>, <span class="string">'nvcc'</span>, <span class="string">'enableCudnn'</span>, <span class="string">'true'</span>, ...</div><div class="line">                <span class="string">'cudnnRoot'</span>, <span class="string">'E:\postgraduate\project\Machine Learning\Deep Learning\CNN\matconvnet-1.0-beta22\local\cudnn'</span>);   <span class="comment">% cuDNN的路径</span></div></pre></td></tr></table></figure>
<p style="text-align: justify;">出现下面图片中类似的结果，就代表成功了。</p>

<p><img src="http://blog.frankge.me/wp-content/uploads/2016/10/matconvnet-installation-in-windows-system-02.png" alt="matconvnet-installation-in-windows-system-02"></p>
<p>4.测试</p>
<p style="text-align: justify;">还是根据官网的<span style="color: #3366ff;"><a href="http://www.vlfeat.org/matconvnet/install/" target="_blank" rel="external">这个页面</a></span>，在命令行窗口输入<code>vl_testnn</code>命令，测试非GPU模式，会出现下面的内容。</p>

<p><img src="http://blog.frankge.me/wp-content/uploads/2016/10/matconvnet-installation-in-windows-system-03.png" alt="matconvnet-installation-in-windows-system-03"></p>
<p style="text-align: justify;">接下来测试GPU模式，在命令行窗口输入<code>vl_testnn(&#39;gpu&#39;, true)</code>，会有类似上面的内容出现。这就是成功了，GPU模式下的速度提示还是很明显的，一般都会有十倍以上。</p>

<p><img src="http://blog.frankge.me/wp-content/uploads/2016/10/matconvnet-installation-in-windows-system-05.png" alt="matconvnet-installation-in-windows-system-05"></p>
<p>到此，MatConvNet的安装就结束了。</p>
<p style="text-align: justify;">同时，把我在安装过程中遇到的一个问题的解决方式给写一下。在安装cuDNN的时候，可能会遇到如下的错<code>Error using mex nvcc fatal : Unsupported gpu architecture &#39;compute_21&#39;</code>，其中21可以为其他不能被10整除的数字。这个时候可以把<code>matconvnet-1.0-beta22\matlab</code>下的<code>vl_compilenn.m</code>文件中的732行的代码中”%s”改为向下取10的整数倍。</p>

<p>比如，原代码为</p>
<figure class="highlight matlab"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">cudaArch = ...</div><div class="line">    sprintf(<span class="string">'-gencode=arch=compute_%s,code=\\\&amp;amp;quot;sm_%s,compute_%s\\\&amp;amp;quot; '</span>, ...</div><div class="line">            arch_code, arch_code, arch_code) ;</div></pre></td></tr></table></figure>
<p>可以改为</p>
<figure class="highlight matlab"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div></pre></td><td class="code"><pre><div class="line">cudaArch = ...</div><div class="line">    sprintf(<span class="string">'-gencode=arch=compute_20,code=\\\&amp;amp;quot;sm_20,compute_20\\\&amp;amp;quot; '</span>, ... </div><div class="line">            arch_code, arch_code, arch_code) ;</div></pre></td></tr></table></figure>
<p>这样，经常遇到的问题就能解决了。</p>
<p>&nbsp;</p>
]]></content>
    
    <summary type="html">
    
      &lt;p&gt;&lt;br&gt;&lt;/p&gt;
&lt;h3 id=&quot;16-11-29更新&quot;&gt;&lt;a href=&quot;#16-11-29更新&quot; class=&quot;headerlink&quot; title=&quot;16.11.29更新&quot;&gt;&lt;/a&gt;16.11.29更新&lt;/h3&gt;&lt;p style=&quot;text-align: justify
    
    </summary>
    
      <category term="编程学习" scheme="http://skills.frankge.me/categories/%E7%BC%96%E7%A8%8B%E5%AD%A6%E4%B9%A0/"/>
    
    
      <category term="深度学习" scheme="http://skills.frankge.me/tags/%E6%B7%B1%E5%BA%A6%E5%AD%A6%E4%B9%A0/"/>
    
  </entry>
  
  <entry>
    <title>浅谈动态规划（一）——从lintcode刷题入门</title>
    <link href="http://skills.frankge.me/getting-start-to-dynamic-programming-part-1-some-exercises-from-lintcode/"/>
    <id>http://skills.frankge.me/getting-start-to-dynamic-programming-part-1-some-exercises-from-lintcode/</id>
    <published>2016-10-24T13:10:34.000Z</published>
    <updated>2016-11-30T16:54:50.601Z</updated>
    
    <content type="html"><![CDATA[<p style="text-align: justify;">动态规划是算法中比较常见的一种分析问题的方式，最近看算法看到这，带着lintcode上面的题目，在这写个总结。</p>

<p style="text-align: justify;">首先从一个lintcode上面简单的题目开始。</p>

<p><span style="color: #3366ff;"><a href="http://www.lintcode.com/zh-cn/problem/climbing-stairs/" target="_blank" rel="external">Climbing Stairs（爬楼梯）</a></span></p>
<p>题目描述：</p>
<p style="text-align: justify;">假设你正在爬楼梯，需要<code>n</code>步你才能到达顶部。但每次你只能爬一步或者两步，你能有多少种不同的方法爬到楼顶部？</p>

<p style="text-align: justify;">样例：<br><br>比如<code>n=3</code>，<code>1+1+1=1+2=2+1=3</code>，共有<code>3</code>中不同的方法，所以返回<code>3</code>。</p>

<p>这是一道非常具有代表性的动态规划的一道问题。</p>
<p style="text-align: justify;">令<code>f[n]</code>记录到达第<code>n</code>阶台阶的方法数。假设你还有最后一步就能到达第n阶台阶，那么最后一步，你可以选择两种方式：1）踏一步以及，2）踏两步。如果是踏一步，那么你要从第n-1阶台阶踏出，此时的方法数是 <code>f[n-1]</code>；如果是踏两步，那么你要从第n-2阶台阶出发，此时的方法数是f[n-2]。所以爬到第n级台阶的方法总数有<code>f[n] = f[n-1] + f[n-2]</code>种。状态转移方程：</p>

<p><code>f[n] = f[n-1] + f[n-2]</code></p>
<p>这样可以写出解答的递归形式：</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">climbStairs</span><span class="params">(<span class="keyword">int</span> n)</span> </span>&#123;</div><div class="line">	<span class="comment">// write your code here</span></div><div class="line">	<span class="keyword">if</span> (n &lt;= <span class="number">1</span>)</div><div class="line">		<span class="keyword">return</span> <span class="number">1</span>;</div><div class="line">	<span class="keyword">else</span> </div><div class="line">		<span class="keyword">return</span> climbStairs(n<span class="number">-1</span>) + climbStairs(n<span class="number">-2</span>);</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p style="text-align: justify;">此时我们发现可以用一个一维数组来记录之前出现的结果，这样可以省去递归中不必要的空间开销：</p>

<figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">climbStairs</span><span class="params">(<span class="keyword">int</span> n)</span> </span>&#123;</div><div class="line">	<span class="comment">// write your code here</span></div><div class="line">	<span class="built_in">vector</span>&lt;<span class="keyword">int</span>&gt; f(n+<span class="number">1</span>);</div><div class="line"></div><div class="line">	f[<span class="number">0</span>] = <span class="number">1</span>;</div><div class="line">	f[<span class="number">1</span>] = <span class="number">1</span>;</div><div class="line"></div><div class="line">	<span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">2</span>; i &lt;= n; i++)</div><div class="line">		f[i] = f[i<span class="number">-1</span>] + f[i<span class="number">-2</span>];</div><div class="line"></div><div class="line">	<span class="keyword">return</span> f[n];</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p style="text-align: justify;">其实，这个还可以进一步优化，因为每一步都只需要前两个台阶的结果，所以可以用两个变量来代替一维数组。</p>

<figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">climbStairs</span><span class="params">(<span class="keyword">int</span> n)</span> </span>&#123;</div><div class="line">	<span class="comment">// write your code here</span></div><div class="line">	<span class="keyword">if</span> (n == <span class="number">1</span> || n == <span class="number">0</span>)</div><div class="line">		<span class="keyword">return</span> <span class="number">1</span>;</div><div class="line">	</div><div class="line">	<span class="keyword">int</span> ways1 = <span class="number">1</span>;</div><div class="line">	<span class="keyword">int</span> ways2 = <span class="number">1</span>;</div><div class="line">	<span class="keyword">int</span> ways = <span class="number">0</span>;</div><div class="line">	</div><div class="line">	<span class="keyword">int</span> i = <span class="number">2</span>;</div><div class="line">	<span class="keyword">while</span> (i &lt;= n)</div><div class="line">	&#123;</div><div class="line">		ways = ways1 + ways2;</div><div class="line">		</div><div class="line">		ways1 = ways2;</div><div class="line">		ways2 = ways;</div><div class="line">		</div><div class="line">		i++;</div><div class="line">	&#125;</div><div class="line">	</div><div class="line">	<span class="keyword">return</span> ways;</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p>接下来，我们再来看一题。</p>
<p><span style="color: #3366ff;"><a href="http://www.lintcode.com/zh-cn/problem/triangle/" target="_blank" rel="external">Triangle（数字三角形）</a></span></p>
<p>题目描述：</p>
<p style="text-align: justify;">给定一个数字三角形，找到从顶部到底部的最小路径和。每一步可以移动到下面一行的相邻数字上。</p>

<p>样例<br>比如，给出下列数字三角形：</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div></pre></td><td class="code"><pre><div class="line">[</div><div class="line">     [<span class="number">2</span>],</div><div class="line">    [<span class="number">3</span>,<span class="number">4</span>],</div><div class="line">   [<span class="number">6</span>,<span class="number">5</span>,<span class="number">7</span>],</div><div class="line">  [<span class="number">4</span>,<span class="number">1</span>,<span class="number">8</span>,<span class="number">3</span>]</div><div class="line">]</div></pre></td></tr></table></figure>
<p>从顶到底部的最小路径和为<code>11</code> <code>( 2 + 3 + 5 + 1 = 11)</code>。</p>
<p style="text-align: justify;">分析问题，我们发现可以用二维数组来计算到最底层每个位置的最小路径和，令第i层下标为j的位置上最小路径和为<code>f[i][j]</code>。那么，第i层下标为<code>j</code>位置的值<code>f[i][j]</code>，只和<code>i-1</code>层位置<code>j-1</code>下标的最小路径和<code>f[i-1][j-1]</code>以及j位置的最小路径和<code>f[i-1][j]</code>有关。即，<code>f[i][j] = min(f[i-1][j-1],  f[i-1][j])</code>。所以状态转移方程为：</p>

<p><code>f[i][j] = min(f[i-1][j-1],  f[i-1][j])</code></p>
<p style="text-align: justify;">同时，发现每次的结果只与上面一层的结果有关，所以省去二维数组，只用一维数组作为辅助。代码为：</p>

<figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div></pre></td><td class="code"><pre><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">minimumTotal</span><span class="params">(<span class="built_in">vector</span>&lt;<span class="built_in">vector</span>&lt;<span class="keyword">int</span>&gt; &gt; &amp;triangle)</span> </span>&#123;</div><div class="line">	<span class="comment">// write your code here</span></div><div class="line">	<span class="keyword">if</span> (triangle.size() == <span class="number">0</span>)</div><div class="line">		<span class="keyword">return</span> <span class="number">0</span>;</div><div class="line">		</div><div class="line">	<span class="built_in">vector</span>&lt;<span class="keyword">int</span>&gt; f(triangle[triangle.size() - <span class="number">1</span>].size());</div><div class="line">	</div><div class="line">	<span class="comment">// 动态规划过程</span></div><div class="line">	f[<span class="number">0</span>] = triangle[<span class="number">0</span>][<span class="number">0</span>];</div><div class="line">	<span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>; i &lt; triangle.size(); i++) </div><div class="line">        &#123; </div><div class="line">                <span class="keyword">for</span> (<span class="keyword">int</span> j = triangle.size()<span class="number">-1</span>; j &gt;= <span class="number">0</span>; j--)</div><div class="line">		&#123;</div><div class="line">			<span class="keyword">if</span> (j == <span class="number">0</span>)</div><div class="line">				f[j] = f[j] + triangle[i][j];</div><div class="line">			<span class="keyword">else</span> <span class="keyword">if</span> (j == triangle[i].size()<span class="number">-1</span>)</div><div class="line">				f[j] = f[j<span class="number">-1</span>] + triangle[i][j];</div><div class="line">			<span class="keyword">else</span></div><div class="line">				f[j] = min(f[j<span class="number">-1</span>], f[j]) + triangle[i][j];</div><div class="line">		&#125;</div><div class="line">	&#125;</div><div class="line">	</div><div class="line">	<span class="comment">// 从辅助数组中找出最小值</span></div><div class="line">	<span class="keyword">int</span> result;</div><div class="line">	result = f[<span class="number">0</span>];</div><div class="line">	<span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">1</span>; i &lt; f.size(); i++)</div><div class="line">		result = min(result, f[i]);</div><div class="line">		</div><div class="line">	<span class="keyword">return</span> result;</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p style="text-align: justify;">分析这两道题目，发现它们有两个共同的特征：<br><br>1.最优子结构：一个问题的最优解包含其子问题的最优解。<br><br>2.子问题重叠：一个问题的子问题都是相同的。那么这些子问题可以用同样的方式解决，每次将解决的子问题给记录到表中，在计算之后的问题时查找前面的结果来计算当前问题。这也就是“动态规划”名称的由来了。</p>

<p style="text-align: justify;">在climbing stairs问题中，到达每个位置的方法个数，和之前的所有方法是相关联的。即，到达第n阶台阶的所有的方法个数，同时需要找出第n-1阶台阶的所有的方法以及第n-2阶台阶的所有的方法，以此类推。如果之前的问题找出的不是所有的方法数，那么第n阶台阶找出的结果也不是所有的方法数目。而且，第n阶台阶的求解方式和之前的台阶的求解方式是相同的。</p>

<p style="text-align: justify;">在triangle问题中，每个位置的最小路径和需要知道前一层此位置和下一个位置的最小路径和，如果前一层的结果不是最小路径和，那么此层求出的就不是最小路径和。同样，每层问题的求解方式和之前层问题的求解方式是相同的。</p>

<p>所以，这也就是《算法导论》一书中表述的动态规划的两个特征：<br><br>1.最优子结构<br><br>2.子问题重叠</p>
<p>参考资料：</p>
<p>1.lintcode<br><span style="color: #3366ff;"><a href="http://www.lintcode.com/en/problem/triangle/" target="_blank" rel="external">Triangle</a></span><br><span style="color: #3366ff;"><a href="http://www.lintcode.com/en/problem/climbing-stairs/" target="_blank" rel="external">Climbing Stairs</a></span></p>
<p>2.《算法导论（第三版）》。<br>第15章动态规划</p>
]]></content>
    
    <summary type="html">
    
      &lt;p style=&quot;text-align: justify;&quot;&gt;动态规划是算法中比较常见的一种分析问题的方式，最近看算法看到这，带着lintcode上面的题目，在这写个总结。&lt;/p&gt;

&lt;p style=&quot;text-align: justify;&quot;&gt;首先从一个lintcode上面
    
    </summary>
    
      <category term="编程学习" scheme="http://skills.frankge.me/categories/%E7%BC%96%E7%A8%8B%E5%AD%A6%E4%B9%A0/"/>
    
    
      <category term="算法" scheme="http://skills.frankge.me/tags/%E7%AE%97%E6%B3%95/"/>
    
  </entry>
  
  <entry>
    <title>二叉树类的实现</title>
    <link href="http://skills.frankge.me/the-implement-of-binary-tree-class/"/>
    <id>http://skills.frankge.me/the-implement-of-binary-tree-class/</id>
    <published>2016-09-10T17:05:45.000Z</published>
    <updated>2016-12-01T16:30:19.680Z</updated>
    
    <content type="html"><![CDATA[<p style="text-align: justify;">最近看数据结构看到二叉树的时候，自己实现了一下，同时写成了类，正好复习一下以前看C++的一些知识。代码如下。</p>

<figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// BiTNode.h</span></div><div class="line"><span class="comment">// 参照《c++大学教程》中P639页编写</span></div><div class="line"><span class="comment">// 模版结点BiTNode类的声明</span></div><div class="line"></div><div class="line"><span class="meta">#<span class="meta-keyword">ifndef</span> BITNODE_H</span></div><div class="line"><span class="meta">#<span class="meta-keyword">define</span> BITNODE_H</span></div><div class="line"></div><div class="line"><span class="comment">// 声明BiNTree类型</span></div><div class="line"><span class="keyword">template</span>&lt;<span class="keyword">typename</span> NODETYPE&gt; <span class="keyword">class</span> BiTree;</div><div class="line"></div><div class="line"><span class="keyword">template</span>&lt;<span class="keyword">typename</span> NODETYPE&gt;</div><div class="line"><span class="keyword">class</span> BiTNode</div><div class="line">&#123;</div><div class="line">	<span class="comment">// 声明友元BiNTree类，使得BiTree类可以访问BiTNode类中的private成员</span></div><div class="line">	<span class="keyword">friend</span> <span class="keyword">class</span> BiTree&lt;NODETYPE&gt;;</div><div class="line"></div><div class="line"><span class="keyword">public</span>:</div><div class="line">	BiTNode(<span class="keyword">const</span> NODETYPE &amp;d) </div><div class="line">		: lchild(<span class="number">0</span>), </div><div class="line">			data(d),</div><div class="line">			rchild(<span class="number">0</span>)</div><div class="line">	&#123;</div><div class="line">	&#125;</div><div class="line"></div><div class="line">	<span class="function">NODETYPE <span class="title">getData</span><span class="params">()</span> <span class="keyword">const</span></span></div><div class="line">	&#123;</div><div class="line">		<span class="keyword">return</span> data;</div><div class="line">	&#125;</div><div class="line"></div><div class="line"><span class="keyword">private</span>:</div><div class="line">	BiTNode&lt;NODETYPE&gt; *lchild;</div><div class="line">	NODETYPE data;</div><div class="line">	BiTNode&lt;NODETYPE&gt; *rchild;</div><div class="line">&#125;;</div><div class="line"></div><div class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></div></pre></td></tr></table></figure>
<p><br><br><figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div><div class="line">66</div><div class="line">67</div><div class="line">68</div><div class="line">69</div><div class="line">70</div><div class="line">71</div><div class="line">72</div><div class="line">73</div><div class="line">74</div><div class="line">75</div><div class="line">76</div><div class="line">77</div><div class="line">78</div><div class="line">79</div><div class="line">80</div><div class="line">81</div><div class="line">82</div><div class="line">83</div><div class="line">84</div><div class="line">85</div><div class="line">86</div><div class="line">87</div><div class="line">88</div><div class="line">89</div><div class="line">90</div><div class="line">91</div><div class="line">92</div><div class="line">93</div><div class="line">94</div><div class="line">95</div><div class="line">96</div><div class="line">97</div><div class="line">98</div><div class="line">99</div><div class="line">100</div><div class="line">101</div><div class="line">102</div><div class="line">103</div><div class="line">104</div><div class="line">105</div><div class="line">106</div><div class="line">107</div><div class="line">108</div><div class="line">109</div><div class="line">110</div><div class="line">111</div><div class="line">112</div><div class="line">113</div><div class="line">114</div><div class="line">115</div><div class="line">116</div><div class="line">117</div><div class="line">118</div><div class="line">119</div><div class="line">120</div><div class="line">121</div><div class="line">122</div><div class="line">123</div><div class="line">124</div><div class="line">125</div><div class="line">126</div><div class="line">127</div><div class="line">128</div><div class="line">129</div><div class="line">130</div><div class="line">131</div><div class="line">132</div><div class="line">133</div><div class="line">134</div><div class="line">135</div><div class="line">136</div><div class="line">137</div><div class="line">138</div><div class="line">139</div><div class="line">140</div><div class="line">141</div><div class="line">142</div><div class="line">143</div><div class="line">144</div><div class="line">145</div><div class="line">146</div><div class="line">147</div><div class="line">148</div><div class="line">149</div><div class="line">150</div><div class="line">151</div><div class="line">152</div><div class="line">153</div><div class="line">154</div><div class="line">155</div><div class="line">156</div><div class="line">157</div><div class="line">158</div><div class="line">159</div><div class="line">160</div><div class="line">161</div><div class="line">162</div><div class="line">163</div><div class="line">164</div><div class="line">165</div><div class="line">166</div><div class="line">167</div><div class="line">168</div><div class="line">169</div><div class="line">170</div><div class="line">171</div><div class="line">172</div><div class="line">173</div><div class="line">174</div><div class="line">175</div><div class="line">176</div><div class="line">177</div><div class="line">178</div><div class="line">179</div><div class="line">180</div><div class="line">181</div><div class="line">182</div><div class="line">183</div><div class="line">184</div><div class="line">185</div><div class="line">186</div><div class="line">187</div><div class="line">188</div><div class="line">189</div><div class="line">190</div><div class="line">191</div><div class="line">192</div><div class="line">193</div><div class="line">194</div><div class="line">195</div><div class="line">196</div><div class="line">197</div><div class="line">198</div><div class="line">199</div><div class="line">200</div><div class="line">201</div><div class="line">202</div><div class="line">203</div><div class="line">204</div><div class="line">205</div><div class="line">206</div><div class="line">207</div><div class="line">208</div><div class="line">209</div><div class="line">210</div><div class="line">211</div><div class="line">212</div><div class="line">213</div><div class="line">214</div><div class="line">215</div><div class="line">216</div><div class="line">217</div><div class="line">218</div><div class="line">219</div><div class="line">220</div><div class="line">221</div><div class="line">222</div><div class="line">223</div><div class="line">224</div><div class="line">225</div><div class="line">226</div><div class="line">227</div><div class="line">228</div><div class="line">229</div><div class="line">230</div><div class="line">231</div><div class="line">232</div><div class="line">233</div><div class="line">234</div><div class="line">235</div><div class="line">236</div><div class="line">237</div><div class="line">238</div><div class="line">239</div><div class="line">240</div><div class="line">241</div><div class="line">242</div><div class="line">243</div><div class="line">244</div><div class="line">245</div><div class="line">246</div><div class="line">247</div><div class="line">248</div><div class="line">249</div><div class="line">250</div><div class="line">251</div><div class="line">252</div><div class="line">253</div><div class="line">254</div><div class="line">255</div><div class="line">256</div><div class="line">257</div><div class="line">258</div><div class="line">259</div><div class="line">260</div><div class="line">261</div><div class="line">262</div><div class="line">263</div><div class="line">264</div><div class="line">265</div><div class="line">266</div><div class="line">267</div><div class="line">268</div><div class="line">269</div><div class="line">270</div><div class="line">271</div><div class="line">272</div><div class="line">273</div><div class="line">274</div><div class="line">275</div><div class="line">276</div><div class="line">277</div><div class="line">278</div><div class="line">279</div><div class="line">280</div><div class="line">281</div><div class="line">282</div><div class="line">283</div><div class="line">284</div><div class="line">285</div><div class="line">286</div><div class="line">287</div><div class="line">288</div><div class="line">289</div><div class="line">290</div><div class="line">291</div><div class="line">292</div><div class="line">293</div><div class="line">294</div><div class="line">295</div><div class="line">296</div><div class="line">297</div><div class="line">298</div><div class="line">299</div><div class="line">300</div><div class="line">301</div><div class="line">302</div><div class="line">303</div><div class="line">304</div><div class="line">305</div><div class="line">306</div><div class="line">307</div><div class="line">308</div><div class="line">309</div><div class="line">310</div><div class="line">311</div><div class="line">312</div><div class="line">313</div><div class="line">314</div><div class="line">315</div><div class="line">316</div><div class="line">317</div><div class="line">318</div><div class="line">319</div><div class="line">320</div><div class="line">321</div><div class="line">322</div><div class="line">323</div><div class="line">324</div><div class="line">325</div><div class="line">326</div><div class="line">327</div><div class="line">328</div><div class="line">329</div><div class="line">330</div><div class="line">331</div><div class="line">332</div><div class="line">333</div><div class="line">334</div><div class="line">335</div><div class="line">336</div><div class="line">337</div><div class="line">338</div><div class="line">339</div><div class="line">340</div><div class="line">341</div><div class="line">342</div><div class="line">343</div><div class="line">344</div><div class="line">345</div><div class="line">346</div><div class="line">347</div><div class="line">348</div><div class="line">349</div><div class="line">350</div><div class="line">351</div><div class="line">352</div><div class="line">353</div><div class="line">354</div><div class="line">355</div><div class="line">356</div><div class="line">357</div><div class="line">358</div><div class="line">359</div><div class="line">360</div><div class="line">361</div><div class="line">362</div><div class="line">363</div><div class="line">364</div><div class="line">365</div><div class="line">366</div><div class="line">367</div><div class="line">368</div><div class="line">369</div><div class="line">370</div><div class="line">371</div><div class="line">372</div><div class="line">373</div><div class="line">374</div><div class="line">375</div><div class="line">376</div><div class="line">377</div><div class="line">378</div><div class="line">379</div><div class="line">380</div><div class="line">381</div><div class="line">382</div><div class="line">383</div><div class="line">384</div><div class="line">385</div><div class="line">386</div><div class="line">387</div><div class="line">388</div><div class="line">389</div><div class="line">390</div><div class="line">391</div><div class="line">392</div><div class="line">393</div><div class="line">394</div><div class="line">395</div><div class="line">396</div><div class="line">397</div><div class="line">398</div><div class="line">399</div><div class="line">400</div><div class="line">401</div><div class="line">402</div><div class="line">403</div><div class="line">404</div><div class="line">405</div><div class="line">406</div><div class="line">407</div><div class="line">408</div><div class="line">409</div><div class="line">410</div><div class="line">411</div><div class="line">412</div><div class="line">413</div><div class="line">414</div><div class="line">415</div><div class="line">416</div><div class="line">417</div><div class="line">418</div><div class="line">419</div><div class="line">420</div><div class="line">421</div><div class="line">422</div><div class="line">423</div><div class="line">424</div><div class="line">425</div><div class="line">426</div><div class="line">427</div><div class="line">428</div><div class="line">429</div><div class="line">430</div><div class="line">431</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// BiTree.h</span></div><div class="line"><span class="comment">// 链表二叉树类模版的定义</span></div><div class="line"></div><div class="line"><span class="meta">#<span class="meta-keyword">ifndef</span> BITREE_H</span></div><div class="line"><span class="meta">#<span class="meta-keyword">define</span> BITREE_H</span></div><div class="line"></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iomanip&gt;</span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">"BiTNode.h"</span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;queue&gt;</span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stack&gt;</span></span></div><div class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> <span class="built_in">std</span>;</div><div class="line"></div><div class="line"><span class="keyword">typedef</span> <span class="keyword">int</span> Status;</div><div class="line"></div><div class="line"><span class="meta">#<span class="meta-keyword">define</span> OK	1</span></div><div class="line"><span class="meta">#<span class="meta-keyword">define</span> ERROR	0</span></div><div class="line"><span class="meta">#<span class="meta-keyword">define</span> TRUE	1</span></div><div class="line"><span class="meta">#<span class="meta-keyword">define</span> FALSE	0</span></div><div class="line"></div><div class="line"><span class="keyword">template</span>&lt;<span class="keyword">typename</span> NODETYPE&gt;</div><div class="line"><span class="keyword">class</span> BiTree</div><div class="line">&#123;</div><div class="line"><span class="keyword">public</span>:</div><div class="line">	BiTree();</div><div class="line"></div><div class="line">	<span class="function"><span class="keyword">void</span> <span class="title">CreateBiTree</span><span class="params">()</span></span>;</div><div class="line">	<span class="function"><span class="keyword">void</span> <span class="title">DestroyBiTree</span><span class="params">()</span></span>;</div><div class="line">	<span class="function">Status <span class="title">BiTreeEmpty</span><span class="params">()</span></span>;</div><div class="line">	<span class="function">NODETYPE <span class="title">Root</span><span class="params">()</span></span>;</div><div class="line"></div><div class="line">	<span class="function"><span class="keyword">int</span> <span class="title">BiTreeDepth</span><span class="params">()</span></span>;</div><div class="line">	<span class="function"><span class="keyword">int</span> <span class="title">BiTreeDepthNonRecursion</span><span class="params">()</span></span>;</div><div class="line"></div><div class="line">	<span class="function"><span class="keyword">void</span> <span class="title">PreOrderTraverse</span><span class="params">()</span></span>;</div><div class="line">	<span class="function"><span class="keyword">void</span> <span class="title">PreOrderNonRecursion</span><span class="params">()</span></span>;</div><div class="line">	<span class="function"><span class="keyword">void</span> <span class="title">InOrderTraverse</span><span class="params">()</span></span>;</div><div class="line">	<span class="function"><span class="keyword">void</span> <span class="title">InOrderNonRecursion</span><span class="params">()</span></span>;</div><div class="line">	<span class="function"><span class="keyword">void</span> <span class="title">PostOrderTraverse</span><span class="params">()</span></span>;</div><div class="line">	<span class="function"><span class="keyword">void</span> <span class="title">PostOrderNonRecursion</span><span class="params">()</span></span>;</div><div class="line">	<span class="function"><span class="keyword">void</span> <span class="title">LevelOrderTraverse</span><span class="params">()</span></span>;</div><div class="line"></div><div class="line">	<span class="function"><span class="keyword">void</span> <span class="title">PrintLast</span><span class="params">()</span></span>;</div><div class="line">	<span class="function"><span class="keyword">void</span> <span class="title">PrintByDepth</span><span class="params">()</span></span>;</div><div class="line"></div><div class="line"><span class="keyword">private</span>:</div><div class="line">	BiTNode&lt;NODETYPE&gt; *rootPtr;</div><div class="line"></div><div class="line">	<span class="comment">// utility function</span></div><div class="line">	<span class="function"><span class="keyword">void</span> <span class="title">visit</span><span class="params">(BiTNode&lt;NODETYPE&gt; *p)</span></span>;</div><div class="line">	<span class="function"><span class="keyword">void</span> <span class="title">CreateBiTreeHelper</span><span class="params">(BiTNode&lt;NODETYPE&gt; **T)</span></span>;</div><div class="line">	<span class="function"><span class="keyword">void</span> <span class="title">DestroyBiTreeHelper</span><span class="params">(BiTNode&lt;NODETYPE&gt; **T)</span></span>;</div><div class="line">	<span class="function"><span class="keyword">int</span> <span class="title">BiTreeDepthHelper</span><span class="params">(BiTNode&lt;NODETYPE&gt; *T)</span></span>;</div><div class="line"></div><div class="line">	<span class="comment">// 用helper函数的原因是对二叉树进行遍历要传入参数</span></div><div class="line">	<span class="function"><span class="keyword">void</span> <span class="title">PreOrderTraverseHelper</span><span class="params">(BiTNode&lt;NODETYPE&gt; *T)</span></span>;</div><div class="line">	<span class="function"><span class="keyword">void</span> <span class="title">InOrderTraverseHelper</span><span class="params">(BiTNode&lt;NODETYPE&gt; *T)</span></span>;</div><div class="line">	<span class="function"><span class="keyword">void</span> <span class="title">PostOrderTraverseHelper</span><span class="params">(BiTNode&lt;NODETYPE&gt; *T)</span></span>;</div><div class="line">&#125;;</div><div class="line"></div><div class="line"><span class="keyword">template</span>&lt;<span class="keyword">typename</span> NODETYPE&gt;</div><div class="line">BiTree&lt;NODETYPE&gt;::BiTree()</div><div class="line">&#123;</div><div class="line">	rootPtr = <span class="number">0</span>;</div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="keyword">template</span>&lt;<span class="keyword">typename</span> NODETYPE&gt;</div><div class="line">Status BiTree&lt;NODETYPE&gt;::BiTreeEmpty()</div><div class="line">&#123;</div><div class="line">	<span class="keyword">if</span> (rootPtr)</div><div class="line">		<span class="keyword">return</span> FALSE;</div><div class="line">	<span class="keyword">else</span></div><div class="line">		<span class="keyword">return</span> TRUE;</div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="keyword">template</span>&lt;<span class="keyword">typename</span> NODETYPE&gt;</div><div class="line"><span class="keyword">void</span> BiTree&lt;NODETYPE&gt;::CreateBiTree()</div><div class="line">&#123;</div><div class="line">	CreateBiTreeHelper(&amp;rootPtr);</div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="comment">// 按前序输入二叉树中结点的值（一个字符）</span></div><div class="line"><span class="comment">// #表示空树，构造二叉链表表示二叉树T。</span></div><div class="line"><span class="keyword">template</span>&lt;<span class="keyword">typename</span> NODETYPE&gt;</div><div class="line"><span class="keyword">void</span> BiTree&lt;NODETYPE&gt;::CreateBiTreeHelper(BiTNode&lt;NODETYPE&gt; **T)</div><div class="line">&#123;</div><div class="line">	NODETYPE val;</div><div class="line"></div><div class="line">	<span class="built_in">cin</span> &gt;&gt; val;</div><div class="line"></div><div class="line">	<span class="keyword">if</span> (val == <span class="string">'#'</span>)</div><div class="line">		*T = <span class="literal">NULL</span>;</div><div class="line">	<span class="keyword">else</span></div><div class="line">	&#123;</div><div class="line">		*T = <span class="keyword">new</span> BiTNode&lt;NODETYPE&gt;(val);</div><div class="line">		CreateBiTreeHelper(&amp;(*T)-&gt;lchild);</div><div class="line">		CreateBiTreeHelper(&amp;(*T)-&gt;rchild);</div><div class="line">	&#125;</div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="keyword">template</span>&lt;<span class="keyword">typename</span> NODETYPE&gt;</div><div class="line"><span class="keyword">void</span> BiTree&lt;NODETYPE&gt;::DestroyBiTree()</div><div class="line">&#123;</div><div class="line">	DestroyBiTreeHelper(&amp;rootPtr);</div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="keyword">template</span>&lt;<span class="keyword">typename</span> NODETYPE&gt;</div><div class="line"><span class="keyword">void</span> BiTree&lt;NODETYPE&gt;::DestroyBiTreeHelper(BiTNode&lt;NODETYPE&gt; **T)</div><div class="line">&#123;</div><div class="line">	<span class="keyword">if</span> (*T)</div><div class="line">	&#123;</div><div class="line">		<span class="keyword">if</span> ((*T)-&gt;lchild)</div><div class="line">			DestroyBiTreeHelper(&amp;(*T)-&gt;lchild);</div><div class="line">		<span class="keyword">if</span> ((*T)-&gt;rchild)</div><div class="line">			DestroyBiTreeHelper(&amp;(*T)-&gt;rchild);</div><div class="line">		<span class="built_in">free</span>(*T);</div><div class="line">		*T = <span class="literal">NULL</span>;</div><div class="line">	&#125;</div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="keyword">template</span>&lt;<span class="keyword">typename</span> NODETYPE&gt;</div><div class="line"><span class="keyword">int</span> BiTree&lt;NODETYPE&gt;::BiTreeDepth()</div><div class="line">&#123;</div><div class="line">	<span class="keyword">return</span> BiTreeDepthHelper(rootPtr);</div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="keyword">template</span>&lt;<span class="keyword">typename</span> NODETYPE&gt;</div><div class="line"><span class="keyword">int</span> BiTree&lt;NODETYPE&gt;::BiTreeDepthHelper(BiTNode&lt;NODETYPE&gt; *T)</div><div class="line">&#123;</div><div class="line">	<span class="keyword">int</span> i, j;</div><div class="line"></div><div class="line">	<span class="keyword">if</span> (!T)</div><div class="line">		<span class="keyword">return</span> <span class="number">0</span>;</div><div class="line"></div><div class="line">	<span class="keyword">if</span> (T-&gt;lchild)</div><div class="line">		i = BiTreeDepthHelper(T-&gt;lchild);</div><div class="line">	<span class="keyword">else</span> </div><div class="line">		i = <span class="number">0</span>;</div><div class="line">	<span class="keyword">if</span> (T-&gt;rchild)</div><div class="line">		j = BiTreeDepthHelper(T-&gt;rchild);</div><div class="line">	<span class="keyword">else</span></div><div class="line">		j = <span class="number">0</span>;</div><div class="line"></div><div class="line">	<span class="keyword">return</span> i &gt; j ? i+<span class="number">1</span> : j+<span class="number">1</span>;</div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="keyword">template</span>&lt;<span class="keyword">typename</span> NODETYPE&gt;</div><div class="line">NODETYPE BiTree&lt;NODETYPE&gt;::Root()</div><div class="line">&#123;</div><div class="line">	<span class="keyword">if</span> (!rootPtr)</div><div class="line">		<span class="keyword">return</span> <span class="string">' '</span>;</div><div class="line">	<span class="keyword">else</span></div><div class="line">		<span class="keyword">return</span> rootPtr-&gt;data;</div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="comment">// 借用层次遍历的思想，实现非递归形式求出二叉树深度</span></div><div class="line"><span class="keyword">template</span>&lt;<span class="keyword">typename</span> NODETYPE&gt;</div><div class="line"><span class="keyword">int</span> BiTree&lt;NODETYPE&gt;::BiTreeDepthNonRecursion()</div><div class="line">&#123;</div><div class="line">	<span class="keyword">if</span> (!rootPtr)</div><div class="line">		<span class="keyword">return</span> <span class="number">0</span>;</div><div class="line"></div><div class="line">	BiTNode&lt;NODETYPE&gt; *p; <span class="comment">// 工作指针，每次记录从队列队首弹出的结点</span></div><div class="line">	BiTNode&lt;NODETYPE&gt; *back; <span class="comment">// 记录每层二叉树的最右边的结点。此结点在每次遍历一层之后的队列队尾</span></div><div class="line">	<span class="keyword">int</span> level = <span class="number">0</span>; <span class="comment">// 层数，初始值为0</span></div><div class="line">	<span class="built_in">queue</span>&lt;BiTNode&lt;NODETYPE&gt; *&gt; Q;</div><div class="line"></div><div class="line">	Q.push(rootPtr);</div><div class="line">	back = Q.back();</div><div class="line">	<span class="keyword">while</span> (!Q.empty())</div><div class="line">	&#123;</div><div class="line">		p = Q.front();</div><div class="line">		Q.pop();</div><div class="line"></div><div class="line">		<span class="keyword">if</span> (p-&gt;lchild)</div><div class="line">			Q.push(p-&gt;lchild);</div><div class="line">		<span class="keyword">if</span> (p-&gt;rchild)</div><div class="line">			Q.push(p-&gt;rchild);</div><div class="line"></div><div class="line">		<span class="keyword">if</span> (p == back) <span class="comment">// 如果p == 每层的最右边的结点，则层数+1，同时重新赋值队尾结点</span></div><div class="line">		&#123;</div><div class="line">			level++;</div><div class="line">			<span class="keyword">if</span> (!Q.empty()) <span class="comment">// 如果队列为空，则下一步的操作出错。主要用于防止最后一个结点弹出队列之后的那次操作</span></div><div class="line">				back = Q.back();</div><div class="line">		&#125;</div><div class="line">	&#125;</div><div class="line"></div><div class="line">	<span class="keyword">return</span> level;</div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="keyword">template</span>&lt;<span class="keyword">typename</span> NODETYPE&gt;</div><div class="line"><span class="keyword">void</span> BiTree&lt;NODETYPE&gt;::PreOrderTraverse()</div><div class="line">&#123;</div><div class="line">	PreOrderTraverseHelper(rootPtr);</div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="keyword">template</span>&lt;<span class="keyword">typename</span> NODETYPE&gt;</div><div class="line"><span class="keyword">void</span> BiTree&lt;NODETYPE&gt;::PreOrderTraverseHelper(BiTNode&lt;NODETYPE&gt; *T)</div><div class="line">&#123;</div><div class="line">	<span class="keyword">if</span> (!T)</div><div class="line">		<span class="keyword">return</span>;</div><div class="line"></div><div class="line">	visit(T);</div><div class="line">	PreOrderTraverseHelper(T-&gt;lchild);</div><div class="line">	PreOrderTraverseHelper(T-&gt;rchild);</div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="comment">// 前序遍历非递归形式</span></div><div class="line"><span class="keyword">template</span>&lt;<span class="keyword">typename</span> NODETYPE&gt;</div><div class="line"><span class="keyword">void</span> BiTree&lt;NODETYPE&gt;::PreOrderNonRecursion()</div><div class="line">&#123;</div><div class="line">	<span class="keyword">if</span> (!rootPtr)</div><div class="line">		<span class="keyword">return</span>;</div><div class="line"></div><div class="line">	BiTNode&lt;NODETYPE&gt; *p;</div><div class="line">	<span class="built_in">stack</span>&lt;BiTNode&lt;NODETYPE&gt; *&gt; S; <span class="comment">// 借助栈实现非递归的前序遍历</span></div><div class="line"></div><div class="line">	p = rootPtr;</div><div class="line">	<span class="keyword">while</span> (p || !S.empty())</div><div class="line">	&#123;</div><div class="line">		<span class="keyword">while</span> (p) </div><div class="line">		&#123;</div><div class="line">			visit(p); <span class="comment">// 在每次入栈之前进行访问</span></div><div class="line">			S.push(p);</div><div class="line">			p = p-&gt;lchild;</div><div class="line">		&#125;</div><div class="line">		<span class="keyword">if</span> (!S.empty())</div><div class="line">		&#123;</div><div class="line">			p = S.top();</div><div class="line">			S.pop();</div><div class="line">			p = p-&gt;rchild;</div><div class="line">		&#125;</div><div class="line">	&#125;</div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="keyword">template</span>&lt;<span class="keyword">typename</span> NODETYPE&gt;</div><div class="line"><span class="keyword">void</span> BiTree&lt;NODETYPE&gt;::InOrderTraverse()</div><div class="line">&#123;</div><div class="line">	InOrderTraverseHelper(rootPtr);</div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="keyword">template</span>&lt;<span class="keyword">typename</span> NODETYPE&gt;</div><div class="line"><span class="keyword">void</span> BiTree&lt;NODETYPE&gt;::InOrderTraverseHelper(BiTNode&lt;NODETYPE&gt; *T)</div><div class="line">&#123;</div><div class="line">	<span class="keyword">if</span> (!T)</div><div class="line">		<span class="keyword">return</span>;</div><div class="line"></div><div class="line">	InOrderTraverseHelper(T-&gt;lchild);</div><div class="line">	visit(T);</div><div class="line">	InOrderTraverseHelper(T-&gt;rchild);</div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="keyword">template</span>&lt;<span class="keyword">typename</span> NODETYPE&gt;</div><div class="line"><span class="keyword">void</span> BiTree&lt;NODETYPE&gt;::InOrderNonRecursion()</div><div class="line">&#123;</div><div class="line">	<span class="keyword">if</span> (!rootPtr)</div><div class="line">		<span class="keyword">return</span>;</div><div class="line"></div><div class="line">	BiTNode&lt;NODETYPE&gt; *p;</div><div class="line">	<span class="built_in">stack</span>&lt;BiTNode&lt;NODETYPE&gt; *&gt; S;</div><div class="line"></div><div class="line">	p = rootPtr;</div><div class="line">	<span class="keyword">while</span> (p || !S.empty())</div><div class="line">	&#123;</div><div class="line">		<span class="keyword">while</span> (p)</div><div class="line">		&#123;</div><div class="line">			S.push(p);</div><div class="line">			p = p-&gt;lchild;</div><div class="line">		&#125;</div><div class="line">		<span class="keyword">if</span> (!S.empty())</div><div class="line">		&#123;</div><div class="line">			p = S.top();</div><div class="line">			S.pop();</div><div class="line">			visit(p); <span class="comment">// 在每次出栈之时进行访问</span></div><div class="line">			p = p-&gt;rchild;</div><div class="line">		&#125;</div><div class="line">	&#125;</div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="keyword">template</span>&lt;<span class="keyword">typename</span> NODETYPE&gt;</div><div class="line"><span class="keyword">void</span> BiTree&lt;NODETYPE&gt;::PostOrderTraverse()</div><div class="line">&#123;</div><div class="line">	PostOrderTraverseHelper(rootPtr);</div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="keyword">template</span>&lt;<span class="keyword">typename</span> NODETYPE&gt;</div><div class="line"><span class="keyword">void</span> BiTree&lt;NODETYPE&gt;::PostOrderTraverseHelper(BiTNode&lt;NODETYPE&gt; *T)</div><div class="line">&#123;</div><div class="line">	<span class="keyword">if</span> (!T)</div><div class="line">		<span class="keyword">return</span>;</div><div class="line"></div><div class="line">	PostOrderTraverseHelper(T-&gt;lchild);</div><div class="line">	PostOrderTraverseHelper(T-&gt;rchild);</div><div class="line">	visit(T);</div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="keyword">template</span>&lt;<span class="keyword">typename</span> NODETYPE&gt;</div><div class="line"><span class="keyword">void</span> BiTree&lt;NODETYPE&gt;::PostOrderNonRecursion()</div><div class="line">&#123;</div><div class="line">	<span class="keyword">if</span> (!rootPtr)</div><div class="line">		<span class="keyword">return</span>;</div><div class="line"></div><div class="line">	BiTNode&lt;NODETYPE&gt; *p;</div><div class="line">	BiTNode&lt;NODETYPE&gt; *r; <span class="comment">// 用于记录栈中弹出的结点的右子树是否访问过</span></div><div class="line">	<span class="built_in">stack</span>&lt;BiTNode&lt;NODETYPE&gt; *&gt; S;</div><div class="line"></div><div class="line">	p = rootPtr;</div><div class="line">	r = <span class="literal">NULL</span>;</div><div class="line">	<span class="keyword">while</span> (p || !S.empty())</div><div class="line">	&#123;</div><div class="line">		<span class="keyword">while</span> (p)</div><div class="line">		&#123;</div><div class="line">			S.push(p);</div><div class="line">			p = p-&gt;lchild;</div><div class="line">		&#125;</div><div class="line">		<span class="keyword">if</span> (!S.empty())</div><div class="line">		&#123;</div><div class="line">			p = S.top();</div><div class="line">			<span class="keyword">if</span> (p-&gt;rchild &amp;&amp; p-&gt;rchild != r) <span class="comment">// 此结点的右子树尚未入栈</span></div><div class="line">			&#123;</div><div class="line">				p = p-&gt;rchild;</div><div class="line">				S.push(p);</div><div class="line">				p = p-&gt;lchild;</div><div class="line">			&#125;</div><div class="line">			<span class="keyword">else</span></div><div class="line">			&#123;</div><div class="line">				S.pop();</div><div class="line">				visit(p); <span class="comment">// 每次出栈时访问结点</span></div><div class="line">				r = p;</div><div class="line">				p = <span class="literal">NULL</span>;</div><div class="line">			&#125;</div><div class="line">		&#125;</div><div class="line">	&#125;</div><div class="line"></div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="keyword">template</span>&lt;<span class="keyword">typename</span> NODETYPE&gt;</div><div class="line"><span class="keyword">void</span> BiTree&lt;NODETYPE&gt;::LevelOrderTraverse()</div><div class="line">&#123;</div><div class="line">	<span class="keyword">if</span> (!rootPtr)</div><div class="line">		<span class="keyword">return</span>;</div><div class="line"></div><div class="line">	BiTNode&lt;NODETYPE&gt; *p;</div><div class="line">	BiTNode&lt;NODETYPE&gt; *back; <span class="comment">// 操作中记录队列尾部的指针</span></div><div class="line">	<span class="built_in">queue</span>&lt;BiTNode&lt;NODETYPE&gt; *&gt; Q; <span class="comment">// 使用辅助队列</span></div><div class="line"></div><div class="line">	Q.push(rootPtr);</div><div class="line">	back = Q.back();</div><div class="line">	<span class="keyword">while</span> (!Q.empty())</div><div class="line">	&#123;</div><div class="line">		p = Q.front();</div><div class="line">		Q.pop();</div><div class="line">		visit(p);</div><div class="line"></div><div class="line">		<span class="keyword">if</span> (p-&gt;lchild)</div><div class="line">			Q.push(p-&gt;lchild);</div><div class="line">		<span class="keyword">if</span> (p-&gt;rchild)</div><div class="line">			Q.push(p-&gt;rchild);</div><div class="line">	&#125;</div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="keyword">template</span>&lt;<span class="keyword">typename</span> NODETYPE&gt;</div><div class="line"><span class="keyword">void</span> BiTree&lt;NODETYPE&gt;::PrintLast()</div><div class="line">&#123;</div><div class="line">	<span class="keyword">if</span> (!rootPtr)</div><div class="line">		<span class="keyword">return</span>;</div><div class="line"></div><div class="line">	BiTNode&lt;NODETYPE&gt; *p;</div><div class="line">	BiTNode&lt;NODETYPE&gt; *back; <span class="comment">// 操作中记录队列尾部的指针</span></div><div class="line">	<span class="built_in">queue</span>&lt;BiTNode&lt;NODETYPE&gt; *&gt; Q; <span class="comment">// 使用辅助队列</span></div><div class="line"></div><div class="line">	Q.push(rootPtr);</div><div class="line">	back = Q.back();</div><div class="line">	<span class="keyword">while</span> (!Q.empty())</div><div class="line">	&#123;</div><div class="line">		p = Q.front();</div><div class="line">		Q.pop();</div><div class="line"></div><div class="line">		<span class="keyword">if</span> (p-&gt;lchild)</div><div class="line">			Q.push(p-&gt;lchild);</div><div class="line">		<span class="keyword">if</span> (p-&gt;rchild)</div><div class="line">			Q.push(p-&gt;rchild);</div><div class="line"></div><div class="line">		<span class="keyword">if</span> (p == back)</div><div class="line">		&#123;</div><div class="line">			visit(p);</div><div class="line">			<span class="keyword">if</span> (!Q.empty())</div><div class="line">				back = Q.back(); <span class="comment">// 更新back指针的位置</span></div><div class="line">		&#125;</div><div class="line">	&#125;</div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="keyword">template</span>&lt;<span class="keyword">typename</span> NODETYPE&gt;</div><div class="line"><span class="keyword">void</span> BiTree&lt;NODETYPE&gt;::PrintByDepth()</div><div class="line">&#123;</div><div class="line">	<span class="keyword">if</span> (!rootPtr)</div><div class="line">		<span class="keyword">return</span>;</div><div class="line"></div><div class="line">	BiTNode&lt;NODETYPE&gt; *p;</div><div class="line">	BiTNode&lt;NODETYPE&gt; *back; <span class="comment">// 操作中记录队列尾部的指针</span></div><div class="line">	<span class="built_in">queue</span>&lt;BiTNode&lt;NODETYPE&gt; *&gt; Q; <span class="comment">// 使用辅助队列</span></div><div class="line"></div><div class="line">	Q.push(rootPtr);</div><div class="line">	back = Q.back();</div><div class="line">	<span class="keyword">while</span> (!Q.empty())</div><div class="line">	&#123;</div><div class="line">		p = Q.front();</div><div class="line">		Q.pop();</div><div class="line">		visit(p);</div><div class="line"></div><div class="line">		<span class="keyword">if</span> (p-&gt;lchild)</div><div class="line">			Q.push(p-&gt;lchild);</div><div class="line">		<span class="keyword">if</span> (p-&gt;rchild)</div><div class="line">			Q.push(p-&gt;rchild);</div><div class="line"></div><div class="line">		<span class="keyword">if</span> (p == back)</div><div class="line">		&#123;</div><div class="line">			<span class="built_in">cout</span> &lt;&lt; <span class="built_in">endl</span>;</div><div class="line">			<span class="keyword">if</span> (!Q.empty())</div><div class="line">				back = Q.back(); <span class="comment">// 更新back指针的位置</span></div><div class="line">		&#125;</div><div class="line">	&#125;</div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="keyword">template</span>&lt;<span class="keyword">typename</span> NODETYPE&gt;</div><div class="line"><span class="keyword">void</span> BiTree&lt;NODETYPE&gt;::visit(BiTNode&lt;NODETYPE&gt; *p)</div><div class="line">&#123;</div><div class="line">	<span class="built_in">cout</span> &lt;&lt; left &lt;&lt; setw(<span class="number">5</span>) &lt;&lt; p-&gt;data;</div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="meta">#<span class="meta-keyword">endif</span></span></div></pre></td></tr></table></figure></p>
<p>为了省事，main函数有些代码直接使用了前面一篇文章里面c的代码。</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div></pre></td><td class="code"><pre><div class="line"><span class="comment">// main.h</span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;iostream&gt;</span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">"BiTree.h"</span></span></div><div class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> <span class="built_in">std</span>;</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></div><div class="line">&#123;</div><div class="line">	<span class="keyword">int</span> i;</div><div class="line">	BiTree&lt;<span class="keyword">char</span>&gt; T;</div><div class="line">	<span class="keyword">char</span> e1;</div><div class="line">	</div><div class="line">	<span class="comment">//StrAssign(str,"ABDH#K###E##CFI###G#J##");</span></div><div class="line"></div><div class="line">	T.CreateBiTree();</div><div class="line"></div><div class="line">	<span class="built_in">printf</span>(<span class="string">"构造空二叉树后,树空否？%d(1:是 0:否) 树的深度: %d\n"</span>,T.BiTreeEmpty(), T.BiTreeDepthNonRecursion());</div><div class="line">	e1 = T.Root();</div><div class="line">	<span class="built_in">printf</span>(<span class="string">"二叉树的根为: %c\n"</span>,e1);</div><div class="line"></div><div class="line">	<span class="built_in">printf</span>(<span class="string">"\n前序遍历二叉树:\n"</span>);</div><div class="line">	<span class="comment">//T.PreOrderTraverse();</span></div><div class="line">	T.PreOrderNonRecursion();</div><div class="line"></div><div class="line">	<span class="built_in">printf</span>(<span class="string">"\n中序遍历二叉树:\n"</span>);</div><div class="line">	T.InOrderTraverse();</div><div class="line">	<span class="comment">//T.InOrderNonRecursion();</span></div><div class="line"></div><div class="line">	<span class="built_in">printf</span>(<span class="string">"\n后序遍历二叉树:\n"</span>);</div><div class="line">	<span class="comment">//T.PostOrderTraverse();</span></div><div class="line">	T.PostOrderNonRecursion();</div><div class="line"></div><div class="line">	<span class="built_in">printf</span>(<span class="string">"\n层次遍历二叉树:\n"</span>);</div><div class="line">	T.LevelOrderTraverse();</div><div class="line"></div><div class="line">	<span class="built_in">printf</span>(<span class="string">"\n每行二叉树的最右边的结点为:\n"</span>);</div><div class="line">	T.PrintLast();</div><div class="line"></div><div class="line">	<span class="built_in">printf</span>(<span class="string">"\n按层次输出每行的结点:\n"</span>);</div><div class="line">	T.PrintByDepth();</div><div class="line"></div><div class="line">	T.DestroyBiTree();</div><div class="line">	<span class="built_in">printf</span>(<span class="string">"\n清除二叉树后,树空否？%d(1:是 0:否) 树的深度=%d\n"</span>,T.BiTreeEmpty(),T.BiTreeDepth());</div><div class="line">	i = T.Root();</div><div class="line">	<span class="keyword">if</span>(!i)</div><div class="line">		<span class="built_in">printf</span>(<span class="string">"树空，无根\n"</span>);</div><div class="line"></div><div class="line">	getchar();</div><div class="line">	getchar();</div><div class="line">	<span class="keyword">return</span> <span class="number">0</span>;</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p style="text-align: justify;">写这个代码的时候，感觉自己计算机编程入门了——之前写代码主要都是照着书写，出错了更多都是照着书查找错误。写这个二叉树类的时候有个地方指针出错了，自己设断点改错，改了很久。所以入门的一些经验在下面一篇文章里面谈谈吧。</p>

<p>参考资料：<br>1.<a href="https://book.douban.com/subject/6424904/" target="_blank" rel="external"><span style="color: #0000ff;">《大话数据结构》</span></a><br>2.<a href="https://book.douban.com/subject/5349823/" target="_blank" rel="external"><span style="color: #0000ff;">《C++大学教程（第七版）》</span></a></p>
]]></content>
    
    <summary type="html">
    
      &lt;p style=&quot;text-align: justify;&quot;&gt;最近看数据结构看到二叉树的时候，自己实现了一下，同时写成了类，正好复习一下以前看C++的一些知识。代码如下。&lt;/p&gt;

&lt;figure class=&quot;highlight cpp&quot;&gt;&lt;table&gt;&lt;tr&gt;&lt;td cla
    
    </summary>
    
      <category term="编程学习" scheme="http://skills.frankge.me/categories/%E7%BC%96%E7%A8%8B%E5%AD%A6%E4%B9%A0/"/>
    
    
      <category term="C/C++" scheme="http://skills.frankge.me/tags/C-C/"/>
    
  </entry>
  
  <entry>
    <title>二叉树的实现以及相关操作C/C++</title>
    <link href="http://skills.frankge.me/the-implement-of-binary-tree-in-cpp/"/>
    <id>http://skills.frankge.me/the-implement-of-binary-tree-in-cpp/</id>
    <published>2016-09-10T16:38:36.000Z</published>
    <updated>2016-12-01T16:34:24.144Z</updated>
    
    <content type="html"><![CDATA[<p style="text-align: justify;">夏天看机器学习之余，把C语言给过了一遍，现在开始数据结构的学习了。最近看的二叉树，照着书实现了一下。</p>

<p style="text-align: justify;">其中包括二叉树的一些基本操作：初始化，建立，销毁，判空，深度和几种遍历。因为书上没给出非递归的遍历的非递归形式，自己这边给总结一下。代码本来是用C写的，但是其中有些功能的实现需要用到队列或者栈，直接调用C++的STL了。如下是相关代码。</p>

<figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div><div class="line">40</div><div class="line">41</div><div class="line">42</div><div class="line">43</div><div class="line">44</div><div class="line">45</div><div class="line">46</div><div class="line">47</div><div class="line">48</div><div class="line">49</div><div class="line">50</div><div class="line">51</div><div class="line">52</div><div class="line">53</div><div class="line">54</div><div class="line">55</div><div class="line">56</div><div class="line">57</div><div class="line">58</div><div class="line">59</div><div class="line">60</div><div class="line">61</div><div class="line">62</div><div class="line">63</div><div class="line">64</div><div class="line">65</div><div class="line">66</div><div class="line">67</div><div class="line">68</div><div class="line">69</div><div class="line">70</div><div class="line">71</div><div class="line">72</div><div class="line">73</div><div class="line">74</div><div class="line">75</div><div class="line">76</div><div class="line">77</div><div class="line">78</div><div class="line">79</div><div class="line">80</div><div class="line">81</div><div class="line">82</div><div class="line">83</div><div class="line">84</div><div class="line">85</div><div class="line">86</div><div class="line">87</div><div class="line">88</div><div class="line">89</div><div class="line">90</div><div class="line">91</div><div class="line">92</div><div class="line">93</div><div class="line">94</div><div class="line">95</div><div class="line">96</div><div class="line">97</div><div class="line">98</div><div class="line">99</div><div class="line">100</div><div class="line">101</div><div class="line">102</div><div class="line">103</div><div class="line">104</div><div class="line">105</div><div class="line">106</div><div class="line">107</div><div class="line">108</div><div class="line">109</div><div class="line">110</div><div class="line">111</div><div class="line">112</div><div class="line">113</div><div class="line">114</div><div class="line">115</div><div class="line">116</div><div class="line">117</div><div class="line">118</div><div class="line">119</div><div class="line">120</div><div class="line">121</div><div class="line">122</div><div class="line">123</div><div class="line">124</div><div class="line">125</div><div class="line">126</div><div class="line">127</div><div class="line">128</div><div class="line">129</div><div class="line">130</div><div class="line">131</div><div class="line">132</div><div class="line">133</div><div class="line">134</div><div class="line">135</div><div class="line">136</div><div class="line">137</div><div class="line">138</div><div class="line">139</div><div class="line">140</div><div class="line">141</div><div class="line">142</div><div class="line">143</div><div class="line">144</div><div class="line">145</div><div class="line">146</div><div class="line">147</div><div class="line">148</div><div class="line">149</div><div class="line">150</div><div class="line">151</div><div class="line">152</div><div class="line">153</div><div class="line">154</div><div class="line">155</div><div class="line">156</div><div class="line">157</div><div class="line">158</div><div class="line">159</div><div class="line">160</div><div class="line">161</div><div class="line">162</div><div class="line">163</div><div class="line">164</div><div class="line">165</div><div class="line">166</div><div class="line">167</div><div class="line">168</div><div class="line">169</div><div class="line">170</div><div class="line">171</div><div class="line">172</div><div class="line">173</div><div class="line">174</div><div class="line">175</div><div class="line">176</div><div class="line">177</div><div class="line">178</div><div class="line">179</div><div class="line">180</div><div class="line">181</div><div class="line">182</div><div class="line">183</div><div class="line">184</div><div class="line">185</div><div class="line">186</div><div class="line">187</div><div class="line">188</div><div class="line">189</div><div class="line">190</div><div class="line">191</div><div class="line">192</div><div class="line">193</div><div class="line">194</div><div class="line">195</div><div class="line">196</div><div class="line">197</div><div class="line">198</div><div class="line">199</div><div class="line">200</div><div class="line">201</div><div class="line">202</div><div class="line">203</div><div class="line">204</div><div class="line">205</div><div class="line">206</div><div class="line">207</div><div class="line">208</div><div class="line">209</div><div class="line">210</div><div class="line">211</div><div class="line">212</div><div class="line">213</div><div class="line">214</div><div class="line">215</div><div class="line">216</div><div class="line">217</div><div class="line">218</div><div class="line">219</div><div class="line">220</div><div class="line">221</div><div class="line">222</div><div class="line">223</div><div class="line">224</div><div class="line">225</div><div class="line">226</div><div class="line">227</div><div class="line">228</div><div class="line">229</div><div class="line">230</div><div class="line">231</div><div class="line">232</div><div class="line">233</div><div class="line">234</div><div class="line">235</div><div class="line">236</div><div class="line">237</div><div class="line">238</div><div class="line">239</div><div class="line">240</div><div class="line">241</div><div class="line">242</div><div class="line">243</div><div class="line">244</div><div class="line">245</div><div class="line">246</div><div class="line">247</div><div class="line">248</div><div class="line">249</div><div class="line">250</div><div class="line">251</div><div class="line">252</div><div class="line">253</div><div class="line">254</div><div class="line">255</div><div class="line">256</div><div class="line">257</div><div class="line">258</div><div class="line">259</div><div class="line">260</div><div class="line">261</div><div class="line">262</div><div class="line">263</div><div class="line">264</div><div class="line">265</div><div class="line">266</div><div class="line">267</div><div class="line">268</div><div class="line">269</div><div class="line">270</div><div class="line">271</div><div class="line">272</div><div class="line">273</div><div class="line">274</div><div class="line">275</div><div class="line">276</div><div class="line">277</div><div class="line">278</div><div class="line">279</div><div class="line">280</div><div class="line">281</div><div class="line">282</div><div class="line">283</div><div class="line">284</div><div class="line">285</div><div class="line">286</div><div class="line">287</div><div class="line">288</div><div class="line">289</div><div class="line">290</div><div class="line">291</div><div class="line">292</div><div class="line">293</div><div class="line">294</div><div class="line">295</div><div class="line">296</div><div class="line">297</div><div class="line">298</div><div class="line">299</div><div class="line">300</div><div class="line">301</div><div class="line">302</div><div class="line">303</div><div class="line">304</div><div class="line">305</div><div class="line">306</div><div class="line">307</div><div class="line">308</div><div class="line">309</div><div class="line">310</div><div class="line">311</div><div class="line">312</div><div class="line">313</div><div class="line">314</div><div class="line">315</div><div class="line">316</div><div class="line">317</div><div class="line">318</div><div class="line">319</div><div class="line">320</div><div class="line">321</div><div class="line">322</div><div class="line">323</div><div class="line">324</div><div class="line">325</div><div class="line">326</div><div class="line">327</div><div class="line">328</div><div class="line">329</div><div class="line">330</div><div class="line">331</div><div class="line">332</div><div class="line">333</div><div class="line">334</div><div class="line">335</div><div class="line">336</div><div class="line">337</div><div class="line">338</div><div class="line">339</div><div class="line">340</div><div class="line">341</div><div class="line">342</div><div class="line">343</div><div class="line">344</div><div class="line">345</div><div class="line">346</div><div class="line">347</div><div class="line">348</div><div class="line">349</div><div class="line">350</div><div class="line">351</div><div class="line">352</div><div class="line">353</div><div class="line">354</div><div class="line">355</div><div class="line">356</div><div class="line">357</div><div class="line">358</div><div class="line">359</div><div class="line">360</div><div class="line">361</div><div class="line">362</div><div class="line">363</div><div class="line">364</div><div class="line">365</div><div class="line">366</div><div class="line">367</div><div class="line">368</div><div class="line">369</div><div class="line">370</div><div class="line">371</div><div class="line">372</div><div class="line">373</div><div class="line">374</div><div class="line">375</div><div class="line">376</div><div class="line">377</div><div class="line">378</div><div class="line">379</div><div class="line">380</div><div class="line">381</div><div class="line">382</div><div class="line">383</div><div class="line">384</div><div class="line">385</div><div class="line">386</div><div class="line">387</div><div class="line">388</div><div class="line">389</div><div class="line">390</div><div class="line">391</div><div class="line">392</div><div class="line">393</div><div class="line">394</div><div class="line">395</div><div class="line">396</div><div class="line">397</div><div class="line">398</div><div class="line">399</div><div class="line">400</div><div class="line">401</div><div class="line">402</div><div class="line">403</div><div class="line">404</div><div class="line">405</div><div class="line">406</div><div class="line">407</div><div class="line">408</div><div class="line">409</div><div class="line">410</div><div class="line">411</div><div class="line">412</div><div class="line">413</div><div class="line">414</div><div class="line">415</div><div class="line">416</div><div class="line">417</div><div class="line">418</div><div class="line">419</div><div class="line">420</div><div class="line">421</div><div class="line">422</div><div class="line">423</div><div class="line">424</div><div class="line">425</div><div class="line">426</div><div class="line">427</div><div class="line">428</div><div class="line">429</div><div class="line">430</div><div class="line">431</div><div class="line">432</div><div class="line">433</div><div class="line">434</div><div class="line">435</div><div class="line">436</div><div class="line">437</div><div class="line">438</div><div class="line">439</div><div class="line">440</div><div class="line">441</div><div class="line">442</div><div class="line">443</div><div class="line">444</div><div class="line">445</div><div class="line">446</div><div class="line">447</div><div class="line">448</div><div class="line">449</div><div class="line">450</div><div class="line">451</div><div class="line">452</div><div class="line">453</div><div class="line">454</div><div class="line">455</div><div class="line">456</div><div class="line">457</div><div class="line">458</div><div class="line">459</div><div class="line">460</div><div class="line">461</div><div class="line">462</div><div class="line">463</div><div class="line">464</div><div class="line">465</div><div class="line">466</div><div class="line">467</div><div class="line">468</div><div class="line">469</div><div class="line">470</div><div class="line">471</div><div class="line">472</div><div class="line">473</div><div class="line">474</div><div class="line">475</div><div class="line">476</div><div class="line">477</div><div class="line">478</div><div class="line">479</div><div class="line">480</div><div class="line">481</div><div class="line">482</div><div class="line">483</div><div class="line">484</div><div class="line">485</div><div class="line">486</div><div class="line">487</div><div class="line">488</div><div class="line">489</div><div class="line">490</div><div class="line">491</div></pre></td><td class="code"><pre><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">"string.h"</span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">"stdio.h"</span>    </span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">"stdlib.h"</span>   </span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">"math.h"</span>  </span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;queue&gt;</span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stack&gt;</span></span></div><div class="line"><span class="keyword">using</span> <span class="keyword">namespace</span> <span class="built_in">std</span>;</div><div class="line"></div><div class="line"><span class="meta">#<span class="meta-keyword">define</span> OK 1</span></div><div class="line"><span class="meta">#<span class="meta-keyword">define</span> ERROR 0</span></div><div class="line"><span class="meta">#<span class="meta-keyword">define</span> TRUE 1</span></div><div class="line"><span class="meta">#<span class="meta-keyword">define</span> FALSE 0</span></div><div class="line"></div><div class="line"><span class="meta">#<span class="meta-keyword">define</span> MAXSIZE 100 <span class="comment">/* 存储空间初始分配量 */</span></span></div><div class="line"></div><div class="line"><span class="keyword">typedef</span> <span class="keyword">int</span> Status;</div><div class="line"></div><div class="line"><span class="keyword">typedef</span> <span class="keyword">char</span> TElemType;</div><div class="line">TElemType Nil = <span class="string">' '</span>;</div><div class="line"></div><div class="line"><span class="comment">/* 用于构造二叉树********************************** */</span></div><div class="line"><span class="keyword">int</span> index=<span class="number">1</span>;</div><div class="line"><span class="keyword">typedef</span> <span class="keyword">char</span> String[<span class="number">24</span>]; <span class="comment">/*  0号单元存放串的长度 */</span></div><div class="line">String str;</div><div class="line"></div><div class="line"><span class="function">Status <span class="title">StrAssign</span><span class="params">(String T,<span class="keyword">char</span> *chars)</span></span></div><div class="line">&#123; </div><div class="line">	<span class="keyword">int</span> i;</div><div class="line">	<span class="keyword">if</span>(<span class="built_in">strlen</span>(chars)&gt;MAXSIZE)</div><div class="line">		<span class="keyword">return</span> ERROR;</div><div class="line">	<span class="keyword">else</span></div><div class="line">	&#123;</div><div class="line">		T[<span class="number">0</span>]=<span class="built_in">strlen</span>(chars);</div><div class="line">		<span class="keyword">for</span>(i=<span class="number">1</span>;i&lt;=T[<span class="number">0</span>];i++)</div><div class="line">			T[i]=*(chars+i<span class="number">-1</span>);</div><div class="line">		<span class="keyword">return</span> OK;</div><div class="line">	&#125;</div><div class="line">&#125;</div><div class="line"><span class="comment">/* ************************************************ */</span></div><div class="line"></div><div class="line"><span class="keyword">typedef</span> <span class="keyword">struct</span> BiTNode</div><div class="line">&#123;</div><div class="line">	TElemType data;</div><div class="line">	<span class="keyword">struct</span> BiTNode *lchild, *rchild;</div><div class="line">&#125; BiTNode, *BiTree;</div><div class="line"></div><div class="line"><span class="function">Status <span class="title">InitBiTree</span><span class="params">(BiTree *T)</span></span>;</div><div class="line"><span class="function"><span class="keyword">void</span> <span class="title">CreateBiTree</span><span class="params">(BiTree *T)</span></span>;</div><div class="line"><span class="function"><span class="keyword">void</span> <span class="title">DestroyBiTree</span><span class="params">(BiTree *T)</span></span>;</div><div class="line"><span class="function">Status <span class="title">BiTreeEmpty</span><span class="params">(BiTree T)</span></span>;</div><div class="line"><span class="function">TElemType <span class="title">Root</span><span class="params">(BiTree T)</span></span>;</div><div class="line"><span class="function">TElemType <span class="title">Value</span><span class="params">(BiTree p)</span></span>;</div><div class="line"><span class="function"><span class="keyword">void</span> <span class="title">visit</span><span class="params">(BiTree T)</span></span>;</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">BiTreeDepth</span><span class="params">(BiTree T)</span></span>;</div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">BiTreeDepthNonRecursion</span><span class="params">(BiTree T)</span></span>;</div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">BiTreeDepthNonRecursion2</span><span class="params">(BiTree T)</span></span>;</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">void</span> <span class="title">PreOrderTraverse</span><span class="params">(BiTree T)</span></span>;</div><div class="line"><span class="function"><span class="keyword">void</span> <span class="title">PreOrderNonRecursion</span><span class="params">(BiTree T)</span></span>;</div><div class="line"><span class="function"><span class="keyword">void</span> <span class="title">InOrderTraverse</span><span class="params">(BiTree T)</span></span>;</div><div class="line"><span class="function"><span class="keyword">void</span> <span class="title">InOrderNonRecursion</span><span class="params">(BiTree T)</span></span>;</div><div class="line"><span class="function"><span class="keyword">void</span> <span class="title">PostOrderTraverse</span><span class="params">(BiTree T)</span></span>;</div><div class="line"><span class="function"><span class="keyword">void</span> <span class="title">PostOrderNonRecurion</span><span class="params">(BiTree T)</span></span>;</div><div class="line"><span class="function"><span class="keyword">void</span> <span class="title">LevelOrderTraverse</span><span class="params">(BiTree T)</span></span>;</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">void</span> <span class="title">PrintLastInEachLevel</span><span class="params">(BiTree T)</span></span>;</div><div class="line"><span class="function"><span class="keyword">void</span> <span class="title">PrintLevelOrderByLevel</span><span class="params">(BiTree T)</span></span>;</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></div><div class="line">&#123;</div><div class="line">	<span class="keyword">int</span> i;</div><div class="line">	BiTree T;</div><div class="line">	TElemType e1;</div><div class="line">	InitBiTree(&amp;T);</div><div class="line">	</div><div class="line">	<span class="comment">//StrAssign(str,"ABDH#K###E##CFI###G#J##");</span></div><div class="line"></div><div class="line">	CreateBiTree(&amp;T);</div><div class="line"></div><div class="line">	<span class="built_in">printf</span>(<span class="string">"构造空二叉树后,树空否？%d(1:是 0:否) 树的深度=%d\n"</span>,BiTreeEmpty(T),BiTreeDepthNonRecursion2(T));</div><div class="line">	e1=Root(T);</div><div class="line">	<span class="built_in">printf</span>(<span class="string">"二叉树的根为: %c\n"</span>,e1);</div><div class="line"></div><div class="line">	<span class="built_in">printf</span>(<span class="string">"\n前序遍历二叉树:\n"</span>);</div><div class="line">	PreOrderTraverse(T);</div><div class="line">	<span class="comment">//PreOrderNonRecursion(T);</span></div><div class="line"></div><div class="line">	<span class="built_in">printf</span>(<span class="string">"\n中序遍历二叉树:\n"</span>);</div><div class="line">	InOrderTraverse(T);</div><div class="line">	<span class="comment">//InOrderNonRecursion(T);</span></div><div class="line"></div><div class="line">	<span class="built_in">printf</span>(<span class="string">"\n后序遍历二叉树:\n"</span>);</div><div class="line">	PostOrderTraverse(T);</div><div class="line">	<span class="comment">//PostOrderNonRecurion(T);</span></div><div class="line"></div><div class="line">	<span class="built_in">printf</span>(<span class="string">"\n层次遍历二叉树:\n"</span>);</div><div class="line">	<span class="comment">//LevelOrderTraverse(T);</span></div><div class="line">	PrintLevelOrderByLevel(T);</div><div class="line">	<span class="built_in">printf</span>(<span class="string">"\n输出每层的最后一个结点:\n"</span>);</div><div class="line">	PrintLastInEachLevel(T);</div><div class="line">	</div><div class="line">	DestroyBiTree(&amp;T);</div><div class="line">	<span class="built_in">printf</span>(<span class="string">"\n清除二叉树后,树空否？%d(1:是 0:否) 树的深度=%d\n"</span>,BiTreeEmpty(T),BiTreeDepth(T));</div><div class="line">	i=Root(T);</div><div class="line">	<span class="keyword">if</span>(!i)</div><div class="line">		<span class="built_in">printf</span>(<span class="string">"树空，无根\n"</span>);</div><div class="line">	</div><div class="line">	getchar();</div><div class="line">	getchar();</div><div class="line">	<span class="keyword">return</span> <span class="number">0</span>;</div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="comment">//* 构造空二叉树T */</span></div><div class="line"><span class="function">Status <span class="title">InitBiTree</span><span class="params">(BiTree *T)</span></span></div><div class="line">&#123;</div><div class="line">	*T = <span class="literal">NULL</span>;</div><div class="line">	<span class="keyword">return</span> OK;</div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="comment">// 按前序输入二叉树中结点的值（一个字符）</span></div><div class="line"><span class="comment">// #表示空树，构造二叉链表表示二叉树T。 </span></div><div class="line"><span class="function"><span class="keyword">void</span> <span class="title">CreateBiTree</span><span class="params">(BiTree *T)</span></span></div><div class="line">&#123;</div><div class="line">	TElemType ch;</div><div class="line"></div><div class="line">	<span class="built_in">scanf</span>(<span class="string">"%c"</span>, &amp;ch);</div><div class="line"></div><div class="line">	<span class="keyword">if</span> (ch == <span class="string">'#'</span>)</div><div class="line">		(*T) = <span class="literal">NULL</span>;</div><div class="line">	<span class="keyword">else</span></div><div class="line">	&#123;</div><div class="line">		*T = (BiTree)<span class="built_in">malloc</span>(<span class="keyword">sizeof</span>(BiTNode));</div><div class="line">		<span class="keyword">if</span> (!*T)</div><div class="line">			<span class="built_in">exit</span>(OVERFLOW);</div><div class="line">		(*T)-&gt;data = ch;</div><div class="line">		CreateBiTree(&amp;(*T)-&gt;lchild);</div><div class="line">		CreateBiTree(&amp;(*T)-&gt;rchild);</div><div class="line">	&#125;</div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="comment">// 初始条件: 二叉树T存在。操作结果: 销毁二叉树T </span></div><div class="line"><span class="function"><span class="keyword">void</span> <span class="title">DestroyBiTree</span><span class="params">(BiTree *T)</span></span></div><div class="line">&#123;</div><div class="line">	<span class="keyword">if</span> (*T)</div><div class="line">	&#123;</div><div class="line">		<span class="keyword">if</span> ((*T)-&gt;lchild)</div><div class="line">			DestroyBiTree(&amp;(*T)-&gt;lchild);</div><div class="line">		<span class="keyword">if</span> ((*T)-&gt;rchild)</div><div class="line">			DestroyBiTree(&amp;(*T)-&gt;rchild);</div><div class="line">		<span class="built_in">free</span>(*T);</div><div class="line">		*T = <span class="literal">NULL</span>;</div><div class="line">	&#125;</div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="comment">// 初始条件：二叉树存在</span></div><div class="line"><span class="comment">// 操作结果：若T为空，则返回TRUE；否则返回FALSE</span></div><div class="line"><span class="function">Status <span class="title">BiTreeEmpty</span><span class="params">(BiTree T)</span></span></div><div class="line">&#123;</div><div class="line">	<span class="keyword">if</span> (!T)</div><div class="line">		<span class="keyword">return</span> TRUE;</div><div class="line">	<span class="keyword">else</span></div><div class="line">		<span class="keyword">return</span> FALSE;</div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="comment">// 初始条件：二叉树存在</span></div><div class="line"><span class="comment">// 操作结果：返回T的根</span></div><div class="line"><span class="function">TElemType <span class="title">Root</span><span class="params">(BiTree T)</span></span></div><div class="line">&#123;</div><div class="line">	<span class="keyword">if</span> (!T)</div><div class="line">		<span class="keyword">return</span> Nil;</div><div class="line">	<span class="keyword">else</span></div><div class="line">		<span class="keyword">return</span> T-&gt;data;</div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="comment">// 初始条件：节点存在</span></div><div class="line"><span class="comment">// 操作结果：输出结点的数据域</span></div><div class="line"><span class="function"><span class="keyword">void</span> <span class="title">visit</span><span class="params">(BiTNode *p)</span></span></div><div class="line">&#123;</div><div class="line">	<span class="keyword">if</span> (p)</div><div class="line">		<span class="built_in">printf</span>(<span class="string">"%c "</span>, p-&gt;data);</div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="comment">// 初始条件：二叉树存在</span></div><div class="line"><span class="comment">// 操作结果：返回二叉树深度</span></div><div class="line"><span class="comment">// 递归实现</span></div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">BiTreeDepth</span><span class="params">(BiTree T)</span></span></div><div class="line">&#123;</div><div class="line">	<span class="keyword">if</span> (!T)</div><div class="line">		<span class="keyword">return</span> <span class="number">0</span>;</div><div class="line"></div><div class="line">	<span class="keyword">int</span> i, j;</div><div class="line"></div><div class="line">	<span class="keyword">if</span> (T-&gt;lchild)</div><div class="line">		i = BiTreeDepth(T-&gt;lchild); <span class="comment">// 递归求出左子树高度</span></div><div class="line">	<span class="keyword">else</span></div><div class="line">		i = <span class="number">0</span>;</div><div class="line"></div><div class="line">	<span class="keyword">if</span> (T-&gt;rchild)</div><div class="line">		j = BiTreeDepth(T-&gt;rchild); <span class="comment">// 递归求出右子树高度</span></div><div class="line">	<span class="keyword">else</span></div><div class="line">		j = <span class="number">0</span>;</div><div class="line"></div><div class="line">	<span class="keyword">return</span> i &gt; j ? i+<span class="number">1</span> : j+<span class="number">1</span>;</div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="comment">// 求二叉树高度的非递归形式</span></div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">BiTreeDepthNonRecursion</span><span class="params">(BiTree T)</span></span></div><div class="line">&#123;</div><div class="line">	<span class="keyword">if</span> (!T)</div><div class="line">		<span class="keyword">return</span> <span class="number">0</span>;</div><div class="line"></div><div class="line">	<span class="built_in">queue</span>&lt;BiTNode *&gt; Q; <span class="comment">// 借助队列实现层次遍历，从而求出高度</span></div><div class="line">	BiTNode *p; <span class="comment">// 记录队列头部</span></div><div class="line">	BiTNode *back; <span class="comment">// 记录队列尾部指针</span></div><div class="line">	<span class="keyword">int</span> level = <span class="number">0</span>; <span class="comment">// 队列高度</span></div><div class="line"></div><div class="line">	Q.push(T);</div><div class="line">	back = Q.back();</div><div class="line">	<span class="keyword">while</span> (!Q.empty())</div><div class="line">	&#123;</div><div class="line">		p = Q.front();</div><div class="line">		Q.pop();</div><div class="line"></div><div class="line">		<span class="keyword">if</span> (p-&gt;lchild)</div><div class="line">			Q.push(p-&gt;lchild);</div><div class="line">		<span class="keyword">if</span> (p-&gt;rchild)</div><div class="line">			Q.push(p-&gt;rchild);</div><div class="line"></div><div class="line">		<span class="keyword">if</span> (p == back)</div><div class="line">		&#123;</div><div class="line">			level++;</div><div class="line">			<span class="keyword">if</span> (!Q.empty()) <span class="comment">// 防止最后Q为空时出错</span></div><div class="line">				back = Q.back();</div><div class="line">		&#125;</div><div class="line">	&#125;</div><div class="line"></div><div class="line">	<span class="keyword">return</span> level;</div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="comment">// 求二叉树高度的非递归形式</span></div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">BiTreeDepthNonRecursion2</span><span class="params">(BiTree T)</span></span></div><div class="line">&#123;</div><div class="line">	BiTNode *Q[MAXSIZE]; <span class="comment">// 借助队列实现层次遍历，从而求出高度。此时用数组实现队列</span></div><div class="line">	<span class="keyword">int</span> level = <span class="number">0</span>; <span class="comment">// 二叉树高度</span></div><div class="line">	<span class="keyword">int</span> last = <span class="number">0</span>; <span class="comment">// 每层次最后一个结点</span></div><div class="line">	<span class="keyword">int</span> front = <span class="number">-1</span>; <span class="comment">// 队列头指针</span></div><div class="line">	<span class="keyword">int</span> rear = <span class="number">-1</span>; <span class="comment">// 队列尾指针</span></div><div class="line">	BiTNode *p;</div><div class="line"></div><div class="line">	Q[++rear] = T;</div><div class="line">	last = rear;</div><div class="line">	<span class="keyword">while</span> (front &lt; rear) <span class="comment">// 队列不空</span></div><div class="line">	&#123;</div><div class="line">		p = Q[++front];</div><div class="line"></div><div class="line">		<span class="keyword">if</span> (p-&gt;lchild)</div><div class="line">			Q[++rear] = p-&gt;lchild;</div><div class="line">		<span class="keyword">if</span> (p-&gt;rchild)</div><div class="line">			Q[++rear] = p-&gt;rchild;</div><div class="line"></div><div class="line">		<span class="keyword">if</span> (front == last)</div><div class="line">		&#123;</div><div class="line">			level++;</div><div class="line">			<span class="keyword">if</span> (front &lt; rear)</div><div class="line">				last = rear;</div><div class="line">		&#125;</div><div class="line">	&#125;</div><div class="line"></div><div class="line">	<span class="keyword">return</span> level;</div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="comment">// 初始条件：二叉树存在</span></div><div class="line"><span class="comment">// 操作结果：前序遍历二叉树</span></div><div class="line"><span class="function"><span class="keyword">void</span> <span class="title">PreOrderTraverse</span><span class="params">(BiTree T)</span></span></div><div class="line">&#123;</div><div class="line">	<span class="keyword">if</span> (!T)</div><div class="line">		<span class="keyword">return</span>;</div><div class="line"></div><div class="line">	visit(T);</div><div class="line">	PreOrderTraverse(T-&gt;lchild);</div><div class="line">	PreOrderTraverse(T-&gt;rchild);</div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="comment">// 前序遍历非递归形式</span></div><div class="line"><span class="function"><span class="keyword">void</span> <span class="title">PreOrderNonRecursion</span><span class="params">(BiTree T)</span></span></div><div class="line">&#123;</div><div class="line">	<span class="keyword">if</span> (!T)</div><div class="line">		<span class="keyword">return</span>;</div><div class="line"></div><div class="line">	<span class="built_in">stack</span>&lt;BiTNode *&gt; S; <span class="comment">// 借助栈实现非递归遍历</span></div><div class="line">	BiTNode *p;</div><div class="line"></div><div class="line">	p = T;</div><div class="line">	<span class="keyword">while</span> (p || !S.empty())</div><div class="line">	&#123;</div><div class="line">		<span class="keyword">while</span> (p)</div><div class="line">		&#123;</div><div class="line">			S.push(p);</div><div class="line">			visit(p); <span class="comment">// 在每次入栈时进行访问</span></div><div class="line">			p = p-&gt;lchild;</div><div class="line">		&#125;</div><div class="line">		<span class="keyword">if</span> (!S.empty())</div><div class="line">		&#123;</div><div class="line">			p = S.top(); </div><div class="line">			S.pop();</div><div class="line">			p = p-&gt;rchild;</div><div class="line">		&#125;</div><div class="line">	&#125;</div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="comment">// 初始条件：二叉树存在</span></div><div class="line"><span class="comment">// 操作结果：中序遍历二叉树</span></div><div class="line"><span class="function"><span class="keyword">void</span> <span class="title">InOrderTraverse</span><span class="params">(BiTree T)</span></span></div><div class="line">&#123;</div><div class="line">	<span class="keyword">if</span> (!T)</div><div class="line">		<span class="keyword">return</span>;</div><div class="line"></div><div class="line">	InOrderTraverse(T-&gt;lchild);</div><div class="line">	visit(T);</div><div class="line">	InOrderTraverse(T-&gt;rchild);</div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="comment">// 中序遍历二叉树非递归形式</span></div><div class="line"><span class="function"><span class="keyword">void</span> <span class="title">InOrderNonRecursion</span><span class="params">(BiTree T)</span></span></div><div class="line">&#123;</div><div class="line">	<span class="keyword">if</span> (!T)</div><div class="line">		<span class="keyword">return</span>;</div><div class="line"></div><div class="line">	<span class="built_in">stack</span>&lt;BiTNode *&gt; S;</div><div class="line">	BiTNode *p;</div><div class="line">	</div><div class="line">	p = T;</div><div class="line">	<span class="keyword">while</span> (p || !S.empty())</div><div class="line">	&#123;</div><div class="line">		<span class="keyword">while</span> (p)</div><div class="line">		&#123;</div><div class="line">			S.push(p);</div><div class="line">			p = p-&gt;lchild;</div><div class="line">		&#125;</div><div class="line">		<span class="keyword">if</span> (!S.empty())</div><div class="line">		&#123;</div><div class="line">			p = S.top();</div><div class="line">			S.pop();</div><div class="line">			visit(p); <span class="comment">// 每次从栈中弹出的时候访问结点</span></div><div class="line">			p = p-&gt;rchild;</div><div class="line">		&#125;</div><div class="line">	&#125;</div><div class="line">&#125;</div><div class="line"></div><div class="line"></div><div class="line"><span class="comment">// 初始条件：二叉树存在</span></div><div class="line"><span class="comment">// 操作结果：后序递归遍历二叉树</span></div><div class="line"><span class="function"><span class="keyword">void</span> <span class="title">PostOrderTraverse</span><span class="params">(BiTree T)</span></span></div><div class="line">&#123;</div><div class="line">	<span class="keyword">if</span> (!T)</div><div class="line">		<span class="keyword">return</span>;</div><div class="line"></div><div class="line">	PostOrderTraverse(T-&gt;lchild);</div><div class="line">	PostOrderTraverse(T-&gt;rchild);</div><div class="line">	visit(T);</div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="comment">// 后序遍历非递归形式</span></div><div class="line"><span class="comment">// 难点是分清栈中弹出根结点时，是从左子树弹出还是右子树弹出。所以使用辅助指针r。</span></div><div class="line"><span class="function"><span class="keyword">void</span> <span class="title">PostOrderNonRecurion</span><span class="params">(BiTree T)</span></span></div><div class="line">&#123;</div><div class="line">	<span class="keyword">if</span> (!T)</div><div class="line">		<span class="keyword">return</span>;</div><div class="line"></div><div class="line">	<span class="built_in">stack</span>&lt;BiTNode *&gt; S;</div><div class="line">	BiTNode *p;</div><div class="line">	BiTNode *r; <span class="comment">// 用指针r记录最近访问的结点</span></div><div class="line"></div><div class="line">	p = T;</div><div class="line">	r = <span class="literal">NULL</span>;</div><div class="line">	<span class="keyword">while</span> (p || !S.empty())</div><div class="line">	&#123;</div><div class="line">		<span class="keyword">while</span> (p)</div><div class="line">		&#123;</div><div class="line">			S.push(p);</div><div class="line">			p = p-&gt;lchild;</div><div class="line">		&#125;</div><div class="line">		<span class="keyword">if</span> (!S.empty())</div><div class="line">		&#123;</div><div class="line">			p = S.top();</div><div class="line">			<span class="keyword">if</span> (p-&gt;rchild &amp;&amp; p-&gt;rchild != r) <span class="comment">// 如果右子树存在，且未访问过</span></div><div class="line">			&#123;</div><div class="line">				p = p-&gt;rchild;</div><div class="line">				S.push(p);</div><div class="line">				p = p-&gt;lchild;</div><div class="line">			&#125;</div><div class="line">			<span class="keyword">else</span></div><div class="line">			&#123;</div><div class="line">				S.pop();</div><div class="line">				visit(p);</div><div class="line">				r = p;</div><div class="line">				p = <span class="literal">NULL</span>;</div><div class="line">			&#125;</div><div class="line">		&#125;</div><div class="line">	&#125;</div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="comment">// 初始条件：二叉树存在</span></div><div class="line"><span class="comment">// 操作结果：层次遍历二叉树</span></div><div class="line"><span class="function"><span class="keyword">void</span> <span class="title">LevelOrderTraverse</span><span class="params">(BiTree T)</span></span></div><div class="line">&#123;</div><div class="line">	<span class="keyword">if</span> (!T)</div><div class="line">		<span class="keyword">return</span>;</div><div class="line"></div><div class="line">	<span class="built_in">queue</span>&lt;BiTNode *&gt; Q; <span class="comment">// 借助队列实现层次遍历</span></div><div class="line">	BiTNode *p;</div><div class="line"></div><div class="line">	Q.push(T);</div><div class="line">	<span class="keyword">while</span> (!Q.empty())</div><div class="line">	&#123;</div><div class="line">		p = Q.front();</div><div class="line">		Q.pop();</div><div class="line">		visit(p); <span class="comment">// 每次弹出的时候访问结点</span></div><div class="line"></div><div class="line">		<span class="keyword">if</span> (p-&gt;lchild)</div><div class="line">			Q.push(p-&gt;lchild);</div><div class="line">		<span class="keyword">if</span> (p-&gt;rchild)</div><div class="line">			Q.push(p-&gt;rchild);</div><div class="line">	&#125;</div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="comment">// 初始条件：二叉树存在</span></div><div class="line"><span class="comment">// 操作结果：访问每层二叉树最右边的结点</span></div><div class="line"><span class="function"><span class="keyword">void</span> <span class="title">PrintLastInEachLevel</span><span class="params">(BiTree T)</span></span></div><div class="line">&#123;</div><div class="line">	<span class="keyword">if</span> (!T) <span class="comment">// 如果树为空，则返回</span></div><div class="line">		<span class="keyword">return</span>;</div><div class="line"></div><div class="line">	<span class="built_in">queue</span>&lt;BiTNode *&gt; Q;</div><div class="line">	BiTNode *p;</div><div class="line">	BiTNode *back; <span class="comment">// 指向每层最后一个结点的指针</span></div><div class="line"></div><div class="line">	Q.push(T);</div><div class="line">	back = Q.back();</div><div class="line">	<span class="keyword">while</span> (!Q.empty())</div><div class="line">	&#123;</div><div class="line">		p = Q.front();</div><div class="line">		Q.pop();</div><div class="line"></div><div class="line">		<span class="keyword">if</span> (p-&gt;lchild)</div><div class="line">			Q.push(p-&gt;lchild);</div><div class="line">		<span class="keyword">if</span> (p-&gt;rchild)</div><div class="line">			Q.push(p-&gt;rchild);</div><div class="line"></div><div class="line">		<span class="keyword">if</span> (p == back)</div><div class="line">		&#123;</div><div class="line">			visit(p);</div><div class="line">			<span class="keyword">if</span> (!Q.empty())</div><div class="line">				back = Q.back();</div><div class="line">		&#125;</div><div class="line">	&#125;</div><div class="line">&#125;</div><div class="line"></div><div class="line"><span class="comment">// 初始条件：二叉树存在</span></div><div class="line"><span class="comment">// 操作结果：分行输出每层二叉树的结点</span></div><div class="line"><span class="function"><span class="keyword">void</span> <span class="title">PrintLevelOrderByLevel</span><span class="params">(BiTree T)</span></span></div><div class="line">&#123;</div><div class="line">	<span class="keyword">if</span> (!T)</div><div class="line">		<span class="keyword">return</span>;</div><div class="line"></div><div class="line">	<span class="built_in">queue</span>&lt;BiTNode *&gt; Q;</div><div class="line">	BiTNode *p;</div><div class="line">	BiTNode *back; <span class="comment">// 记录每层最右边的结点，从而实现分行输出</span></div><div class="line"></div><div class="line">	Q.push(T);</div><div class="line">	back = Q.back();</div><div class="line">	<span class="keyword">while</span> (!Q.empty())</div><div class="line">	&#123;</div><div class="line">		p = Q.front();</div><div class="line">		Q.pop();</div><div class="line">		visit(p);</div><div class="line"></div><div class="line">		<span class="keyword">if</span> (p-&gt;lchild)</div><div class="line">			Q.push(p-&gt;lchild);</div><div class="line">		<span class="keyword">if</span> (p-&gt;rchild)</div><div class="line">			Q.push(p-&gt;rchild);</div><div class="line"></div><div class="line">		<span class="keyword">if</span> (p == back)</div><div class="line">		&#123;</div><div class="line">			<span class="built_in">putchar</span>(<span class="string">'\n'</span>);</div><div class="line">			<span class="keyword">if</span> (!Q.empty())</div><div class="line">				back = Q.back();</div><div class="line">		&#125;</div><div class="line">	&#125;</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p style="text-align: justify;">本身感觉现在这些在计算机专业里面应该是太基础的东西了，不想贴出来的，但是确实这个算是一个里程碑吧——感觉自己对编程有点入门了。下一篇会把用类实现的二叉树的代码贴上来，之后再写点自学编程上面的一些感悟或者说一些经验吧。</p>

<p>参考资料：</p>
<p>1.<span style="color: #0000ff;"><a href="https://book.douban.com/subject/6424904/" target="_blank" rel="external">《大话数据结构》</a></span></p>
]]></content>
    
    <summary type="html">
    
      &lt;p style=&quot;text-align: justify;&quot;&gt;夏天看机器学习之余，把C语言给过了一遍，现在开始数据结构的学习了。最近看的二叉树，照着书实现了一下。&lt;/p&gt;

&lt;p style=&quot;text-align: justify;&quot;&gt;其中包括二叉树的一些基本操作：初始化，建
    
    </summary>
    
      <category term="编程学习" scheme="http://skills.frankge.me/categories/%E7%BC%96%E7%A8%8B%E5%AD%A6%E4%B9%A0/"/>
    
    
      <category term="C/C++" scheme="http://skills.frankge.me/tags/C-C/"/>
    
  </entry>
  
  <entry>
    <title>顺序单链表插入新节点的一种方法</title>
    <link href="http://skills.frankge.me/a-smart-way-to-insert-a-new-node-in-sorted-singly-linked-list/"/>
    <id>http://skills.frankge.me/a-smart-way-to-insert-a-new-node-in-sorted-singly-linked-list/</id>
    <published>2016-08-17T16:09:39.000Z</published>
    <updated>2016-12-01T14:53:23.270Z</updated>
    
    <content type="html"><![CDATA[<p style="text-align: justify;">在学习链表的时候我们都接触过单链表插入新结点的问题。其中有一类就是在顺序链表中插入新节点，并保持链表的递增或者递减性质。</p>

<p style="text-align: justify;">最近看《C和指针》一书中提到了一种方法，我个人感觉不错，并且思想非常好。</p>

<p style="text-align: justify;">这是最常见的思维：</p>

<figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div></pre></td><td class="code"><pre><div class="line"><span class="comment">//sll_node.h  </span></div><div class="line"></div><div class="line"><span class="keyword">typedef</span> <span class="keyword">struct</span> Node  </div><div class="line">&#123;  </div><div class="line">    <span class="keyword">int</span> value;  </div><div class="line">    Node *next;  </div><div class="line">&#125; Node;</div></pre></td></tr></table></figure>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div><div class="line">35</div><div class="line">36</div><div class="line">37</div><div class="line">38</div><div class="line">39</div></pre></td><td class="code"><pre><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">"sll_node.h"</span>  </span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdio.h&gt;</span>  </span></div><div class="line">  </div><div class="line"><span class="meta">#<span class="meta-keyword">define</span> TRUE    1  </span></div><div class="line"><span class="meta">#<span class="meta-keyword">define</span> FALSE   0  </span></div><div class="line">  </div><div class="line"><span class="comment">// insertNode:把newValue的值插入到递增排序的链表中，正确返回TRUE，错误返回FALSE  </span></div><div class="line"><span class="comment">// rootp是链表的头指针。  </span></div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">insertNode</span><span class="params">(Node **rootp, <span class="keyword">int</span> newValue)</span>  </span></div><div class="line">&#123;  </div><div class="line">    Node *newNode; <span class="comment">// 新节点的指针  </span></div><div class="line">    Node *previous; <span class="comment">// 当前指针的前一个指针  </span></div><div class="line">    Node *current; <span class="comment">// 当前指针  </span></div><div class="line">  </div><div class="line">    current = *rootp; <span class="comment">// 初始化  </span></div><div class="line">    previous = <span class="literal">NULL</span>;  </div><div class="line">  </div><div class="line">    <span class="comment">// 查找插入的位置  </span></div><div class="line">    <span class="keyword">while</span> (current != <span class="literal">NULL</span> &amp;&amp; current-&gt;value &lt; newValue)</div><div class="line">    &#123;</div><div class="line">        previous = current;</div><div class="line">        current = current-&gt;next;</div><div class="line">    &#125;</div><div class="line">  </div><div class="line">    <span class="comment">// 给新节点分配空间  </span></div><div class="line">    newNode = (Node *)<span class="built_in">malloc</span>(<span class="keyword">sizeof</span>(Node));  </div><div class="line">    <span class="keyword">if</span> (newNode == <span class="literal">NULL</span>)  </div><div class="line">        <span class="keyword">return</span> FALSE;  </div><div class="line">    newNode-&gt;value = newValue;  </div><div class="line">  </div><div class="line">    <span class="comment">// 更改新节点的前驱和后继节点  </span></div><div class="line">    newNode-&gt;next = current;  </div><div class="line">    <span class="keyword">if</span> (previous == <span class="literal">NULL</span>) <span class="comment">// 此时插入节点的为链表中第一个节点，修改头指针  </span></div><div class="line">        *rootp = newNode;  </div><div class="line">    <span class="keyword">else</span>  </div><div class="line">        previous-&gt;next = newNode;</div><div class="line"></div><div class="line">    <span class="keyword">return</span> TRUE;</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p style="text-align: justify;">我以前编写的时候也会用这样的方法：一个当前指针和指向当前指针之前的指针，这样需要讨论原链表是否为空。书中提到了一种抽象，每次插入新的节点，都是改变一个指向这个新节点的指针以及指向下一个节点，这样可以省略讨论插入的节点是否为第一个节点的步骤。代码如下：</p>

<figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div></pre></td><td class="code"><pre><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">"sll_node.h"</span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdio.h&gt;</span></span></div><div class="line"></div><div class="line"><span class="meta">#<span class="meta-keyword">define</span>	FALSE	0</span></div><div class="line"><span class="meta">#<span class="meta-keyword">define</span> TRUE	1</span></div><div class="line"></div><div class="line"><span class="comment">// insertNode2:把newValue的值插入到递增排序的链表中，正确返回TRUE，错误返回FALSE</span></div><div class="line"><span class="comment">// nextp是指向当前节点的指针，最初是头指针</span></div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">insertNode2</span><span class="params">(Node **nextp, <span class="keyword">int</span> newValue)</span></span></div><div class="line">&#123;</div><div class="line">	Node *newNode; <span class="comment">// 新节点指针</span></div><div class="line">	Node *current; <span class="comment">// 当前节点指针</span></div><div class="line"></div><div class="line">	current = *nextp; <span class="comment">// 最初当前节点为nextp指针指向的节点</span></div><div class="line">	<span class="comment">// 查找新插入节点的位置</span></div><div class="line">	<span class="keyword">while</span> (current != <span class="literal">NULL</span> &amp;&amp; current-&gt;value &lt; newValue)</div><div class="line">	&#123;</div><div class="line">		nextp = &amp;current-&gt;next;</div><div class="line">		current = current-&gt;next;</div><div class="line">	&#125;</div><div class="line"></div><div class="line">	<span class="comment">// 为新节点分配内存</span></div><div class="line">	newNode = (Node *)<span class="built_in">malloc</span>(<span class="keyword">sizeof</span>(Node));</div><div class="line">	<span class="keyword">if</span> (newNode == <span class="literal">NULL</span>)</div><div class="line">		<span class="keyword">return</span> FALSE;</div><div class="line">	newNode-&gt;value = newValue;</div><div class="line"></div><div class="line">	<span class="comment">// 统一了插入的步骤。即：每次插入，都是前一个指针指向新节点，新节点指向下一个节点</span></div><div class="line">	*nextp = newNode;</div><div class="line">	newNode-&gt;next = current;</div><div class="line"></div><div class="line">	<span class="keyword">return</span> TRUE;</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p>main函数</p>
<figure class="highlight cpp"><table><tr><td class="gutter"><pre><div class="line">1</div><div class="line">2</div><div class="line">3</div><div class="line">4</div><div class="line">5</div><div class="line">6</div><div class="line">7</div><div class="line">8</div><div class="line">9</div><div class="line">10</div><div class="line">11</div><div class="line">12</div><div class="line">13</div><div class="line">14</div><div class="line">15</div><div class="line">16</div><div class="line">17</div><div class="line">18</div><div class="line">19</div><div class="line">20</div><div class="line">21</div><div class="line">22</div><div class="line">23</div><div class="line">24</div><div class="line">25</div><div class="line">26</div><div class="line">27</div><div class="line">28</div><div class="line">29</div><div class="line">30</div><div class="line">31</div><div class="line">32</div><div class="line">33</div><div class="line">34</div></pre></td><td class="code"><pre><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdio.h&gt;</span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;stdlib.h&gt;</span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">&lt;time.h&gt;</span></span></div><div class="line"><span class="meta">#<span class="meta-keyword">include</span> <span class="meta-string">"sll_node.h"</span></span></div><div class="line"></div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">insertNode</span><span class="params">(Node **rootp, <span class="keyword">int</span> newValue)</span></span>;</div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">insertNode2</span><span class="params">(Node **nextp, <span class="keyword">int</span> newValue)</span></span>;</div><div class="line"></div><div class="line"><span class="function"><span class="keyword">int</span> <span class="title">main</span><span class="params">()</span></span></div><div class="line">&#123;</div><div class="line">	srand(time(<span class="number">0</span>));</div><div class="line"></div><div class="line">	Node *head = (Node *)<span class="built_in">malloc</span>(<span class="keyword">sizeof</span>(Node));</div><div class="line">	head-&gt;next = <span class="literal">NULL</span>;</div><div class="line"></div><div class="line">	<span class="keyword">for</span> (<span class="keyword">int</span> i = <span class="number">0</span>; i &lt; <span class="number">5</span>; i++)</div><div class="line">	&#123;</div><div class="line">		<span class="keyword">int</span> temp = rand() % <span class="number">50</span>;</div><div class="line">		<span class="built_in">printf</span>(<span class="string">"%d\n"</span>, temp);</div><div class="line">		<span class="comment">//insertNode(&amp;head,temp);</span></div><div class="line">		insertNode2(&amp;head,temp);</div><div class="line">	&#125;</div><div class="line">	</div><div class="line">	Node *p = head-&gt;next;</div><div class="line">	<span class="keyword">while</span> (p != <span class="literal">NULL</span>)</div><div class="line">	&#123;</div><div class="line">		<span class="built_in">printf</span>(<span class="string">"%d\n"</span>, p-&gt;value);</div><div class="line">		p = p-&gt;next;</div><div class="line">	&#125;</div><div class="line"></div><div class="line">	getchar();</div><div class="line">	getchar();</div><div class="line">	<span class="keyword">return</span> <span class="number">0</span>;</div><div class="line">&#125;</div></pre></td></tr></table></figure>
<p style="text-align: justify;">因为我个人没有经过正经的课堂训练，自己考研才接触编程、数据结构之类的。看了很多对自学编程提的建议都是多编写，并且要有抽象的思想，所以将这个方法写了下来，可能对很对科班出身的人不算什么问题了吧。</p>

<p style="text-align: justify;">我感觉这个抽象很好，希望是给自己编程道路的一个好的开端吧:)</p>

<p style="text-align: justify;">同时，因为我在初学时发现测试代码也会花费很多时间，所以将完成的代码都贴了上来，而不仅仅是函数，希望也能帮助到更多的想我这样的初学者吧。</p>]]></content>
    
    <summary type="html">
    
      &lt;p style=&quot;text-align: justify;&quot;&gt;在学习链表的时候我们都接触过单链表插入新结点的问题。其中有一类就是在顺序链表中插入新节点，并保持链表的递增或者递减性质。&lt;/p&gt;

&lt;p style=&quot;text-align: justify;&quot;&gt;最近看《C和指针》一
    
    </summary>
    
      <category term="编程学习" scheme="http://skills.frankge.me/categories/%E7%BC%96%E7%A8%8B%E5%AD%A6%E4%B9%A0/"/>
    
    
      <category term="C/C++" scheme="http://skills.frankge.me/tags/C-C/"/>
    
  </entry>
  
  <entry>
    <title>博客时间轴</title>
    <link href="http://skills.frankge.me/the-timeline-of-my-blog/"/>
    <id>http://skills.frankge.me/the-timeline-of-my-blog/</id>
    <published>2016-08-15T02:56:55.000Z</published>
    <updated>2016-12-03T06:49:40.079Z</updated>
    
    <content type="html"><![CDATA[<h3 id="16-11-21"><a href="#16-11-21" class="headerlink" title="16.11.21"></a><span style="color: #0000ff;">16.11.21</span></h3><p>将<span style="color: #3366ff;"><a href="http://frankge.me/blog-old-site/" target="_blank" rel="external">frankge.me/blog</a></span>站点全部移至<span style="color: #3366ff;"><a href="http://blog.frankge.me" target="_blank" rel="external">blog.frankge.me</a><span style="color: #000000;">，以前的文章保留原链接，但不更新，新链接开始使用。</span></span></p>
<h3 id="16-08-29"><a href="#16-08-29" class="headerlink" title="16.08.29"></a><span style="color: #0000ff;">16.08.29</span></h3><p>添加如下插件：</p>
<p>1.<span style="color: #0000ff;"><a href="https://wordpress.org/plugins/latex/" target="_blank" rel="external">LaTeX for WordPress</a></span>。此插件可以在wordpress编辑LaTex公式。这个插件的作者就是我的推荐博客中<span style="color: #0000ff;"><a href="http://zhiqiang.org/blog/" target="_blank" rel="external">阅微堂</a></span>的博主写的。<span style="color: #0000ff;"><a href="http://www.codelast.com/%E5%8E%9F%E5%88%9B%E7%94%A8latex-for-wordpress%E6%8F%92%E4%BB%B6%E5%9C%A8wordpress%E4%B8%AD%E5%86%99%E6%95%B0%E5%AD%A6%E5%85%AC%E5%BC%8F/" target="_blank" rel="external">这个页面</a></span>中有一些关于此插件用法的总结。</p>
<h3 id="16-08-26"><a href="#16-08-26" class="headerlink" title="16.08.26"></a><span style="color: #0000ff;">16.08.26</span></h3><p>对自己博客的手机端进行了一些优化，比如首页只显示三篇文章标题等，不过手机端的显示每次在更新博文之后几个小时之内会显示成为修改之前的样式。</p>
<p>添加如下插件：</p>
<p>1.<span style="color: #0000ff;"><a href="https://wordpress.org/plugins/wp-mobile-themes/" target="_blank" rel="external">WordPress Mobile Themes</a></span>。此插件可以实现wordpress手机端和桌面端使用不同的主题。<br>2.<span style="color: #0000ff;"><a href="https://wordpress.org/plugins/wp-super-cache/" target="_blank" rel="external">WP Super Cache</a></span>。把wordpress页面静态缓存，提高浏览速度。<br>3.<span style="color: #0000ff;"><a href="https://wordpress.org/plugins/dynamic-to-top/" target="_blank" rel="external">Dynamic To Top</a></span>。在文章页面中增加跳转回顶部的插件。<br>4.<span style="color: #0000ff;"><a href="https://wordpress.org/plugins/backupwordpress/" target="_blank" rel="external">BackUpWordPress</a></span>。众所周知，备份是很重要的，如果出现什么问题，之前的备份就会有很大的作用了。这款插件就是实现自动备份wordpress的插件，可以选择时间将备份的wordpress内容发送到你的邮箱。<br>5.<span style="color: #0000ff;"><a href="https://wordpress.org/plugins/wordpress-importer/" target="_blank" rel="external">WordPress 导入工具</a></span>。将以上提到的BackUpWordPress插件备份的内容还原。之前其实就用过这两款插件。因为本来博客的页面是frankge.me的，但是后来出现了一些问题，所以改到了frankge.me/blog页面，就是用的这两款插件。</p>
<h3 id="16-08-17"><a href="#16-08-17" class="headerlink" title="16.08.17"></a><span style="color: #0000ff;">16.08.17</span></h3><p>添加如下插件：</p>
<p>1.<span style="color: #0000ff;"><a href="https://wordpress.org/plugins/akismet/" target="_blank" rel="external">Akismet</a></span>：此插件可用于过滤垃圾留言。<br>2.<span style="color: #0000ff;"><a href="https://wordpress.org/plugins/google-sitemap-generator/" target="_blank" rel="external">Google XML Sitemap</a></span>：给自己的博客生成sitemap，方便搜索引擎抓取文章。<br>3.<span style="color: #0000ff;"><a href="https://wordpress.org/plugins/syntaxhighlighter/" target="_blank" rel="external">SyntaxHighlighter Evolved</a></span>：便于插入代码。支持很多种编程语言：cpp, java, python, css等等，使用方法和支持的语言具体参见<a href="https://en.support.wordpress.com/code/posting-source-code/" target="_blank" rel="external"><span style="color: #0000ff;">这个页面</span></a>。</p>
<h3 id="16年05月"><a href="#16年05月" class="headerlink" title="16年05月"></a><span style="color: #0000ff;"><strong>16年05月</strong></span></h3><p>于<span style="color: #0000ff;"><a href="https://godaddy.com" target="_blank" rel="external">GoDaddy</a></span>买域名frankge.me。主机采用的<span style="color: #0000ff;"><a href="http://www.gegehost.com/" target="_blank" rel="external">戈戈主机</a></span>。采用<span style="color: #0000ff;"><a href="https://wordpress.org/" target="_blank" rel="external">wordpress</a></span>搭建。</p>
<p><strong>建站过程</strong></p>
<p>按照知乎用户@waylight 在<span style="color: #0000ff;"><a href="https://www.zhihu.com/question/19594033" target="_blank" rel="external">怎样搭建一个自有域名的 WordPress 博客？</a></span>的回答进行。建站期间还遇到一些问题，所以将自己的建站过程记录如下。</p>
<p>主要步骤为：</p>
<p><strong>1.建立本地博客文件</strong></p>
<p>建立博客的过程中肯定需要记录一些信息（比如博客的登录名和密码，主机服务器的ip和登录名密码，还有博客头像和一些备份内容等等）和一些待解决的问题（建立博客可能不是一次就完成的）。这个文件夹用于存放这些信息，便于以后的查看、修改和一些重要信息的备份。</p>
<p><strong>2.购买域名</strong></p>
<p>前文说了，我个人是在GoDaddy上面购买的域名，个人感觉还不错，同时看好像是支持支付宝付款，方便不过我个人是用Visa信用卡付款的。</p>
<p>同时正如知乎的回答中所说，如果你提前想好了想要买的域名，在自己的购物车中放几天，然后GoDaddy就会给你邮箱发送优惠券的，优惠券好像只能信用卡支付使用，具体的忘记了。</p>
<p><strong>3.购买主机空间</strong></p>
<p>只有购买了主机空间，将自己博客内容上传到自己的主机之后，才能让别人看到你的博客内容。支付成功之后主机提供商会给你域名的对应IP，同时还有一些其他的信息。</p>
<p><strong>4.域名解析</strong></p>
<p>使用DNSPod进行域名解析。具体步骤为：</p>
<p>1）在DNSPod中添加域名。<br>2）把DNS地址修改为DNSPod。登录自己的GoDaddy账户，点击DOMAINS左边“+”号，选择Manage DNS。将其中Nameservers改为”f1g1ns1.dnspod.net”，”f1g1ns2.dnspod.net”。<br>3）将域名指向主机服务器的ip，即在DNSPod中添加“A记录”。填写完成后如下图。</p>
<p><img src="http://blog.frankge.me/wp-content/uploads/2016/08/the-timeline-of-my-blog_modify-dns-01.png" alt="the-timeline-of-my-blog_modify-dns-01"> <center>修改DNS-01</center></p>
<p><img src="http://blog.frankge.me/wp-content/uploads/2016/08/the-timeline-of-my-blog_modify-dns-02.png" alt="the-timeline-of-my-blog_modify-dns-02"> <center>修改DNS-02</center></p>
<p><img src="http://blog.frankge.me/wp-content/uploads/2016/08/the-timeline-of-my-blog_modify-dns-03.png" alt="the-timeline-of-my-blog_modify-dns-03"> <center>修改DNS-03</center></p>
<p><strong>5.安装wordpress</strong></p>
<p>知乎回答的原文说，不同的主机空间有不同的虚拟主机控制系统，安装的过程也不尽相同，但是步骤都是差不多的。这个具体的我也不太清楚，我的主机空间使用的也是cPanel面板。</p>
<p>1）登录cPanel面板，“数据库”-&gt;“MySQL数据库”，创建一个数据库，然后创建用户，将用户添加进数据库，勾选“所有权限”。</p>
<p><img src="http://blog.frankge.me/wp-content/uploads/2016/08/the-timeline-of-my-blog_install-wordpress-01.png" alt="the-timeline-of-my-blog_install-wordpress-01"> <center>安装wordpress-01</center></p>
<p><img src="http://blog.frankge.me/wp-content/uploads/2016/08/the-timeline-of-my-blog_install-wordpress-02.png" alt="the-timeline-of-my-blog_install-wordpress-02"> <center>安装wordpress-02</center></p>
<p><img src="http://blog.frankge.me/wp-content/uploads/2016/08/the-timeline-of-my-blog_install-wordpress-03.png" alt="the-timeline-of-my-blog_install-wordpress-03"> <center>安装wordpress-03</center></p>
<p><img src="http://blog.frankge.me/wp-content/uploads/2016/08/the-timeline-of-my-blog_install-wordpress-04.png" alt="the-timeline-of-my-blog_install-wordpress-04"> <center>安装wordpress-04</center></p>
<p><img src="http://blog.frankge.me/wp-content/uploads/2016/08/the-timeline-of-my-blog_install-wordpress-05.png" alt="the-timeline-of-my-blog_install-wordpress-05"> <center>安装wordpress-05</center></p>
<p>2）上传WordPress。进入cPanel首页，点击“文件”-&gt;“文件管理器”，选择public_html文件夹，将wordpress文件夹中的文件上传至此文件夹（忽略我下图中的“wordpress”和”blog”文件夹）。</p>
<p><img src="http://blog.frankge.me/wp-content/uploads/2016/08/the-timeline-of-my-blog_install-wordpress-06.png" alt="the-timeline-of-my-blog_install-wordpress-06"> <center>安装wordpress-06</center></p>
<p>3）按照提示设置wordpress的信息。</p>
<p>以上完成之后，就可以在浏览器中输入你的博客地址，进入wordpress的界面了。</p>
<p><strong>6.主题选择</strong></p>
<p>网上有很多免费的wordpress的主题可供选择，当然也有很多收费的，这个根据自己的需求选择。之后的内容都很简单，就不一一写明了。我个人的主题使用的是twenty fifteen。</p>
]]></content>
    
    <summary type="html">
    
      &lt;h3 id=&quot;16-11-21&quot;&gt;&lt;a href=&quot;#16-11-21&quot; class=&quot;headerlink&quot; title=&quot;16.11.21&quot;&gt;&lt;/a&gt;&lt;span style=&quot;color: #0000ff;&quot;&gt;16.11.21&lt;/span&gt;&lt;/h3&gt;&lt;p&gt;将&lt;span st
    
    </summary>
    
      <category term="建站相关" scheme="http://skills.frankge.me/categories/%E5%BB%BA%E7%AB%99%E7%9B%B8%E5%85%B3/"/>
    
    
      <category term="我的博客" scheme="http://skills.frankge.me/tags/%E6%88%91%E7%9A%84%E5%8D%9A%E5%AE%A2/"/>
    
  </entry>
  
</feed>
