﻿<?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++博客-C++/OpenGL-随笔分类-数据结构</title><link>http://www.cppblog.com/hwj/category/19185.html</link><description /><language>zh-cn</language><lastBuildDate>Tue, 01 May 2012 06:39:31 GMT</lastBuildDate><pubDate>Tue, 01 May 2012 06:39:31 GMT</pubDate><ttl>60</ttl><item><title>链表</title><link>http://www.cppblog.com/hwj/archive/2012/04/29/173160.html</link><dc:creator>有间客栈</dc:creator><author>有间客栈</author><pubDate>Sun, 29 Apr 2012 09:40:00 GMT</pubDate><guid>http://www.cppblog.com/hwj/archive/2012/04/29/173160.html</guid><wfw:comment>http://www.cppblog.com/hwj/comments/173160.html</wfw:comment><comments>http://www.cppblog.com/hwj/archive/2012/04/29/173160.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/hwj/comments/commentRss/173160.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/hwj/services/trackbacks/173160.html</trackback:ping><description><![CDATA[<div align="left"><span style="color: blue">链表概述</span></div>
<div align="left"><span style="color: blue"></span></div>
<div align="left">&nbsp;&nbsp;&nbsp;&nbsp; 链表是一种常见的重要的数据结构。它是动态地进行存储分配的一种结构。它可以根据需要开辟内存单元。链表有一个<span>&#8220;头指针&#8221;变量，以head表示，它存放一个地址。该地址指向一个元素。链表中每一个元素称为&#8220;结点&#8221;，每个结点都应包括两个部分：一为用户需要用的实际数据，二为下一个结点的地址。因此，head指向第一个元素：第一个元素又指向第二个元素；&#8230;&#8230;，直到最后一个元素，该元素不再指向其它元素，它称为&#8220;表尾&#8221;，它的地址部分放一个&#8220;NULL&#8221;（表示&#8220;空地址&#8221;），链表到此结束。</span></div>
<div align="left"><span></span></div>
<div align="left"><span style="color: blue">单向链表</span></div>
<div align="left"><span style="color: blue"></span></div>
<div>&nbsp;&nbsp;&nbsp;&nbsp; 单向链表的每个结点中除<span style="color: red"><font color="#000000"><font color="#ff0000">信息域</font>以外还有一个<span style="color: red">指针域</span>，用来指出其后续结点，单向链表的最后一个结点的指针域为<span style="color: red">空</span>(NULL)。单向链表由头指针唯一确定，因此单向链表可以用头指针的名字来命名，例如头指针名为head的单向链表称为表head，头指针指向单向链表的第一个结点。在用C语言实现时，首先说明一个结构类型，在这个结构类型中包含一个(或多个)信息成员以及一个指针成员</font><font color="#000000">：</font></span></div>
<div>&nbsp;</div>
<div align="left">#define NULL 0</div>
<div align="left">typedef int DATATYPE</div>
<div align="left">typedef struct <span style="color: red">node</span></div>
<div align="left">{DATATYPE info；</div>
<div align="left">node *next;</div>
<div align="left">}<span style="color: blue">LINKLIST;</span></div>
<div>&nbsp;</div>
<div align="left">&nbsp;&nbsp;&nbsp;&nbsp; 链表结构中包含指针型的结构成员，类型为指向相同结构类型的指针。根据<span>C语<br />言的语法要求，结构的成员不能是结构自身类型，即结构不能自己定义自己，因为这样将导致一个无穷的递归定义，但结构的成员可以是结构自身的指针类型，通过指针引用自身这种类型的结构。</span></div>
<div align="left">&nbsp;&nbsp;&nbsp;&nbsp; 链表的每个结点是<span style="color: blue">lINKIST<font color="#000000">结构类型的一个变量。例如定义了个链表的头指针head<br />和两个指向链表结点的指针p，q：</font></span></div>
<div align="left">&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; LINKLIST *head,*P，<span>*q;</span></div>
<div align="left">&nbsp;&nbsp;&nbsp;&nbsp; 根据结构成员的引用方法，当<span>p和q分别指向了链表的确定结点后，P-&gt;info和p-&gt;next分别是某个结点的信息分量和指针分量，LINKLIST结构的信息分量是整型，可以用常规的方法对这两个结点的信息分量分别赋值：</span></div>
<div align="left">p-＞<span>info＝20;<br />q-＞inFo＝30;</span></div>
<div>&nbsp;&nbsp;&nbsp;&nbsp; 指针分量是指向<span>LINKLIST类型变量的指针，指针中将存储链表的下一个结点的存储首地址，在链表尾部的最后一个结点的指针域中，指针的值为空(NULL)。</span></div>
<div>&nbsp;</div>
<table style="width: 101%" cellpadding="0" width="101%" border="0">
<tbody>
<tr>
<td style="padding-right: 0.75pt; padding-left: 0.75pt; padding-bottom: 0.75pt; width: 54%; padding-top: 0.75pt" width="54%">
<div align="left">head＝<span>p;</span></div>
<div align="left">p-＞<span>next＝q；</span></div>
<div align="left">q-＞<span>next＝NULL;</span></div>
<div align="left">&nbsp;&nbsp;&nbsp;&nbsp; 经上列的赋值后，组成右图的一个链表。</div></td>
<td style="padding-right: 0.75pt; padding-left: 0.75pt; padding-bottom: 0.75pt; width: 47%; padding-top: 0.75pt" width="47%">
<div align="left"><img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/bingwen0210/a13e142cf8bc4ffeb5e248f228188857.gif" /></div></td></tr></tbody></table>
<div>&nbsp;</div>
<div sizcache="1" sizset="33"><a name="lianbiao"><span style="color: black">下面将以上述链表结点结构为例，给出单向链表的几种算法。</span></a></div>
<div>&nbsp;</div>
<div sizcache="1" sizset="34"><a name="jianli"><span style="color: fuchsia">建立单向链表</span></a></div>
<div>&nbsp;</div>
<div align="left">&nbsp;&nbsp;&nbsp;&nbsp; 建立单向链表的算法写成为函数<span style="color: red">create()<font color="#000000">，该函数将顺序输人的一组数构造为一个首尾相接的单向链表，为将新结点放在当前链表的尾部，函数中定义了个尾指针<span style="color: red">tail</span>，使其一直指向当前链表的尾结点。<br /><br />例：建立单向链表的函数。 </font></span></div>
<div align="left">LINKLIST *create() </div>
<div align="left">{DATATYPE data;</div>
<div align="left">LINKLIST *head, *tail,*node;</div>
<div align="left">head＝<span>new(LINKLIST)；</span></div>
<div align="left">tail=head;</div>
<div align="left">scanf("%d",&amp;data);</div>
<div align="left">while(data!=0);</div>
<div align="left">{node=new(LINKLIST);</div>
<div align="left">&nbsp;&nbsp; node-&gt;info=data;</div>
<div align="left">&nbsp;&nbsp; tail-&gt;next=node;</div>
<div align="left">&nbsp;&nbsp; tail=node;</div>
<div align="left">&nbsp;&nbsp; scanf("%d",&amp;data);</div>
<div align="left">}<br /><br />tail-&gt;next=NULL;</div>
<div align="left">return head;</div>
<div>}</div>
<div>&nbsp;</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp; 在函数中首先为<span>Head申请了&#8212;个所指向的结点，该结点称为链表的首结点。开始链表的头指针和尾指针都指向头结点(见上图)，以后每输入一个数则申请一个结点，将输入的数放到结点的信息域后，由语句<span style="color: red">tail-&gt;next</span><span style="color: red">＝node</span>将该结点链接在链表的尾部。输入结束后，置链表最后一个结点的指针域为空，返回链表头指针。</span></div>
<div>&nbsp;</div>
<div sizcache="1" sizset="35"><a name="charu"><span style="color: fuchsia">单向链表中插入结点</span></a></div>
<div>&nbsp;</div>
<div><strong><span style="color: fuchsia">&nbsp;&nbsp;</span></strong> 在单向链表中插入一个结点要引起插入位置前面结点的指针的变化、下图表示了向一个单向链表插人结点时指针的变化情况，虚线所示为变化后的指针。<span> <img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/bingwen0210/66369f3f9f0a429b90f50249565780ab.gif" /><br />例：在单向链表的p结点后面插入一个信息域的值为x的新结点。</span></div>
<div>&nbsp;&nbsp;&nbsp;&nbsp; void insert(LINKLIST*p, DATATYPE x)<br />&nbsp;&nbsp;&nbsp;&nbsp; {LINKLIST *newp＝<span>new(LINKLIST);<br />&nbsp;&nbsp;&nbsp;&nbsp; newp-＞info＝x;<br />&nbsp;&nbsp;&nbsp;&nbsp; newp-＞next＝p-＞next;<br />&nbsp;&nbsp;&nbsp;&nbsp; p-＞next＝newp;<br />&nbsp;&nbsp;&nbsp;&nbsp; }</span></div>
<div>&nbsp;</div>
<div>&nbsp;&nbsp;&nbsp;&nbsp; 在插入一个结点时首先要由<span>new(LINKLIST)向系统申请一个存储LINKLIST类型变量的空间，并将该空间的首地址赋给指向新结点的指针newp，在为该新结点的信息域赋值后，先要将该结点插入位置后面一个结点的指针赋给该结点的指针域，然后才能将指向该结点的指针赋给其前一个结点的指针域，这样来完成上图的插入过程。</span></div>
<div>&nbsp;</div>
<div><strong><span style="color: fuchsia">单向链表中删除结点</span></strong></div>
<div><strong>&nbsp;</strong></div>
<div style="text-indent: 21.75pt">在单向链表中删除个结点同样要引起删除结点的前面结点的指针的变化，下图形象地表示了从单向链表中删除一个结点时指针的变化情况，虚线所示为变化后的指针。<span> <img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/bingwen0210/d920644b90ca46f392f833975d13afa8.gif" /><br />例：删除单向链表结点*p后面结点。</span></div>
<div style="text-indent: 21.75pt">&nbsp;</div>
<div style="text-indent: 21.75pt">&nbsp;void delete(LINKLIST *p) <br />&nbsp;&nbsp;&nbsp;&nbsp; {LINKKLIST *temp；<span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; temp＝p-＞next；<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; p-＞next=P-＞next-＞next；<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; delet(temp)；<br />&nbsp;&nbsp;&nbsp;&nbsp; }<br /><br /></span></div>
<div style="text-indent: 21.75pt">将指向被删除结点的指针保存在一个同类型的指针变量中，然后将其前一个结点的指针调整到指向该结点的后一个结点，最后将被删除的结点释放给系统。</div>
<div style="text-indent: 21.75pt">&nbsp;</div>
<div style="text-indent: 21.75pt"><strong><span style="color: fuchsia">遍历链表</span></strong></div>
<div style="text-indent: 21.75pt"><strong>&nbsp;</strong></div>
<div style="text-indent: 21.75pt">由于链表是一个动态的数据结构，链表的各个结点由指针链接在起，访问链表元素时通过每个链表结点的指针逐个找到该结点的下一个结点，<span>&#8212;直找到链表尾，链表的最后一个结点的指针为空。<br />例：编历链表函数。</span></div>
<div style="text-indent: 21.75pt">&nbsp;</div>
<div style="text-indent: 21.75pt">&nbsp;void outputlist(LINKLIST *head)<br />&nbsp;&nbsp;&nbsp;&nbsp; LINKLIST *current＝<span>head-＞next;<br />&nbsp;&nbsp;&nbsp;&nbsp; while(current！＝NULL)<br />&nbsp;&nbsp;&nbsp;&nbsp; {printf("%d/n",current-&gt;info);</span></div>
<div align="left">&nbsp;&nbsp;&nbsp; current=current-&gt;next;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; }<br />&nbsp;&nbsp;&nbsp;&nbsp; return;<br />&nbsp;&nbsp;&nbsp;&nbsp; } </div>
<div style="text-indent: 21.75pt">&nbsp;</div>
<div style="text-indent: 21.75pt">&nbsp;</div>
<div align="left"><strong><span style="color: blue">双向链表 </span></strong></div>
<div align="left">&nbsp;&nbsp;&nbsp;&nbsp; 每个结点中只包括一个指向下个结点的指针域，这种链表称为单向链表。如果要在单向链表一个指针所指的当前位置插入一个新结点，就必须从链表头指针开始逐个遍历直到当前指针所指结点的前一结点，修改这个结点的指针。双向链表的每个结点中包括两个指针域，分别指向该结点的前一个结点和后一个结点。在双向链表中由任何一个结点都很容易找到其前面的结点和后面的结点，而不需要在上述的插入<span>(及删除)操作中由头结点开始寻找。定义双向链表的结点结构为</span></div>
<div align="left">typedef struct node</div>
<div align="left">{ DATATYPE info；</div>
<div align="left">node *priv, *next;</div>
<div align="left">}DINKLIST；</div>
<div align="left">&nbsp;&nbsp;&nbsp;&nbsp; 下面给出双向链表中插入删除一个结点的函数。操作过程见下图：</div>
<div align="left"><img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/bingwen0210/d742699ccf854e84880ad4a007aba5c2.gif" /></div>
<div align="left">&nbsp;&nbsp;&nbsp;&nbsp; 例<span>:将一个结点插入到双向链表指定结点之后。</span></div>
<div align="left">insertafter(DINKLIST *current，<span>DINKLIST *new) </span></div>
<div align="left">{new-&gt;next=current-&gt;next; </div>
<div align="left">new-＞<span>priv＝current; </span></div>
<div align="left">current-＞<span>next-＞priv＝new ; </span></div>
<div align="left">current-＞<span>next-＞new; </span></div>
<div align="left">} </div>
<div align="left">&nbsp;&nbsp;&nbsp;&nbsp; 例<span>:将一个结点插入到双向链表指定结点之前。 </span></div>
<div align="left">insertbefor(DINKLIST *current，<span>DINKLIST *new) </span></div>
<div align="left">{new-＞<span>next＝current; </span></div>
<div align="left">new-&gt;priv=current-&gt;priv;　 </div>
<div align="left">current-＞<span>priv=current-&gt;priv ; </span></div>
<div align="left">current-＞<span>priv=new; </span></div>
<div align="left">} </div>
<div align="left">&nbsp;&nbsp;&nbsp;&nbsp; 例<span>:在双向链表中删除一个指定结点。 </span></div>
<div align="left">deleteelement(DINKLIST *current) </div>
<div align="left">{current-＞<span>next-&gt;priv=current-&gt;priv ; </span></div>
<div align="left">current-＞<span>priv-&gt;next=current-&gt;next; </span></div>
<div align="left">delete(current); </div>
<div align="left">} </div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div>&nbsp;</div>
<div><strong><font size="4"><span style="font-size: 10.5pt; color: blue">循环链表</span></font></strong></div>
<div><span style="font-size: 10.5pt">&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size: 10.5pt">单向链表的最后一个结点的指针域为空（NULL）。如果将这个指针里利用起来，以指向单向链表的第一个结点，就组成一个单向循环链表。如下图所示： <img alt="" src="http://p.blog.csdn.net/images/p_blog_csdn_net/bingwen0210/3aa3cdd24bf4445fb47d433e50899daa.gif" /></span></div>
<div><span style="font-size: 10.5pt">&nbsp;&nbsp;&nbsp;&nbsp; </span><span style="font-size: 10.5pt">对双向链表做类似的处理可构造一个双向循环链表。 </span></div><img src ="http://www.cppblog.com/hwj/aggbug/173160.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/hwj/" target="_blank">有间客栈</a> 2012-04-29 17:40 <a href="http://www.cppblog.com/hwj/archive/2012/04/29/173160.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>表达式的前后缀表达形式 </title><link>http://www.cppblog.com/hwj/archive/2012/04/24/172629.html</link><dc:creator>有间客栈</dc:creator><author>有间客栈</author><pubDate>Tue, 24 Apr 2012 09:19:00 GMT</pubDate><guid>http://www.cppblog.com/hwj/archive/2012/04/24/172629.html</guid><wfw:comment>http://www.cppblog.com/hwj/comments/172629.html</wfw:comment><comments>http://www.cppblog.com/hwj/archive/2012/04/24/172629.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/hwj/comments/commentRss/172629.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/hwj/services/trackbacks/172629.html</trackback:ping><description><![CDATA[<div class="article_content" id="article_content">35,15,+,80,70,-,*,20,/&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //后缀表达方式<br /><br />(((35+15)*(80-70))/20）=25 //中缀表达方式 <br /><br />/,*,+,35,15,-,80,70, 20&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; //前缀表达方式 <br /><br />人的思维方式很容易固定~~！正如习惯拉10进制。就对2，3，4，8，16<br />等进制不知所措一样~~！<br /><br />人们习惯的运算方式是中缀表达式。而碰到前缀，后缀方式。。迷茫<br />其实仅仅是一种表达式子的方式而已（不被你习惯的方式）<br />这里教你一种也许你老师都没跟你讲的简单转换方式<br /><br />一个中缀式到其他式子的转换方法~~<br />这里我给出一个中缀表达式~<br />a+b*c-(d+e)<br />第一步：按照运算符的优先级对所有的运算单位加括号~<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 式子变成拉：((a+(b*c))-(d+e))<br />第二步：转换前缀与后缀表达式<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 前缀：把运算符号移动到对应的括号前面<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 则变成拉：-( +(a *(bc)) +(de))<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 把括号去掉：-+a*bc+de&nbsp; 前缀式子出现<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 后缀：把运算符号移动到对应的括号后面<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 则变成拉：((a(bc)* )- (de)+ )-<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 把括号去掉：abc*-de+-&nbsp; 后缀式子出现<br />发现没有，前缀式，后缀式是不需要用括号来进行优先级的确定的。<br /><br />如果你习惯了他的运算方法。计算的时候也就是从两个操作数的前面<br />或者后面找运算符。而不是中间找，那么也就直接可以口算了<br /></div><img src ="http://www.cppblog.com/hwj/aggbug/172629.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/hwj/" target="_blank">有间客栈</a> 2012-04-24 17:19 <a href="http://www.cppblog.com/hwj/archive/2012/04/24/172629.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>最小生成树 Prim and Kruskal算法</title><link>http://www.cppblog.com/hwj/archive/2012/04/23/172497.html</link><dc:creator>有间客栈</dc:creator><author>有间客栈</author><pubDate>Mon, 23 Apr 2012 13:23:00 GMT</pubDate><guid>http://www.cppblog.com/hwj/archive/2012/04/23/172497.html</guid><wfw:comment>http://www.cppblog.com/hwj/comments/172497.html</wfw:comment><comments>http://www.cppblog.com/hwj/archive/2012/04/23/172497.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/hwj/comments/commentRss/172497.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/hwj/services/trackbacks/172497.html</trackback:ping><description><![CDATA[<p><span style="font-size: 15px"><strong>Prim 算法思想：</strong></span></p>
<p>从任意一顶点 v0 开始选择其最近顶点 v1 构成树 T1，再连接与 T1 最近顶点 v2 构成树 T2， 如此重复直到所有顶点均在所构成树中为止。<br /><span style="font-size: 16px"><strong>Prim 算法步骤：</strong></span><br />T0 存放生成树的边，初值为空<br />输入加权图的带权邻接矩阵 C = (Cij)n&#215;n (两点间无边相连则其大小为无穷)<br />为每个顶点 v 添加一属性 L(v) ：表 v 到 T0 的最小直接距离<br />1) T0&#8592;&#8709;, V1={v0}, C(T0)=0<br />2) 对任意v &#8712; V，L(v)&#8592;C(v, v0)<br />3) If V==V1 then stop else goto next.<br />4) 在 V-V1 中找点 u 使 L(u) =min{ L(v) | v &#8712; (V &#8722; V1 )},记 V1 中与 u 相邻点为 w.<br />5) T0&#8592;T0&#8746;{(u, w)}, C(T0) &#8592;C(T0)+C(u, w), V1&#8592;V1&#8746;{u}<br />6) 对任意v &#8712; (V &#8722; V1 ) if C(v, u)&lt;L(v) then L(v) = C(v, u) else L(v)不变。<br />7) Go to 3.<br /><br /></p>
<div id="cnblogs_post_body">
<h2><strong>Kruskal</strong><strong>算法思想：</strong></h2>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 把n个顶点看成看成n棵分离的树（每棵树只有一个顶点），每次选取可连接两个分离树中权值最小的边把两个分离的树合成一个新的树取代原来的两个分离树，如果重复n-1步后便得到最小生成树。</p>
<h2><strong>Kruskal</strong><strong>算法步骤：</strong></h2>
<p><strong>T<sub>0</sub></strong>存放生成树的边，初值为空</p>
<p><strong>C(T<sub>0</sub>) </strong>最小生成树的权，初值为0</p>
<p><strong>VS </strong>分离树顶点的集合，初值为 { {v<sub>1</sub>} {v<sub>2</sub>} &#8230; {v<sub>n</sub>} }</p>
<p><strong>A B W</strong>分别为边的顶点和权值数组，由用户输入</p>
<p>1)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; T<sub>0</sub>&#8592;0, C(T<sub>0</sub>)&#8592;0, VS&#8592;{ {v<sub>1</sub>} {v<sub>2</sub>} &#8230; {v<sub>n</sub>} }, A, B, W按W排序后构成队列Q</p>
<p>2)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; If n(VS)==1 then stop else goto 3</p>
<p>3)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 取Q第一组数组(u, v, w) 并从Q中将其删除.</p>
<p>4)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; If u, v 属于同一个集合 then goto 3 else 分属两个集合X, Y, goto 5.</p>
<p>5)&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; T<sub>0</sub>&#8592;T<sub>0</sub>&#8746;(u, v), C(T<sub>0</sub>)&#8592;C(T<sub>0</sub>)+w, VS&#8592;VS-X-Y+X&#8746;Y goto 2.</p>
<p>&nbsp;</p>
<h2><strong>Kruskal</strong><strong>算法证明：</strong></h2>
<p>树定义：无圈连通图。</p>
<p>引理1：一个图是树 等价于 一个图无圈且任意不相关联的顶点u, v ，图G+(u, v)则必存在唯一一个圈。</p>
<p>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp; 设由Kruskal算法生成的T<sub>0</sub>序列为e<sub>1, </sub>e<sub>2,</sub> e<sub>3 </sub>&#8230; e<sub>v-1</sub>，假设其不是最小生成树。任意最小生成树T定义函数f(T)：T<sub>0</sub>中不存在于T中边在T<sub>0</sub>的下标。设T<sub>1</sub>是使f(T)最大的变量，设f(T<sub>1</sub>)=k，即e<sub>k</sub>不存在于T<sub>1</sub>中，T<sub>1</sub>为树且e<sub>k</sub>不在T<sub>1</sub>中，所以由引理1得T<sub>1</sub>+e<sub>k</sub>必存在圈C，C上必有e<sup>,</sup><sub>k </sub>&#8800;e<sub>k</sub>，e<sup>,</sup><sub>k</sub>不在T<sub>0</sub> 中。现令T<sub>2</sub> = T<sub>1</sub> - e<sup>,</sup><sub>k + </sub>e<sub>k</sub>，则T<sub>2</sub>也为生成树但由Kruskal算法可知e<sub>k</sub>是使e<sub>1</sub>, e<sub>2</sub> &#8230; e<sub>k-1</sub>, e<sub>k</sub>无圈的权值最小的边，e<sub>1</sub>, e<sub>2</sub> &#8230; e<sub>k-1</sub>, e<sup>,</sup><sub>k</sub>是树的子图必无圈故e<sup>,</sup><sub>k</sub>的权值必定小于e<sub>k</sub><sub>，</sub>即T<sub>2</sub>的总权值不大于T<sub>1</sub>的权值，因T<sub>1</sub>是最小生成树，故必T<sub>2</sub>也是最小生成树，但f(T<sub>2</sub>)＞k与k是f函数最大取值矛盾，故T<sub>0</sub>是最小生成树。</p></div>
<p><script type="text/javascript">
if ($ != jQuery) {
	$ = jQuery.noConflict();
}
var isLogined = false;
var cb_blogId = 93526;
var cb_entryId = 2367360;
var cb_blogApp = "visayafan";
var cb_blogUserGuid = "85a764ab-ccb6-e011-8673-842b2b196315";
var cb_entryCreatedDate = '2012/2/25 0:34:00';
</script></p> <img src ="http://www.cppblog.com/hwj/aggbug/172497.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/hwj/" target="_blank">有间客栈</a> 2012-04-23 21:23 <a href="http://www.cppblog.com/hwj/archive/2012/04/23/172497.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>平衡二叉树</title><link>http://www.cppblog.com/hwj/archive/2012/04/23/172494.html</link><dc:creator>有间客栈</dc:creator><author>有间客栈</author><pubDate>Mon, 23 Apr 2012 12:25:00 GMT</pubDate><guid>http://www.cppblog.com/hwj/archive/2012/04/23/172494.html</guid><wfw:comment>http://www.cppblog.com/hwj/comments/172494.html</wfw:comment><comments>http://www.cppblog.com/hwj/archive/2012/04/23/172494.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/hwj/comments/commentRss/172494.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/hwj/services/trackbacks/172494.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 平衡二叉树（解惑） 平衡二叉树定义(AVL)：它或者是一颗空树，或者具有以下性质的二叉树：它的左子树和右子树的深度之差的绝对值不超过1，且它的左子树和右子树都是一颗平衡二叉树。平衡因子(bf)：结点的左子树的深度减去右子树的深度，那么显然-1&lt;=bf&lt;=1;很显然，平衡二叉树是在二叉排序树(BST)上引入的，就是为了解决二叉排序树的不平衡性导致时间复杂度大大下降，那么A...&nbsp;&nbsp;<a href='http://www.cppblog.com/hwj/archive/2012/04/23/172494.html'>阅读全文</a><img src ="http://www.cppblog.com/hwj/aggbug/172494.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/hwj/" target="_blank">有间客栈</a> 2012-04-23 20:25 <a href="http://www.cppblog.com/hwj/archive/2012/04/23/172494.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>