﻿<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:trackback="http://madskills.com/public/xml/rss/module/trackback/" xmlns:wfw="http://wellformedweb.org/CommentAPI/" xmlns:slash="http://purl.org/rss/1.0/modules/slash/"><channel><title>C++博客-. . . . . . . . . . . . . . Blog Garden'  C plus plus (My technology Impire!)-文章分类-Algorithm &amp; DataStruct</title><link>http://www.cppblog.com/stevennash/category/2738.html</link><description>................................................................ It‘s a age of economic globalization and Infomation globalization........................................</description><language>zh-cn</language><lastBuildDate>Thu, 22 May 2008 20:04:06 GMT</lastBuildDate><pubDate>Thu, 22 May 2008 20:04:06 GMT</pubDate><ttl>60</ttl><item><title>数据结构复习篇:队列</title><link>http://www.cppblog.com/stevennash/articles/13321.html</link><dc:creator>Technical Consultant</dc:creator><author>Technical Consultant</author><pubDate>Tue, 03 Oct 2006 19:24:00 GMT</pubDate><guid>http://www.cppblog.com/stevennash/articles/13321.html</guid><wfw:comment>http://www.cppblog.com/stevennash/comments/13321.html</wfw:comment><comments>http://www.cppblog.com/stevennash/articles/13321.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/stevennash/comments/commentRss/13321.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/stevennash/services/trackbacks/13321.html</trackback:ping><description><![CDATA[
		<font color="#800080">数据结构复习篇:队列<br /><br /><div align="justify">队列是一种先进先出（FIFO）的线性表。跟栈一样，它们的pop()、push()操作的时间复杂度都为1。同样有两种实现，基于数组的AQueue和链式LQueue的。难点在于基于数组的。为了保证pop()和push()的时间复杂度为1，要用到“循环存储”的思想。这个思想就是把一个固定长度数组看作是一个首尾相接的“圈”。这样，我们的“入队”push()和“出队”pop()操作，就可以直接向队尾加入一个元素或从队首取出一个元素。要在数组中，实现循环存储，需要用到一个小技巧：</div><div>例如，已知数组A长度为100，那么，当队尾为A[99]时，如果再执行一个push()操作（前提是，A[0]没有被队首元素占用），那么A[0]将成为新的队尾，怎么告诉计算机当队尾下标为99时，新加入的元素应该放在下标为0的地方而不是100呢？这里用到一个求余运算，可以解决“下标循环”的问题：</div><div>设数组长度为Len，队尾下标为rear，那么加入一个元素后，新的队尾下标为：</div><div><span>                                   newRear = (rear+1)%Len</span></div><div>还有一点需要注意，因为队列是可以为空的，这个时候，队首与队尾的下标相等，那么当有一元素的时候，队尾下标指向那个元素的后面那个位置，这就是说，队尾下标所指的那个位置，是不存放元素的，所以数组的长度Len应比队列长度queSize大1。</div><div>链式队列很容易理解，我不多说了。</div><div>下面是我按照C＋＋标准库中queue的接口，自己写的代码：</div><div style="BORDER-RIGHT: windowtext 0.5pt solid; PADDING-RIGHT: 5.4pt; BORDER-TOP: windowtext 0.5pt solid; PADDING-LEFT: 5.4pt; BACKGROUND: #e6e6e6; PADDING-BOTTOM: 4px; BORDER-LEFT: windowtext 0.5pt solid; WIDTH: 95%; WORD-BREAK: break-all; PADDING-TOP: 4px; BORDER-BOTTOM: windowtext 0.5pt solid"><div><span style="COLOR: #008000">/*</span><span style="COLOR: #008000"><br />定义队列的共公接口<br />文件名：QueueInterface.h<br /></span><span style="COLOR: #008000">*/</span><span style="COLOR: #000000"><br />#ifndef QUEUEINTERFACK_H<br /></span><span style="COLOR: #0000ff">#define</span><span style="COLOR: #000000"> QUEUEINTERFACK_H</span><span style="COLOR: #000000"><br /><br />#include </span><span style="COLOR: #000000">"</span><span style="COLOR: #000000">NodeInterface.h</span><span style="COLOR: #000000">"</span><span style="COLOR: #000000"><br /></span><span style="COLOR: #0000ff">using</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">namespace</span><span style="COLOR: #000000"> std;<br /></span><span style="COLOR: #0000ff">namespace</span><span style="COLOR: #000000"> zyk<br />{<br /><br />    <br />    template</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> T</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> Queue<br />    {<br />    </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br />        </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">从今天开始,我决定采用STL的接口,<br />        </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">这样有利于我们熟悉标准库函数</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000">        </span><span style="COLOR: #0000ff">virtual</span><span style="COLOR: #000000"> T </span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000"> back() </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;        </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">返回队尾元素</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000">        </span><span style="COLOR: #0000ff">virtual</span><span style="COLOR: #000000"> T </span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000"> front() </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;    </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">返回队首元素    </span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000">        </span><span style="COLOR: #0000ff">virtual</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> pop() </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;        </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">出队</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000">        </span><span style="COLOR: #0000ff">virtual</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> push(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000"> T</span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000">) </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;</span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">进队</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000">        </span><span style="COLOR: #0000ff">virtual</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">bool</span><span style="COLOR: #000000"> empty() </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;    </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">返回值指示队列是否为空 </span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000">        </span><span style="COLOR: #0000ff">virtual</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000"> size() </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;        </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">返回队中元素个数            </span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000">    };<br /><br />    </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">基于数组的队列AQueue</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000">    template</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> T</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> AQueue : Queue</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">T</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br />    {<br />    </span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">:<br />        </span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000"> maxSize;    </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">队列的最大容量,由于采用循环存储的方式,<br />                </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">它比实际值大1,以保证队尾rear所指的位置,<br />                </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">是队尾元素的下一个位置 </span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000">        </span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000"> mfront;    </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">指示队首元素的在数组中的下标</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000">        </span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000"> mrear;    </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">队尾元素的在数组中的下标的下一个位置</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000">        T </span><span style="COLOR: #000000">*</span><span style="COLOR: #000000"> listArray;    </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">数组指针</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000"><br />    </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br />        AQueue(</span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000"> size </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">100</span><span style="COLOR: #000000">)<br />        {<br />            maxSize </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> size </span><span style="COLOR: #000000">+</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">;    </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">这一点很关键</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000">            mfront </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> mrear </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br />            listArray </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> T[maxSize];<br />        }<br />        </span><span style="COLOR: #000000">~</span><span style="COLOR: #000000">AQueue()<br />        {<br />            delete [] listArray;<br />        }<br /><br />        T </span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000"> back()<br />        {<br />            </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">当rear=0里,(rear-1)%maxSize将会成为负-1,而(mrear-1+maxSize)%maxSize可以解决这个问题</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000">            </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> listArray[(mrear </span><span style="COLOR: #000000">-</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">1</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">+</span><span style="COLOR: #000000"> maxSize)</span><span style="COLOR: #000000">%</span><span style="COLOR: #000000">maxSize];    <br />        }<br /><br />        T </span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000"> front()<br />        {<br />            </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> listArray[mfront];<br />        }<br />        <br />        </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> pop()<br />        {<br />            mfront </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> (mfront</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">)</span><span style="COLOR: #000000">%</span><span style="COLOR: #000000">maxSize;<br />        }<br />        </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> push(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000"> T </span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000"> item)<br />        {<br />            listArray[mrear] </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> item;<br />            mrear </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> (mrear</span><span style="COLOR: #000000">+</span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">)</span><span style="COLOR: #000000">%</span><span style="COLOR: #000000">maxSize;<br />        }<br />        </span><span style="COLOR: #0000ff">bool</span><span style="COLOR: #000000"> empty()<br />        {<br />            </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> (mrear </span><span style="COLOR: #000000">==</span><span style="COLOR: #000000"> mfront)<br />                </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">true</span><span style="COLOR: #000000">;<br />            </span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">false</span><span style="COLOR: #000000">;<br />        }<br />        </span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000"> size()<br />        {<br />            </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> (mrear </span><span style="COLOR: #000000">-</span><span style="COLOR: #000000"> mfront </span><span style="COLOR: #000000">+</span><span style="COLOR: #000000"> maxSize)</span><span style="COLOR: #000000">%</span><span style="COLOR: #000000">maxSize;<br />        }<br /><br />    };<br /><br />    </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">链式队列</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000">    template</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> T</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">class</span><span style="COLOR: #000000"> LQueue : Queue</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">T</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"><br />    {<br />    </span><span style="COLOR: #0000ff">private</span><span style="COLOR: #000000">:<br />        </span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000"> queSize;    </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">队元素的个数</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000">        Node</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">T</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">*</span><span style="COLOR: #000000"> pfront;    </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">指向队首元素</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000">        Node</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">T</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">*</span><span style="COLOR: #000000"> prear;    </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">指向队尾元素</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000">    </span><span style="COLOR: #0000ff">public</span><span style="COLOR: #000000">:<br />        LQueue()<br />        {<br />            queSize </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">;<br />            pfront </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> prear </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> NULL;<br />        }<br />        </span><span style="COLOR: #000000">~</span><span style="COLOR: #000000">LQueue()<br />        {<br />            </span><span style="COLOR: #0000ff">while</span><span style="COLOR: #000000"> (pfront </span><span style="COLOR: #000000">!=</span><span style="COLOR: #000000"> NULL)<br />            {<br />                Node</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">T</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">*</span><span style="COLOR: #000000"> tmp;<br />                tmp </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> pfront;<br />                pfront </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> pfront</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">next;<br />                delete tmp;<br />            }<br />        }<br /><br />        T </span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000"> back()<br />        {<br />            </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> prear</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">element;<br />        }<br /><br />        T </span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000"> front()<br />        {<br />            </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> pfront</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">element;<br />        }<br /><br />        </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> pop()<br />        {<br />            Node</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">T</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">*</span><span style="COLOR: #000000"> tmp;<br />            tmp </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> pfront;    <br />            </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> (queSize </span><span style="COLOR: #000000">==</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">1</span><span style="COLOR: #000000">)    </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">只有一个元素.</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000">            {<br />                prear </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> pfront</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">next;<br />            }<br />            pfront </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> pfront</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">next;<br />            delete tmp;            <br />            </span><span style="COLOR: #000000">--</span><span style="COLOR: #000000">queSize;<br />        }<br />        </span><span style="COLOR: #0000ff">void</span><span style="COLOR: #000000"> push(</span><span style="COLOR: #0000ff">const</span><span style="COLOR: #000000"> T </span><span style="COLOR: #000000">&amp;</span><span style="COLOR: #000000"> item)<br />        {<br />            </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> (queSize </span><span style="COLOR: #000000">==</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">)    </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">第一个元素入栈,这时情况比较特殊</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000">            {<br />                pfront </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> prear </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> Node</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">T</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">(item);    </span><span style="COLOR: #008000">//</span><span style="COLOR: #008000">一同指向第一个元素</span><span style="COLOR: #008000"><br /></span><span style="COLOR: #000000">                </span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">queSize;<br />                </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000">;<br />            }<br />            prear</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">next </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">new</span><span style="COLOR: #000000"> Node</span><span style="COLOR: #000000">&lt;</span><span style="COLOR: #000000">T</span><span style="COLOR: #000000">&gt;</span><span style="COLOR: #000000">(item);<br />            prear </span><span style="COLOR: #000000">=</span><span style="COLOR: #000000"> prear</span><span style="COLOR: #000000">-&gt;</span><span style="COLOR: #000000">next;<br />            </span><span style="COLOR: #000000">++</span><span style="COLOR: #000000">queSize;<br />        }<br />        </span><span style="COLOR: #0000ff">bool</span><span style="COLOR: #000000"> empty()<br />        {<br />            </span><span style="COLOR: #0000ff">if</span><span style="COLOR: #000000"> (queSize </span><span style="COLOR: #000000">==</span><span style="COLOR: #000000"> </span><span style="COLOR: #000000">0</span><span style="COLOR: #000000">)<br />                </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">true</span><span style="COLOR: #000000">;<br />            </span><span style="COLOR: #0000ff">else</span><span style="COLOR: #000000"> <br />                </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> </span><span style="COLOR: #0000ff">false</span><span style="COLOR: #000000">;<br />        }<br />        </span><span style="COLOR: #0000ff">int</span><span style="COLOR: #000000"> size()<br />        {<br />            </span><span style="COLOR: #0000ff">return</span><span style="COLOR: #000000"> queSize;<br />        }<br />        <br />    };<br />}<br /><br /></span><span style="COLOR: #0000ff">#endif</span></div></div></font>
<img src ="http://www.cppblog.com/stevennash/aggbug/13321.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/stevennash/" target="_blank">Technical Consultant</a> 2006-10-04 03:24 <a href="http://www.cppblog.com/stevennash/articles/13321.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>案例讨论：不规则树算法</title><link>http://www.cppblog.com/stevennash/articles/13267.html</link><dc:creator>Technical Consultant</dc:creator><author>Technical Consultant</author><pubDate>Tue, 03 Oct 2006 10:54:00 GMT</pubDate><guid>http://www.cppblog.com/stevennash/articles/13267.html</guid><wfw:comment>http://www.cppblog.com/stevennash/comments/13267.html</wfw:comment><comments>http://www.cppblog.com/stevennash/articles/13267.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/stevennash/comments/commentRss/13267.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/stevennash/services/trackbacks/13267.html</trackback:ping><description><![CDATA[
		<a class="f20">案例讨论：不规则树算法</a>
		<br />
		<br />
		<a class="f1">  
<div class="guanggao"><span id="contentAdv"></span></div><p><font face="Verdana">      有如下的数据，parentid表示父节点id，totalchilren表示该节点有几个子节点，total表示数量<br /><table style="BORDER-RIGHT: #cccccc 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: #cccccc 1px dotted; BORDER-LEFT: #cccccc 1px dotted; BORDER-BOTTOM: #cccccc 1px dotted" cellspacing="0" cellpadding="6" width="95%" align="center" border="0"><tbody><tr><td style="WORD-WRAP: break-word" bgcolor="#f3f3f3">id filecode parentid total children total<br />1  ws112           0       3         0<br />2  01              1       1         2<br />3  02              1       1         2<br />4  03              1       1         2<br />5  0101            2       0         3<br />6  0201            3       0         3<br />7  0301            4       0         3<br /></td></tr></tbody></table></font></p><p><font face="Verdana">     我想输入ws112，得到如下的结果：<br />     0101  6（2*3）<br />     0201  6（2*3）<br />     0301  6（2*3）<br />     即不管01、02、03这些节点，直接得到ws112最低级的节点情况，请各位帮忙了。</font></p><p><font face="Verdana">     讨论一：<br /></font></p><p><font face="Verdana"><table style="BORDER-RIGHT: #cccccc 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: #cccccc 1px dotted; BORDER-LEFT: #cccccc 1px dotted; BORDER-BOTTOM: #cccccc 1px dotted" cellspacing="0" cellpadding="6" width="95%" align="center" border="0"><tbody><tr><td style="WORD-WRAP: break-word" bgcolor="#f3f3f3">create table A<br />(<br />   id int,<br />   filecode varchar(10),<br />   parentid int,<br />   totalchildren int,<br />   total int<br />) 
<p><font face="Verdana">insert A select 1,'ws112',0,3,0<br />insert A select 2,'01',1,1,  2<br />insert A select 3,'02',1,1,  2<br />insert A select 4,'03',1,1,  2<br />insert A select 5,'0101',2,0,  3<br />insert A select 6,'0201',3,0,  3<br />insert A select 7,'0301',4,0,  3</font></p><p><font face="Verdana">create Function Find_num(@Code varchar(10))<br />returns @A table(filecode varchar(10),num int)<br />as<br />begin<br /> declare @T table(id int,filecode varchar(10),parentid int,totalchildren int,total int,lev int,num int)<br /> declare @lev int<br /> set @lev=1<br />  insert @T select id,filecode,parentid,totalchildren,total,@lev as lev,@lev as num from A where filecode=@Code<br /> while @@rowcount&gt;0<br /> begin<br />   set @lev=@lev+1<br />   insert @T select A1.id,A1.filecode,A1.parentid,A1.totalchildren,A1.total,@lev,A1.total*T.num  from A A1, (select * from @T where lev=@lev-1) T where T.id=A1.parentid<br /> end <br /> insert @A select T.filecode,T.num from @T T where T.lev=(select top 1 lev from @T order by lev DESC )<br /> return <br />end</font></p><p><font face="Verdana">select * from dbo.Find_num('ws112')</font></p></td></tr></tbody></table></font></p><p><font face="Verdana">      <strong>点评：例子好像只能实现规则的树，应该说，这个例子是特例，其实你的树是一颗不规则的树，叶子的深度可能不一样.你想想实现的目标是：<br />      1、查找到任一节点的全部叶子；<br />      2、然后每一个叶子到目标节点之间的所有节点的total值相乘；</strong><br />       0101  6（2*3）<br />       0201  6（2*3）<br />       0301  6（2*3）<br />    <br />      讨论二：<br /></font><font face="Verdana"><table style="BORDER-RIGHT: #cccccc 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: #cccccc 1px dotted; BORDER-LEFT: #cccccc 1px dotted; BORDER-BOTTOM: #cccccc 1px dotted" cellspacing="0" cellpadding="6" width="95%" align="center" border="0"><tbody><tr><td style="WORD-WRAP: break-word" bgcolor="#f3f3f3">create table A<br />(<br />   id int,<br />   filecode varchar(10),<br />   parentid int,<br />   totalchildren int,<br />   total int<br />) 
<p><font face="Verdana">insert A select 1,'ws112',0,3,0<br />insert A select 2,'01',1,1,  2<br />insert A select 3,'02',1,1,  2<br />insert A select 4,'03',1,1,  2<br />insert A select 5,'0101',2,0,  3<br />insert A select 6,'0201',3,0,  3<br />insert A select 7,'0301',4,0,  3<br />insert A select 8,'04',1,0,5</font></p><p><font face="Verdana">create function List_Leaf(@filecode varchar(10))<br />returns @LeafDetail table(filecode varchar(10),num int)<br />As<br />begin<br />declare @TempTable table(id int, filecode varchar(10),parentid int,totalchildren int,total int,lev int,num int)<br />declare @level int<br />set @level = 0<br />insert @TempTable select *,@level,1 from A where filecode = @filecode<br />while @@RowCount&gt;0<br />begin<br />set @level = @level + 1<br />insert @TempTable select A.*,@level,A.total*(T.num) from @TempTable T,A where T.lev = @level-1 and A.parentid = T.id <br />end<br />insert @LeafDetail select filecode,num  from @TempTable where totalchildren  = 0<br />return <br />end</font></p><p><font face="Verdana">select * from List_Leaf('ws112')<br />go</font></p><p><font face="Verdana">测试结果：<br />filecode   num         <br />---------- ----------- <br />04         5<br />0101       6<br />0201       6<br />0301       6</font></p><p><font face="Verdana">（所影响的行数为 4 行）</font></p></td></tr></tbody></table></font></p><p><font face="Verdana">      <strong>点评：办法实现了需要的功能,不过,用了两个临时表,效率方面让人有点不满意.<br /></strong></font><font face="Verdana"><br />     讨论三：</font></p><p></p><table style="BORDER-RIGHT: #cccccc 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: #cccccc 1px dotted; BORDER-LEFT: #cccccc 1px dotted; BORDER-BOTTOM: #cccccc 1px dotted" cellspacing="0" cellpadding="6" width="95%" align="center" border="0"><tbody><tr><td style="WORD-WRAP: break-word" bgcolor="#f3f3f3"><p>create table filedir<br />(<br />   id int,<br />   filecode varchar(10),<br />   pid int,<br />   totalchildren int,<br />   total int<br />)<br />insert filedir select 1,'ws112',0,3,0<br />insert filedir select 2,'01',1,1,  2<br />insert filedir select 3,'02',1,1,  2<br />insert filedir select 4,'03',1,1,  2<br />insert filedir select 5,'0101',2,0,  3<br />insert filedir select 6,'0201',3,0,  3<br />insert filedir select 7,'0301',4,0,  3<br />insert filedir select 8,'0401',1,0,  2<br />go</p><p>--创建用户定义函数<br />create function f_getChild(@ID VARCHAR(10))<br />returns @t table(ID VARCHAR(10),PID VARCHAR(10),Level INT)<br />as<br />begin<br />    declare @i int,@ret varchar(8000)<br />    set @i = 1<br />    insert into @t select ID,pid,@i from filedir where pid = @ID<br />    <br />    while @@rowcount&lt;&gt;0<br />    begin<br />        set @i = @i + 1<br />        <br />        insert into @t <br />        select <br />            a.ID,a.PID,@i <br />        from <br />            filedir a,@t b <br />        where <br />            a.PID=b.ID and b.Level = @i-1<br />    end<br />    return<br />end<br />go</p><p>create   function  f_getparenttotal(@id int,@topid int)<br />returns int<br />as<br />begin<br />declare   @pid   int<br />declare   @re    int<br />set @re=1<br />select   @pid=pid   from   filedir   where   id=@id<br />while    @pid&gt;@topid<br />begin<br />select   @pid=pid,@re=@re*[total]   from   filedir   where   id=@pid<br />end<br />return @re<br />end<br />go</p><p>--执行查询,dbo.f_getparenttotal(id,1)和f_getChild(1)代表根节点id</p><p>select id,filecode,bb=dbo.f_getparenttotal(id,1)*total from filedir  where id in( select ID from  dbo.f_getChild(1) where id not in(select pid from filedir))</p><p>go</p><p>drop function f_getparenttotal<br />drop function f_getChild<br />drop table filedir</p></td></tr></tbody></table><p>      <strong>点评：此办法考虑到了功能的实现和执行的效率问题，但这是SQL Server2000的传统思维，下面介绍一下SQL Server 2005在这方面的应用：</strong></p><p></p><table style="BORDER-RIGHT: #cccccc 1px dotted; TABLE-LAYOUT: fixed; BORDER-TOP: #cccccc 1px dotted; BORDER-LEFT: #cccccc 1px dotted; BORDER-BOTTOM: #cccccc 1px dotted" cellspacing="0" cellpadding="6" width="95%" align="center" border="0"><tbody><tr><td style="WORD-WRAP: break-word" bgcolor="#f3f3f3"><p>--SQL Sever 2005 用(公共表表达式,实现递归方法)如下:</p><p>--测试环境<br />create table A<br />(<br />   id int,<br />   filecode varchar(10),<br />   parentid int,<br />   totalchildren int,<br />   total int<br />)<br />insert A select 1,'ws112',0,3,0<br />insert A select 2,'01',1,1,  2<br />insert A select 3,'02',1,1,  2<br />insert A select 4,'03',1,1,  2<br />insert A select 5,'0101',2,0,  3<br />insert A select 6,'0201',3,0,  3<br />insert A select 7,'0301',4,0,  3<br />insert A select 8,'04',1,0,5</p><p>--建递归CTE<br />DECLARE @FILECODE AS VARCHAR(20)<br />SET @FILECODE='ws112';<br />WITH ACTE(ID,FILECODE,PARENTID,TOTALCHILDREN,TOTAL,LVL)<br />AS<br />( <br />SELECT ID,FILECODE,PARENTID,TOTALCHILDREN,TOTAL,0<br />FROM A WHERE FILECODE=@FILECODE<br />UNION ALL<br />SELECT TA.ID,TA.FILECODE,TA.PARENTID,TA.TOTALCHILDREN,TA.TOTAL,TB.LVL+1<br />FROM A TA INNER JOIN ACTE TB<br />    ON TA.PARENTID=TB.ID<br />)<br />SELECT FILECODE,值=TOTAL*LVL FROM ACTE WHERE TOTALCHILDREN=0<br />--结果<br />/*<br />FILECODE   值<br />---------- -----------<br />04         5<br />0301       6<br />0201       6<br />0101       6</p><p>(4 行受影响)<br />*/<br />--删除环境 Drop table A</p></td></tr></tbody></table></a>
<img src ="http://www.cppblog.com/stevennash/aggbug/13267.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/stevennash/" target="_blank">Technical Consultant</a> 2006-10-03 18:54 <a href="http://www.cppblog.com/stevennash/articles/13267.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>SQL与最短路径算法</title><link>http://www.cppblog.com/stevennash/articles/13261.html</link><dc:creator>Technical Consultant</dc:creator><author>Technical Consultant</author><pubDate>Tue, 03 Oct 2006 10:40:00 GMT</pubDate><guid>http://www.cppblog.com/stevennash/articles/13261.html</guid><wfw:comment>http://www.cppblog.com/stevennash/comments/13261.html</wfw:comment><comments>http://www.cppblog.com/stevennash/articles/13261.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/stevennash/comments/commentRss/13261.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/stevennash/services/trackbacks/13261.html</trackback:ping><description><![CDATA[
		<a class="f20">SQL与最短路径算法</a>
		<br />
		<br />
		<a class="f1">  
<div class="guanggao"><span id="contentAdv"></span></div><p>　　SQL与最短路径算法</p><p>　　题目:空间有若干个点，每个点之间的联系都是随机的，现求任意一个点(设为A)到另一任意点(设为Z)之间间隔最少其他点的最佳算法(可用SQL数据库)</p><p>　　约束:在一个点中只可以直接找出和它有直接联系的点</p><p>　　用途:通过朋友列表以最快的速度认识一个认识的人(MM/GG)</p><p>　　比如5的好友列表中有1，30，3</p><p>　　7的好友列表中有9，5，8</p><p>　　10的好友列表中有7，21，30</p><p>　　11的好友列表中有7，5，30</p><p>　　21的好友列表中有7，30，66</p><p>　　30的好友列表中有21，88，99</p><p>　　如果5要和7交朋友，则可通过5-11-7。而5-30-21-7是较长的路径。</p><p>　　各位大虾有什么绝招能在SQL里实现这算法?</p><p>　　--如果全部建立双向关联，可以试试看下面的语句</p><p>declare @t table<br />(<br />id int,<br />f_id varchar(20)<br />)<br />insert into @t<br />select 5,'1,7,30,3' union all<br />select 7,'11,21,9,5,8' union all<br />select 11,'7,21,30' union all<br />select 21,'7,11,30,66' union all<br />select 30,'5,11,21,88,99'<br />--select * from @t<br />declare @start int<br />declare @end int<br />declare @node int<br />declare @count int<br />declare @result varchar(100)<br />set @count=0<br />set @start=5<br />set @end=11<br />set @result=''<br />declare @tmp table<br />(<br />id int,<br />f_id varchar(20),<br />step int<br />)<br />insert into @tmp select @start,'',@count<br />while @end not in (select id from @tmp)<br />begin<br />set @count=@count+1<br />insert into @tmp<br />select distinct a.id,a.f_id,@count from @t a,@tmp b where charindex(rtrim(b.id),a.f_id)&gt;0 and a.id not in (select id from @tmp)<br />end<br />select @result=rtrim(@count)+':'+rtrim(@end)<br />while @count&gt;1<br />begin<br />set @count=@count-1<br />select top 1 @end=id from @tmp where step=@count and charindex(rtrim(@end),f_id)&gt;0<br />select @result=rtrim(@count)+':'+rtrim(@end)+'/'+@result<br />end<br />select @result='0:'+rtrim(@start)+'/'+@result<br />select @result</p><p><br />/*<br />0:5/1:7/2:11<br />*/<br />点评：上面的方法的缺点是不能列出所有的路径，只能列出最短路径其中一条</p><p><br />5的列表中没有7，是不是可以认为5不认识7，那么5也不认识11，谈何5-11-7是最短路径？</p><p>--按照你说的逻辑，步骤如下</p><p>--1.建立查询函数<br />CREATE  FUNCTION dbo.F_RouteSearch<br />(<br /> @START INT,<br /> @END INT<br />)<br />RETURNS VARCHAR(200)<br />AS<br />BEGIN<br />DECLARE @NODE INT<br />DECLARE @COUNT INT<br />DECLARE @RESULT VARCHAR(100)<br />SET @COUNT=0<br />SET @RESULT=''<br />DECLARE @TMP TABLE<br />(<br />ID INT,<br />F_ID VARCHAR(20),<br />STEP INT<br />)<br />INSERT INTO @TMP SELECT @START,(SELECT F_ID FROM LIST WHERE ID=@START),@COUNT<br />WHILE @END NOT IN (SELECT ID FROM @TMP)<br />BEGIN<br />SET @COUNT=@COUNT+1<br />INSERT INTO @TMP<br />SELECT DISTINCT a.ID,a.F_ID,@COUNT FROM List a,@TMP b WHERE CHARINDEX(','+RTRIM(a.ID)+',',','+b.F_ID+',')&gt;0 and a.ID not in (SELECT ID FROM @TMP)<br />IF @@ROWCOUNT=0<br />BEGIN<br />SELECT @RESULT='NO ROUTE FIND'<br />GOTO RETURNHANDLE<br />END<br />END<br />SELECT @RESULT=RTRIM(@COUNT)+':'+RTRIM(@END)<br />WHILE @COUNT&gt;1<br />BEGIN<br />SET @COUNT=@COUNT-1<br />SELECT TOP 1 @END=ID FROM @TMP WHERE STEP=@COUNT AND CHARINDEX(','+RTRIM(@END)+',',','+F_ID+',')&gt;0<br />SELECT @RESULT=RTRIM(@COUNT)+':'+RTRIM(@END)+'→'+@RESULT<br />END<br />SELECT @RESULT='0:'+RTRIM(@START)+'→'+@RESULT<br />RETURNHANDLE:<br />RETURN @RESULT<br />END<br />GO</p><p>--准备测试数据（与LZ提供数据相同）<br />insert into list<br />select 5,'1,30,3' union all<br />select 7,'9,5,8' union all<br />select 10,'7,21,30' union all<br />select 11,'7,5,30' union all<br />select 21,'7,66,30' union all<br />select 30,'21,88,99'<br />go<br />--测试</p><p>select dbo.F_RouteSearch(5,7) --从5开始，到7为止</p><p>--结果<br />/*<br />0:5→1:30→2:21→3:7<br />注解<br />5通过30，21最后找到7，耗费3步完成<br />5不认识11，因此LZ所说的路径5-11-7不成立<br />*/</p><p>--List表生成脚本</p><p>CREATE TABLE [List] (<br /> [id] [int] NULL ,<br /> [f_id] [varchar] (40) COLLATE Chinese_PRC_CI_AS NULL <br />) ON [PRIMARY]<br />GO</p></a>
<img src ="http://www.cppblog.com/stevennash/aggbug/13261.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/stevennash/" target="_blank">Technical Consultant</a> 2006-10-03 18:40 <a href="http://www.cppblog.com/stevennash/articles/13261.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>