﻿<?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小加-随笔分类-数据结构和算法</title><link>http://www.cppblog.com/cxiaojia/category/18031.html</link><description>厚德 博学 求真 至善
The bright moon and breeze</description><language>zh-cn</language><lastBuildDate>Tue, 26 Mar 2013 08:30:11 GMT</lastBuildDate><pubDate>Tue, 26 Mar 2013 08:30:11 GMT</pubDate><ttl>60</ttl><item><title>优先队列（二叉堆）模板</title><link>http://www.cppblog.com/cxiaojia/archive/2012/09/15/190272.html</link><dc:creator>C小加</dc:creator><author>C小加</author><pubDate>Sat, 15 Sep 2012 06:40:00 GMT</pubDate><guid>http://www.cppblog.com/cxiaojia/archive/2012/09/15/190272.html</guid><wfw:comment>http://www.cppblog.com/cxiaojia/comments/190272.html</wfw:comment><comments>http://www.cppblog.com/cxiaojia/archive/2012/09/15/190272.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/cxiaojia/comments/commentRss/190272.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cxiaojia/services/trackbacks/190272.html</trackback:ping><description><![CDATA[<div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #000000; ">template</span><span style="color: #000000; ">&lt;</span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;T,</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;MAX</span><span style="color: #000000; ">=</span><span style="color: #000000; ">100003</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "><br /></span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;BinaryHeap<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">private</span><span style="color: #000000; ">:<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;Size;<br />&nbsp;&nbsp;&nbsp;&nbsp;T&nbsp;</span><span style="color: #000000; ">*</span><span style="color: #000000; ">&nbsp;Tarr;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">public</span><span style="color: #000000; ">:<br />&nbsp;&nbsp;&nbsp;&nbsp;BinaryHeap();<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;insert(T&nbsp;x);<br />&nbsp;&nbsp;&nbsp;&nbsp;T&nbsp;deleteMin();<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000; ">~</span><span style="color: #000000; ">BinaryHeap();<br />};<br /><br />template</span><span style="color: #000000; ">&lt;</span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;T,</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;MAX</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "><br />BinaryHeap</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">T,MAX</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">::BinaryHeap()<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;Tarr</span><span style="color: #000000; ">=</span><span style="color: #0000FF; ">new</span><span style="color: #000000; ">&nbsp;T[MAX</span><span style="color: #000000; ">+</span><span style="color: #000000; ">1</span><span style="color: #000000; ">];<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">(Tarr</span><span style="color: #000000; ">==</span><span style="color: #000000; ">NULL)&nbsp;{cout</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">"</span><span style="color: #000000; ">创建数组失败</span><span style="color: #000000; ">"</span><span style="color: #000000; ">&lt;&lt;</span><span style="color: #000000; ">endl;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;;}<br />&nbsp;&nbsp;&nbsp;&nbsp;Size</span><span style="color: #000000; ">=</span><span style="color: #000000; ">0</span><span style="color: #000000; ">;<br />}<br />template</span><span style="color: #000000; ">&lt;</span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;T,</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;MAX</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "><br /></span><span style="color: #0000FF; ">void</span><span style="color: #000000; ">&nbsp;BinaryHeap</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">T,MAX</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">::insert(T&nbsp;x)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000; ">++</span><span style="color: #000000; ">Size;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">(Size</span><span style="color: #000000; ">==</span><span style="color: #000000; ">MAX)&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;i;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">for</span><span style="color: #000000; ">(i</span><span style="color: #000000; ">=</span><span style="color: #000000; ">Size;Tarr[i</span><span style="color: #000000; ">/</span><span style="color: #000000; ">2</span><span style="color: #000000; ">]</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">x;i</span><span style="color: #000000; ">/=</span><span style="color: #000000; ">2</span><span style="color: #000000; ">)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Tarr[i]</span><span style="color: #000000; ">=</span><span style="color: #000000; ">Tarr[i</span><span style="color: #000000; ">/</span><span style="color: #000000; ">2</span><span style="color: #000000; ">];<br />&nbsp;&nbsp;&nbsp;&nbsp;Tarr[i]</span><span style="color: #000000; ">=</span><span style="color: #000000; ">x;<br />}<br />template</span><span style="color: #000000; ">&lt;</span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;T,</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;MAX</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "><br />T&nbsp;BinaryHeap</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">T,MAX</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">::deleteMin()<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">(Size</span><span style="color: #000000; ">==</span><span style="color: #000000; ">0</span><span style="color: #000000; ">)&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;</span><span style="color: #000000; ">0</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;T&nbsp;minem</span><span style="color: #000000; ">=</span><span style="color: #000000; ">Tarr[</span><span style="color: #000000; ">1</span><span style="color: #000000; ">];<br />&nbsp;&nbsp;&nbsp;&nbsp;T&nbsp;lastem</span><span style="color: #000000; ">=</span><span style="color: #000000; ">Tarr[Size</span><span style="color: #000000; ">--</span><span style="color: #000000; ">];<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;i,child;<br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">for</span><span style="color: #000000; ">(i</span><span style="color: #000000; ">=</span><span style="color: #000000; ">1</span><span style="color: #000000; ">;i</span><span style="color: #000000; ">*</span><span style="color: #000000; ">2</span><span style="color: #000000; ">&lt;=</span><span style="color: #000000; ">Size;i</span><span style="color: #000000; ">=</span><span style="color: #000000; ">child)&nbsp;&nbsp;&nbsp;&nbsp;<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;child</span><span style="color: #000000; ">=</span><span style="color: #000000; ">i</span><span style="color: #000000; ">*</span><span style="color: #000000; ">2</span><span style="color: #000000; ">;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">(child</span><span style="color: #000000; ">!=</span><span style="color: #000000; ">Size</span><span style="color: #000000; ">-</span><span style="color: #000000; ">1</span><span style="color: #000000; ">&amp;&amp;</span><span style="color: #000000; ">Tarr[child</span><span style="color: #000000; ">+</span><span style="color: #000000; ">1</span><span style="color: #000000; ">]</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">Tarr[child])<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #000000; ">++</span><span style="color: #000000; ">child;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">if</span><span style="color: #000000; ">(lastem</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">Tarr[child])<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Tarr[i]</span><span style="color: #000000; ">=</span><span style="color: #000000; ">Tarr[child];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">else</span><span style="color: #000000; "><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">break</span><span style="color: #000000; ">;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;Tarr[i]</span><span style="color: #000000; ">=</span><span style="color: #000000; ">lastem;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #0000FF; ">return</span><span style="color: #000000; ">&nbsp;minem;<br />}<br /><br />template</span><span style="color: #000000; ">&lt;</span><span style="color: #0000FF; ">class</span><span style="color: #000000; ">&nbsp;T,</span><span style="color: #0000FF; ">int</span><span style="color: #000000; ">&nbsp;MAX</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; "><br />BinaryHeap</span><span style="color: #000000; ">&lt;</span><span style="color: #000000; ">T,MAX</span><span style="color: #000000; ">&gt;</span><span style="color: #000000; ">::</span><span style="color: #000000; ">~</span><span style="color: #000000; ">BinaryHeap()<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;delete[]&nbsp;Tarr;<br /><br />}<br /><br /></span></div><img src ="http://www.cppblog.com/cxiaojia/aggbug/190272.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cxiaojia/" target="_blank">C小加</a> 2012-09-15 14:40 <a href="http://www.cppblog.com/cxiaojia/archive/2012/09/15/190272.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一步一步写平衡二叉树（AVL树）</title><link>http://www.cppblog.com/cxiaojia/archive/2012/08/20/187776.html</link><dc:creator>C小加</dc:creator><author>C小加</author><pubDate>Mon, 20 Aug 2012 09:11:00 GMT</pubDate><guid>http://www.cppblog.com/cxiaojia/archive/2012/08/20/187776.html</guid><wfw:comment>http://www.cppblog.com/cxiaojia/comments/187776.html</wfw:comment><comments>http://www.cppblog.com/cxiaojia/archive/2012/08/20/187776.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.cppblog.com/cxiaojia/comments/commentRss/187776.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cxiaojia/services/trackbacks/187776.html</trackback:ping><description><![CDATA[<p style="padding: 0px; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; line-height: 19px; background-color: #f5f5f5; text-align: center; "><strong style="margin: 0px; padding: 0px; "></strong></p><p data-mce-="" style="margin-top: 10px; margin-bottom: 10px; font-family: verdana, Arial, Helvetica, sans-serif; text-align: center; "><strong>一步一步写平衡二叉树（AVL树）</strong></p><p data-mce-="" style="margin-top: 10px; margin-bottom: 10px; font-family: verdana, Arial, Helvetica, sans-serif; text-align: center; "><span data-mce-style="color: #ff0000;" style="color: #ff0000; ">作者：</span>C小加&nbsp;<span data-mce-style="color: #ff0000;" style="color: #ff0000; ">更新时间：</span>2012-8-20</p><p data-mce-="" style="margin-top: 10px; margin-bottom: 10px; font-family: verdana, Arial, Helvetica, sans-serif; ">　　平衡二叉树（Balanced Binary Tree）是二叉查找树的一个进化体，也是第一个引入平衡概念的二叉树。1962年，G.M. Adelson-Velsky 和 E.M. Landis发明了这棵树，所以它又叫AVL树。平衡二叉树要求对于每一个节点来说，它的左右子树的高度之差不能超过1，如果插入或者删除一个节点使得高度之差大于1，就要进行节点之间的旋转，将二叉树重新维持在一个平衡状态。这个方案很好的解决了二叉查找树退化成链表的问题，把插入，查找，删除的时间复杂度最好情况和最坏情况都维持在O(logN)。但是频繁旋转会使插入和删除牺牲掉O(logN)左右的时间，不过相对二叉查找树来说，时间上稳定了很多。</p><p style="text-align: center;margin-top: 10px; margin-bottom: 10px; font-family: verdana, Arial, Helvetica, sans-serif; "><img src="http://pic002.cnblogs.com/images/2012/229056/2012082016003157.jpg" alt="" data-mce-src="http://pic002.cnblogs.com/images/2012/229056/2012082016003157.jpg" style="border: 0px; cursor: default; " /></p><p data-mce-="" style="margin-top: 10px; margin-bottom: 10px; font-family: verdana, Arial, Helvetica, sans-serif; ">　　平衡二叉树实现的大部分过程和二叉查找树是一样的（学平衡二叉树之前一定要会二叉查找树），区别就在于插入和删除之后要写一个旋转算法去维持平衡，维持平衡需要借助一个节点高度的属性。我参考了机械工业出版社的《数据结构与算法分析-C语言描述》写了一个C++版的代码。这本书的AVLTree讲的很好，不过没有很完整的去描述。我会一步一步的讲解如何写平衡二叉树，重点是平衡二叉树的核心部分，也就是旋转算法。</p><p data-mce-="" style="margin-top: 10px; margin-bottom: 10px; font-family: verdana, Arial, Helvetica, sans-serif; "><strong>第一步：节点信息</strong></p><p data-mce-="" style="margin-top: 10px; margin-bottom: 10px; font-family: verdana, Arial, Helvetica, sans-serif; ">　　相对于二叉查找树的节点来说，我们需要用一个属性二叉树的高度，目的是维护插入和删除过程中的旋转算法。</p><p data-mce-="" style="margin-top: 10px; margin-bottom: 10px; font-family: verdana, Arial, Helvetica, sans-serif; ">代码如下：</p><p style="padding: 0px; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; line-height: 19px; background-color: #f5f5f5; "></p><div style="margin: 5px 0px; font-size: 12px; "><div style="margin: 5px 0px 0px; "><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008000; ">//</span><span style="color: #008000; ">AVL树节点信息</span><span style="color: #008000; "><br /></span>template&lt;<span style="color: #0000FF; ">class</span>&nbsp;T&gt;<br /><span style="color: #0000FF; ">class</span>&nbsp;TreeNode<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TreeNode():lson(NULL),rson(NULL),freq(1),hgt(0){}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;T&nbsp;data;<span style="color: #008000; ">//</span><span style="color: #008000; ">值</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;hgt;<span style="color: #008000; ">//</span><span style="color: #008000; ">以此节点为根的树的高度</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;freq;<span style="color: #008000; ">//</span><span style="color: #008000; ">频率</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TreeNode*&nbsp;lson;<span style="color: #008000; ">//</span><span style="color: #008000; ">指向左儿子的地址</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TreeNode*&nbsp;rson;<span style="color: #008000; ">//</span><span style="color: #008000; ">指向右儿子的地址</span><span style="color: #008000; "><br /></span>};</div></div></div><p style="padding: 0px; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; line-height: 19px; background-color: #f5f5f5; "><strong style="margin: 0px; padding: 0px; "></strong></p><p style="margin-top: 10px; margin-bottom: 10px; font-family: verdana, Arial, Helvetica, sans-serif; "><strong>第二步：平衡二叉树类的声明</strong></p><p style="margin-top: 10px; margin-bottom: 10px; font-family: verdana, Arial, Helvetica, sans-serif; ">　　声明中的旋转函数将在后边的步骤中详解。</p><p style="margin-top: 10px; margin-bottom: 10px; font-family: verdana, Arial, Helvetica, sans-serif; ">代码如下：</p><p style="padding: 0px; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; line-height: 19px; background-color: #f5f5f5; "></p><div style="margin: 5px 0px; font-size: 12px; "><div style="margin: 5px 0px 0px; "><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008000; ">//</span><span style="color: #008000; ">AVL树类的属性和方法声明</span><span style="color: #008000; "><br /></span>template&lt;<span style="color: #0000FF; ">class</span>&nbsp;T&gt;<br /><span style="color: #0000FF; ">class</span>&nbsp;AVLTree<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">private</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TreeNode&lt;T&gt;*&nbsp;root;<span style="color: #008000; ">//</span><span style="color: #008000; ">根节点</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;insertpri(TreeNode&lt;T&gt;*&nbsp;&amp;node,T&nbsp;x);<span style="color: #008000; ">//</span><span style="color: #008000; ">插入</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TreeNode&lt;T&gt;*&nbsp;findpri(TreeNode&lt;T&gt;*&nbsp;node,T&nbsp;x);<span style="color: #008000; ">//</span><span style="color: #008000; ">查找</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;insubtree(TreeNode&lt;T&gt;*&nbsp;node);<span style="color: #008000; ">//</span><span style="color: #008000; ">中序遍历</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;Deletepri(TreeNode&lt;T&gt;*&nbsp;&amp;node,T&nbsp;x);<span style="color: #008000; ">//</span><span style="color: #008000; ">删除</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;height(TreeNode&lt;T&gt;*&nbsp;node);<span style="color: #008000; ">//</span><span style="color: #008000; ">求树的高度</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;SingRotateLeft(TreeNode&lt;T&gt;*&nbsp;&amp;k2);<span style="color: #008000; ">//</span><span style="color: #008000; ">左左情况下的旋转</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;SingRotateRight(TreeNode&lt;T&gt;*&nbsp;&amp;k2);<span style="color: #008000; ">//</span><span style="color: #008000; ">右右情况下的旋转</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;DoubleRotateLR(TreeNode&lt;T&gt;*&nbsp;&amp;k3);<span style="color: #008000; ">//</span><span style="color: #008000; ">左右情况下的旋转</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;DoubleRotateRL(TreeNode&lt;T&gt;*&nbsp;&amp;k3);<span style="color: #008000; ">//</span><span style="color: #008000; ">右左情况下的旋转</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;Max(<span style="color: #0000FF; ">int</span>&nbsp;cmpa,<span style="color: #0000FF; ">int</span>&nbsp;cmpb);<span style="color: #008000; ">//</span><span style="color: #008000; ">求最大值</span><span style="color: #008000; "><br /></span><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;AVLTree():root(NULL){}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;insert(T&nbsp;x);<span style="color: #008000; ">//</span><span style="color: #008000; ">插入接口</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TreeNode&lt;T&gt;*&nbsp;find(T&nbsp;x);<span style="color: #008000; ">//</span><span style="color: #008000; ">查找接口</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;Delete(T&nbsp;x);<span style="color: #008000; ">//</span><span style="color: #008000; ">删除接口</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;traversal();<span style="color: #008000; ">//</span><span style="color: #008000; ">遍历接口</span><span style="color: #008000; "><br /></span><br />};</div></div></div><p style="padding: 0px; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; line-height: 19px; background-color: #f5f5f5; "><strong style="margin: 0px; padding: 0px; "></strong></p><p style="margin-top: 10px; margin-bottom: 10px; font-family: verdana, Arial, Helvetica, sans-serif; "><strong>第三步：两个辅助方法</strong></p><p style="margin-top: 10px; margin-bottom: 10px; font-family: verdana, Arial, Helvetica, sans-serif; ">　　旋转算法需要借助于两个功能的辅助，一个是求树的高度，一个是求两个高度的最大值。这里规定，一棵空树的高度为-1，只有一个根节点的树的高度为0，以后每多一层高度加1。为了解决指针NULL这种情况，写了一个求高度的函数，这个函数还是很有必要的。</p><p style="margin-top: 10px; margin-bottom: 10px; font-family: verdana, Arial, Helvetica, sans-serif; ">代码如下：</p><p style="padding: 0px; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; line-height: 19px; background-color: #f5f5f5; "></p><div style="margin: 5px 0px; font-size: 12px; "><div style="margin: 5px 0px 0px; "><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008000; ">//</span><span style="color: #008000; ">计算以节点为根的树的高度</span><span style="color: #008000; "><br /></span>template&lt;<span style="color: #0000FF; ">class</span>&nbsp;T&gt;<br /><span style="color: #0000FF; ">int</span>&nbsp;AVLTree&lt;T&gt;::height(TreeNode&lt;T&gt;*&nbsp;node)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(node!=NULL)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;node-&gt;hgt;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;-1;<br />}<br /><span style="color: #008000; ">//</span><span style="color: #008000; ">求最大值</span><span style="color: #008000; "><br /></span>template&lt;<span style="color: #0000FF; ">class</span>&nbsp;T&gt;<br /><span style="color: #0000FF; ">int</span>&nbsp;AVLTree&lt;T&gt;::Max(<span style="color: #0000FF; ">int</span>&nbsp;cmpa,<span style="color: #0000FF; ">int</span>&nbsp;cmpb)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;cmpa&gt;cmpb?cmpa:cmpb;<br />}</div></div><div style="margin: 5px 0px 0px; "></div></div><p style="margin-top: 10px; margin-bottom: 10px; font-family: verdana, Arial, Helvetica, sans-serif; "><strong>第四步：旋转</strong></p><p style="margin-top: 10px; margin-bottom: 10px; font-family: verdana, Arial, Helvetica, sans-serif; ">　　对于一个平衡的节点，由于任意节点最多有两个儿子，因此高度不平衡时，此节点的两颗子树的高度差2.容易看出，这种不平衡出现在下面四种情况：</p><p style="text-align: center;margin-top: 10px; margin-bottom: 10px; font-family: verdana, Arial, Helvetica, sans-serif; "><img src="http://pic002.cnblogs.com/images/2012/229056/2012082016021366.jpg" alt="" data-mce-src="http://pic002.cnblogs.com/images/2012/229056/2012082016021366.jpg" style="border: 0px; cursor: default; " /></p><p style="margin-top: 10px; margin-bottom: 10px; font-family: verdana, Arial, Helvetica, sans-serif; ">　　1、6节点的左子树3节点高度比右子树7节点大2，左子树3节点的左子树1节点高度大于右子树4节点，这种情况成为<span data-mce-style="color: #ff0000;" style="color: #ff0000; ">左左</span>。</p><p style="margin-top: 10px; margin-bottom: 10px; font-family: verdana, Arial, Helvetica, sans-serif; ">　　2、6节点的左子树2节点高度比右子树7节点大2，左子树2节点的左子树1节点高度小于右子树4节点，这种情况成为<span data-mce-style="color: #ff0000;" style="color: #ff0000; ">左右</span>。</p><p style="margin-top: 10px; margin-bottom: 10px; font-family: verdana, Arial, Helvetica, sans-serif; ">　　3、2节点的左子树1节点高度比右子树5节点小2，右子树5节点的左子树3节点高度大于右子树6节点，这种情况成为<span data-mce-style="color: #ff0000;" style="color: #ff0000; ">右左</span>。</p><p style="margin-top: 10px; margin-bottom: 10px; font-family: verdana, Arial, Helvetica, sans-serif; ">　　4、2节点的左子树1节点高度比右子树4节点小2，右子树4节点的左子树3节点高度小于右子树6节点，这种情况成为<span data-mce-style="color: #ff0000;" style="color: #ff0000; ">右右</span>。</p><p style="margin-top: 10px; margin-bottom: 10px; font-family: verdana, Arial, Helvetica, sans-serif; ">　　从图2中可以可以看出，1和4两种情况是对称的，这两种情况的旋转算法是一致的，只需要经过一次旋转就可以达到目标，我们称之为单旋转。2和3两种情况也是对称的，这两种情况的旋转算法也是一致的，需要进行两次旋转，我们称之为双旋转。</p><p style="margin-top: 10px; margin-bottom: 10px; font-family: verdana, Arial, Helvetica, sans-serif; "><strong>第五步：单旋转</strong></p><p style="margin-top: 10px; margin-bottom: 10px; font-family: verdana, Arial, Helvetica, sans-serif; ">　　单旋转是针对于左左和右右这两种情况的解决方案，这两种情况是对称的，只要解决了左左这种情况，右右就很好办了。图3是左左情况的解决方案，节点k2不满足平衡特性，因为它的左子树k1比右子树Z深2层，而且k1子树中，更深的一层的是k1的左子树X子树，所以属于左左情况。</p><p style="text-align: center;margin-top: 10px; margin-bottom: 10px; font-family: verdana, Arial, Helvetica, sans-serif; "><img src="http://www.cppblog.com/images/cppblog_com/cxiaojia/avltree35.jpg" width="530" height="229" alt="" /><br /></p><p style="margin-top: 10px; margin-bottom: 10px; font-family: verdana, Arial, Helvetica, sans-serif; ">　　为使树恢复平衡，我们把k2变成这棵树的根节点，因为k2大于k1，把k2置于k1的右子树上，而原本在k1右子树的Y大于k1，小于k2，就把Y置于k2的左子树上，这样既满足了二叉查找树的性质，又满足了平衡二叉树的性质。</p><p style="margin-top: 10px; margin-bottom: 10px; font-family: verdana, Arial, Helvetica, sans-serif; ">　　这样的操作只需要一部分指针改变，结果我们得到另外一颗二叉查找树，它是一棵AVL树，因为X向上一移动了一层，Y还停留在原来的层面上，Z向下移动了一层。整棵树的新高度和之前没有在左子树上插入的高度相同，插入操作使得X高度长高了。因此，由于这颗子树高度没有变化，所以通往根节点的路径就不需要继续旋转了。</p><p style="margin-top: 10px; margin-bottom: 10px; font-family: verdana, Arial, Helvetica, sans-serif; ">代码如下：</p><p style="padding: 0px; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; line-height: 19px; background-color: #f5f5f5; "></p><div style="margin: 5px 0px; font-size: 12px; "><div style="margin: 5px 0px 0px; "><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008000; ">//</span><span style="color: #008000; ">左左情况下的旋转</span><span style="color: #008000; "><br /></span>template&lt;<span style="color: #0000FF; ">class</span>&nbsp;T&gt;<br /><span style="color: #0000FF; ">void</span>&nbsp;AVLTree&lt;T&gt;::SingRotateLeft(TreeNode&lt;T&gt;*&nbsp;&amp;k2)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;TreeNode&lt;T&gt;*&nbsp;k1;<br />&nbsp;&nbsp;&nbsp;&nbsp;k1=k2-&gt;lson;<br />&nbsp;&nbsp;&nbsp;&nbsp;k2-&gt;lson=k1-&gt;rson;<br />&nbsp;&nbsp;&nbsp;&nbsp;k1-&gt;rson=k2;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;k2-&gt;hgt=Max(height(k2-&gt;lson),height(k2-&gt;rson))+1;<br />&nbsp;&nbsp;&nbsp;&nbsp;k1-&gt;hgt=Max(height(k1-&gt;lson),k2-&gt;hgt)+1;<br />}<br /><span style="color: #008000; ">//</span><span style="color: #008000; ">右右情况下的旋转</span><span style="color: #008000; "><br /></span>template&lt;<span style="color: #0000FF; ">class</span>&nbsp;T&gt;<br /><span style="color: #0000FF; ">void</span>&nbsp;AVLTree&lt;T&gt;::SingRotateRight(TreeNode&lt;T&gt;*&nbsp;&amp;k2)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;TreeNode&lt;T&gt;*&nbsp;k1;<br />&nbsp;&nbsp;&nbsp;&nbsp;k1=k2-&gt;rson;<br />&nbsp;&nbsp;&nbsp;&nbsp;k2-&gt;rson=k1-&gt;lson;<br />&nbsp;&nbsp;&nbsp;&nbsp;k1-&gt;lson=k2;<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;k2-&gt;hgt=Max(height(k2-&gt;lson),height(k2-&gt;rson))+1;<br />&nbsp;&nbsp;&nbsp;&nbsp;k1-&gt;hgt=Max(height(k1-&gt;rson),k2-&gt;hgt)+1;<br />}</div></div></div><p style="padding: 0px; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; line-height: 19px; background-color: #f5f5f5; "><strong style="margin: 0px; padding: 0px; "></strong></p><p style="margin-top: 10px; margin-bottom: 10px; font-family: verdana, Arial, Helvetica, sans-serif; "><strong>第六步：双旋转</strong></p><p style="margin-top: 10px; margin-bottom: 10px; font-family: verdana, Arial, Helvetica, sans-serif; ">　　对于左右和右左这两种情况，单旋转不能使它达到一个平衡状态，要经过两次旋转。双旋转是针对于这两种情况的解决方案，同样的，这样两种情况也是对称的，只要解决了左右这种情况，右左就很好办了。图4是左右情况的解决方案，节点k3不满足平衡特性，因为它的左子树k1比右子树Z深2层，而且k1子树中，更深的一层的是k1的右子树k2子树，所以属于左右情况。</p><p style="text-align: center;margin-top: 10px; margin-bottom: 10px; font-family: verdana, Arial, Helvetica, sans-serif; "><img src="http://pic002.cnblogs.com/images/2012/229056/2012082016534455.jpg" alt="" data-mce-src="http://pic002.cnblogs.com/images/2012/229056/2012082016534455.jpg" style="border: 0px; cursor: default; " /></p><p style="margin-top: 10px; margin-bottom: 10px; font-family: verdana, Arial, Helvetica, sans-serif; ">&nbsp;　　为使树恢复平衡，我们需要进行两步，第一步，把k1作为根，进行一次右右旋转，旋转之后就变成了左左情况，所以第二步再进行一次左左旋转，最后得到了一棵以k2为根的平衡二叉树树。</p><p style="margin-top: 10px; margin-bottom: 10px; font-family: verdana, Arial, Helvetica, sans-serif; ">代码如下：</p><p style="padding: 0px; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; line-height: 19px; background-color: #f5f5f5; "></p><div style="margin: 5px 0px; font-size: 12px; "><div style="margin: 5px 0px 0px; "><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008000; ">//</span><span style="color: #008000; ">左右情况的旋转</span><span style="color: #008000; "><br /></span>template&lt;<span style="color: #0000FF; ">class</span>&nbsp;T&gt;<br /><span style="color: #0000FF; ">void</span>&nbsp;AVLTree&lt;T&gt;::DoubleRotateLR(TreeNode&lt;T&gt;*&nbsp;&amp;k3)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;SingRotateRight(k3-&gt;lson);<br />&nbsp;&nbsp;&nbsp;&nbsp;SingRotateLeft(k3);<br />}<br /><span style="color: #008000; ">//</span><span style="color: #008000; ">右左情况的旋转</span><span style="color: #008000; "><br /></span>template&lt;<span style="color: #0000FF; ">class</span>&nbsp;T&gt;<br /><span style="color: #0000FF; ">void</span>&nbsp;AVLTree&lt;T&gt;::DoubleRotateRL(TreeNode&lt;T&gt;*&nbsp;&amp;k3)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;SingRotateLeft(k3-&gt;rson);<br />&nbsp;&nbsp;&nbsp;&nbsp;SingRotateRight(k3);<br />}</div></div></div><p style="padding: 0px; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; line-height: 19px; background-color: #f5f5f5; "></p><p style="margin-top: 10px; margin-bottom: 10px; font-family: verdana, Arial, Helvetica, sans-serif; ">&nbsp;<strong>第七步：插入</strong></p><p style="margin-top: 10px; margin-bottom: 10px; font-family: verdana, Arial, Helvetica, sans-serif; ">　　插入的方法和二叉查找树基本一样，区别是，插入完成后需要从插入的节点开始维护一个到根节点的路径，每经过一个节点都要维持树的平衡。维持树的平衡要根据高度差的特点选择不同的旋转算法。</p><p style="margin-top: 10px; margin-bottom: 10px; font-family: verdana, Arial, Helvetica, sans-serif; ">代码如下：</p><p style="margin-top: 10px; margin-bottom: 10px; font-family: verdana, Arial, Helvetica, sans-serif; "></p><p style="padding: 0px; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; line-height: 19px; background-color: #f5f5f5; "></p><div style="margin: 5px 0px; font-size: 12px; "><div style="margin: 5px 0px 0px; "><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008000; ">//</span><span style="color: #008000; ">插入</span><span style="color: #008000; "><br /></span>template&lt;<span style="color: #0000FF; ">class</span>&nbsp;T&gt;<br /><span style="color: #0000FF; ">void</span>&nbsp;AVLTree&lt;T&gt;::insertpri(TreeNode&lt;T&gt;*&nbsp;&amp;node,T&nbsp;x)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(node==NULL)<span style="color: #008000; ">//</span><span style="color: #008000; ">如果节点为空,就在此节点处加入x信息</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;node=<span style="color: #0000FF; ">new</span>&nbsp;TreeNode&lt;T&gt;();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;node-&gt;data=x;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(node-&gt;data&gt;x)<span style="color: #008000; ">//</span><span style="color: #008000; ">如果x小于节点的值,就继续在节点的左子树中插入x</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;insertpri(node-&gt;lson,x);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(2==height(node-&gt;lson)-height(node-&gt;rson))<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(x&lt;node-&gt;lson-&gt;data)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SingRotateLeft(node);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">else</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DoubleRotateLR(node);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">else</span>&nbsp;<span style="color: #0000FF; ">if</span>(node-&gt;data&lt;x)<span style="color: #008000; ">//</span><span style="color: #008000; ">如果x大于节点的值,就继续在节点的右子树中插入x</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;insertpri(node-&gt;rson,x);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(2==height(node-&gt;rson)-height(node-&gt;lson))<span style="color: #008000; ">//</span><span style="color: #008000; ">如果高度之差为2的话就失去了平衡,需要旋转</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(x&gt;node-&gt;rson-&gt;data)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SingRotateRight(node);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">else</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DoubleRotateRL(node);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">else</span>&nbsp;++(node-&gt;freq);<span style="color: #008000; ">//</span><span style="color: #008000; ">如果相等,就把频率加1</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;node-&gt;hgt=Max(height(node-&gt;lson),height(node-&gt;rson));<br />}<br /><span style="color: #008000; ">//</span><span style="color: #008000; ">插入接口</span><span style="color: #008000; "><br /></span>template&lt;<span style="color: #0000FF; ">class</span>&nbsp;T&gt;<br /><span style="color: #0000FF; ">void</span>&nbsp;AVLTree&lt;T&gt;::insert(T&nbsp;x)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;insertpri(root,x);<br />}</div></div></div><p style="padding: 0px; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; line-height: 19px; background-color: #f5f5f5; "><strong style="margin: 0px; padding: 0px; "></strong></p><p style="margin-top: 10px; margin-bottom: 10px; font-family: verdana, Arial, Helvetica, sans-serif; "><strong>第八步：查找</strong></p><p style="margin-top: 10px; margin-bottom: 10px; font-family: verdana, Arial, Helvetica, sans-serif; ">和二叉查找树相比，查找方法没有变法，不过根据存储的特性，AVL树能维持在一个O(logN)的稳定的时间，而二叉查找树则相当不稳定。</p><p style="margin-top: 10px; margin-bottom: 10px; font-family: verdana, Arial, Helvetica, sans-serif; ">代码如下：</p><p style="padding: 0px; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; line-height: 19px; background-color: #f5f5f5; "></p><div style="margin: 5px 0px; font-size: 12px; "><div style="margin: 5px 0px 0px; "><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008000; ">//</span><span style="color: #008000; ">查找</span><span style="color: #008000; "><br /></span>template&lt;<span style="color: #0000FF; ">class</span>&nbsp;T&gt;<br />TreeNode&lt;T&gt;*&nbsp;AVLTree&lt;T&gt;::findpri(TreeNode&lt;T&gt;*&nbsp;node,T&nbsp;x)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(node==NULL)<span style="color: #008000; ">//</span><span style="color: #008000; ">如果节点为空说明没找到,返回NULL</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;NULL;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(node-&gt;data&gt;x)<span style="color: #008000; ">//</span><span style="color: #008000; ">如果x小于节点的值,就继续在节点的左子树中查找x</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;findpri(node-&gt;lson,x);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">else</span>&nbsp;<span style="color: #0000FF; ">if</span>(node-&gt;data&lt;x)<span style="color: #008000; ">//</span><span style="color: #008000; ">如果x大于节点的值,就继续在节点的左子树中查找x</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;findpri(node-&gt;rson,x);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">else</span>&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;node;<span style="color: #008000; ">//</span><span style="color: #008000; ">如果相等,就找到了此节点</span><span style="color: #008000; "><br /></span>}<br /><span style="color: #008000; ">//</span><span style="color: #008000; ">查找接口</span><span style="color: #008000; "><br /></span>template&lt;<span style="color: #0000FF; ">class</span>&nbsp;T&gt;<br />TreeNode&lt;T&gt;*&nbsp;AVLTree&lt;T&gt;::find(T&nbsp;x)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;findpri(root,x);<br />}</div></div></div><p style="padding: 0px; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; line-height: 19px; background-color: #f5f5f5; "><strong style="margin: 0px; padding: 0px; "></strong></p><p style="margin-top: 10px; margin-bottom: 10px; font-family: verdana, Arial, Helvetica, sans-serif; "><strong>第九步：删除</strong></p><p style="margin-top: 10px; margin-bottom: 10px; font-family: verdana, Arial, Helvetica, sans-serif; ">　　删除的方法也和二叉查找树的一致，区别是，删除完成后，需要从删除节点的父亲开始向上维护树的平衡一直到根节点。</p><p style="margin-top: 10px; margin-bottom: 10px; font-family: verdana, Arial, Helvetica, sans-serif; ">代码如下：</p><p style="padding: 0px; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; line-height: 19px; background-color: #f5f5f5; "></p><div style="margin: 5px 0px; font-size: 12px; "><div style="margin: 5px 0px 0px; "><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008000; ">//</span><span style="color: #008000; ">删除</span><span style="color: #008000; "><br /></span>template&lt;<span style="color: #0000FF; ">class</span>&nbsp;T&gt;<br /><span style="color: #0000FF; ">void</span>&nbsp;AVLTree&lt;T&gt;::Deletepri(TreeNode&lt;T&gt;*&nbsp;&amp;node,T&nbsp;x)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(node==NULL)&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;;<span style="color: #008000; ">//</span><span style="color: #008000; ">没有找到值是x的节点</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(x&nbsp;&lt;&nbsp;node-&gt;data)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Deletepri(node-&gt;lson,x);<span style="color: #008000; ">//</span><span style="color: #008000; ">如果x小于节点的值,就继续在节点的左子树中删除x</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(2==height(node-&gt;rson)-height(node-&gt;lson))<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(node-&gt;rson-&gt;lson!=NULL&amp;&amp;(height(node-&gt;rson-&gt;lson)&gt;height(node-&gt;rson-&gt;rson))&nbsp;)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DoubleRotateRL(node);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">else</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SingRotateRight(node);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">else</span>&nbsp;<span style="color: #0000FF; ">if</span>(x&nbsp;&gt;&nbsp;node-&gt;data)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Deletepri(node-&gt;rson,x);<span style="color: #008000; ">//</span><span style="color: #008000; ">如果x大于节点的值,就继续在节点的右子树中删除x</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(2==height(node-&gt;lson)-height(node-&gt;rson))<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(node-&gt;lson-&gt;rson!=NULL&amp;&amp;&nbsp;(height(node-&gt;lson-&gt;rson)&gt;height(node-&gt;lson-&gt;lson)&nbsp;))<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DoubleRotateLR(node);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">else</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SingRotateLeft(node);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br /><br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">else</span><span style="color: #008000; ">//</span><span style="color: #008000; ">如果相等,此节点就是要删除的节点</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(node-&gt;lson&amp;&amp;node-&gt;rson)<span style="color: #008000; ">//</span><span style="color: #008000; ">此节点有两个儿子</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TreeNode&lt;T&gt;*&nbsp;temp=node-&gt;rson;<span style="color: #008000; ">//</span><span style="color: #008000; ">temp指向节点的右儿子</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">while</span>(temp-&gt;lson!=NULL)&nbsp;temp=temp-&gt;lson;<span style="color: #008000; ">//</span><span style="color: #008000; ">找到右子树中值最小的节点<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">把右子树中最小节点的值赋值给本节点</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;node-&gt;data=temp-&gt;data;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;node-&gt;freq=temp-&gt;freq;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Deletepri(node-&gt;rson,temp-&gt;data);<span style="color: #008000; ">//</span><span style="color: #008000; ">删除右子树中最小值的节点</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(2==height(node-&gt;lson)-height(node-&gt;rson))<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(node-&gt;lson-&gt;rson!=NULL&amp;&amp;&nbsp;(height(node-&gt;lson-&gt;rson)&gt;height(node-&gt;lson-&gt;lson)&nbsp;))<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;DoubleRotateLR(node);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">else</span><br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;SingRotateLeft(node);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">else</span><span style="color: #008000; ">//</span><span style="color: #008000; ">此节点有1个或0个儿子</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TreeNode&lt;T&gt;*&nbsp;temp=node;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(node-&gt;lson==NULL)<span style="color: #008000; ">//</span><span style="color: #008000; ">有右儿子或者没有儿子</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;node=node-&gt;rson;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">else</span>&nbsp;<span style="color: #0000FF; ">if</span>(node-&gt;rson==NULL)<span style="color: #008000; ">//</span><span style="color: #008000; ">有左儿子</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;node=node-&gt;lson;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;delete(temp);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;temp=NULL;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(node==NULL)&nbsp;<span style="color: #0000FF; ">return</span>;<br />&nbsp;&nbsp;&nbsp;&nbsp;node-&gt;hgt=Max(height(node-&gt;lson),height(node-&gt;rson))+1;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>;<br />}<br /><span style="color: #008000; ">//</span><span style="color: #008000; ">删除接口</span><span style="color: #008000; "><br /></span>template&lt;<span style="color: #0000FF; ">class</span>&nbsp;T&gt;<br /><span style="color: #0000FF; ">void</span>&nbsp;AVLTree&lt;T&gt;::Delete(T&nbsp;x)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;Deletepri(root,x);<br />}</div></div></div><p style="padding: 0px; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; line-height: 19px; background-color: #f5f5f5; "><strong style="margin: 0px; padding: 0px; "></strong></p><p style="margin-top: 10px; margin-bottom: 10px; font-family: verdana, Arial, Helvetica, sans-serif; "><strong>第十步：中序遍历</strong></p><p style="margin-top: 10px; margin-bottom: 10px; font-family: verdana, Arial, Helvetica, sans-serif; ">代码如下：</p><p style="padding: 0px; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; line-height: 19px; background-color: #f5f5f5; "></p><div style="margin: 5px 0px; font-size: 12px; "><div style="margin: 5px 0px 0px; "><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008000; ">//</span><span style="color: #008000; ">中序遍历函数</span><span style="color: #008000; "><br /></span>template&lt;<span style="color: #0000FF; ">class</span>&nbsp;T&gt;<br /><span style="color: #0000FF; ">void</span>&nbsp;AVLTree&lt;T&gt;::insubtree(TreeNode&lt;T&gt;*&nbsp;node)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(node==NULL)&nbsp;<span style="color: #0000FF; ">return</span>;<br />&nbsp;&nbsp;&nbsp;&nbsp;insubtree(node-&gt;lson);<span style="color: #008000; ">//</span><span style="color: #008000; ">先遍历左子树</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;cout&lt;&lt;node-&gt;data&lt;&lt;"&nbsp;";<span style="color: #008000; ">//</span><span style="color: #008000; ">输出根节点</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;insubtree(node-&gt;rson);<span style="color: #008000; ">//</span><span style="color: #008000; ">再遍历右子树</span><span style="color: #008000; "><br /></span>}<br /><span style="color: #008000; ">//</span><span style="color: #008000; ">中序遍历接口</span><span style="color: #008000; "><br /></span>template&lt;<span style="color: #0000FF; ">class</span>&nbsp;T&gt;<br /><span style="color: #0000FF; ">void</span>&nbsp;AVLTree&lt;T&gt;::traversal()<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;insubtree(root);<br />}</div></div></div><p style="padding: 0px; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; line-height: 19px; background-color: #f5f5f5; "><strong style="margin: 0px; padding: 0px; "></strong></p><p style="margin-top: 10px; margin-bottom: 10px; font-family: verdana, Arial, Helvetica, sans-serif; "><strong>第十一步：关于效率</strong></p><p style="margin-top: 10px; margin-bottom: 10px; font-family: verdana, Arial, Helvetica, sans-serif; "><strong>　　</strong>此数据结构插入、查找和删除的时间复杂度均为O(logN)，但是插入和删除需要额外的旋转算法需要的时间，有时旋转过多也会影响效率。</p><p style="margin-top: 10px; margin-bottom: 10px; font-family: verdana, Arial, Helvetica, sans-serif; ">　　关于递归和非递归。我用的是递归的方法进行插入，查找和删除，而非递归的方法一般来说要比递归的方法快很多，但是我感觉非递归的方法写出来会比较困难，所以我还是选择了递归的方法。</p><p style="margin-top: 10px; margin-bottom: 10px; font-family: verdana, Arial, Helvetica, sans-serif; ">　　还有一种效率的问题是关于高度信息的存储，由于我们需要的仅仅是高度的差，不需要知道这棵树的高度，所以只需要使用两个二进制位就可以表示这个差。这样可以避免平衡因子的重复计算，可以稍微的加快一些速度，不过代码也丧失了相对简明性和清晰度。如果采用递归写法的话，这种微加速就更显得微乎其微了。</p><p style="margin-top: 10px; margin-bottom: 10px; font-family: verdana, Arial, Helvetica, sans-serif; ">&nbsp;</p><p style="margin-top: 10px; margin-bottom: 10px; font-family: verdana, Arial, Helvetica, sans-serif; ">　　如果有哪些不对的或者不清晰的地方请指出，我会修改并加以完善。</p><p style="margin-top: 10px; margin-bottom: 10px; font-family: verdana, Arial, Helvetica, sans-serif; ">&nbsp;　　附：<a href="http://files.cnblogs.com/cxiaojia/AVLTree.zip" target="_blank" data-mce-href="http://files.cnblogs.com/cxiaojia/AVLTree.zip">完整代码</a></p><p style="margin-top: 10px; margin-bottom: 10px; font-family: verdana, Arial, Helvetica, sans-serif; ">&nbsp;</p><p style="padding: 0px; font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif; font-size: 13px; line-height: 19px; background-color: #f5f5f5; "><a href="http://files.cnblogs.com/cxiaojia/AVLTree.zip" target="_blank" style="margin: 0px; padding: 0px; color: #0069d6; line-height: inherit; "></a></p><img src ="http://www.cppblog.com/cxiaojia/aggbug/187776.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cxiaojia/" target="_blank">C小加</a> 2012-08-20 17:11 <a href="http://www.cppblog.com/cxiaojia/archive/2012/08/20/187776.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>一步一步写二叉查找树</title><link>http://www.cppblog.com/cxiaojia/archive/2012/08/09/186752.html</link><dc:creator>C小加</dc:creator><author>C小加</author><pubDate>Thu, 09 Aug 2012 08:56:00 GMT</pubDate><guid>http://www.cppblog.com/cxiaojia/archive/2012/08/09/186752.html</guid><wfw:comment>http://www.cppblog.com/cxiaojia/comments/186752.html</wfw:comment><comments>http://www.cppblog.com/cxiaojia/archive/2012/08/09/186752.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.cppblog.com/cxiaojia/comments/commentRss/186752.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cxiaojia/services/trackbacks/186752.html</trackback:ping><description><![CDATA[<p align="center" style="text-align:center"><strong><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;"></span></strong></p><p align="center" style="text-align:center"></p><div style="text-align: center;"><strong>一步一步写二叉查找树</strong></div><p>&nbsp;</p>  <p align="center" style="text-align:center"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;color:red">作者：</span><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">C</span><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">小加 &nbsp;<span style="color:red">更新时间：</span>2012-8-9</span></p>  <p style="text-indent:21.0pt;"><span style="font-family:宋体;">二叉查找树（</span>BST<span style="font-family:宋体;">）是二叉树的一个重要的应用，它在二叉树的基础上加上了这样的一个性质：对于树中的每一个节点来说，如果有左儿子的话，它的左儿子的值一定小于它本身的值，如果有右儿子的话，它的右儿子的值一定大于它本身的值。</span></p>  <p style="text-indent:21.0pt;"><span style="font-family:宋体;">二叉查找树的操作一般有插入、删除和查找，这几个操作的平均时间复杂度都为</span>O(logn)<span style="font-family:宋体;">，插入和查找操作很简单，删除操作会复杂一点，除此之外，因为二叉树的中序遍历是一个有序序列，我就额外加上了一个中序遍历操作。</span></p>  <p style="text-indent:21.0pt;"><span style="font-family:宋体;">二叉查找树的应用不是很多，因为它最坏的时候跟线性表差不多，大部分会应用到它的升级版，平衡二叉树和红黑树，这两棵树都能把时间复杂度稳定在</span>O(logn)<span style="font-family:宋体;">左右。虽然不会用到，但是二叉查找树是一定要学好的，毕竟它是平衡二叉树和红黑树的基础。</span></p>  <p><span style="font-family:宋体;">接下来一步一步写一个二叉查找树模板。<a href="/Files/cxiaojia/bst.zip">完整代码下载</a></span></p>  <p><strong><span style="font-family:宋体;">第一步：节点信息</span></strong></p>  <p style="text-indent:21.0pt;"><span style="font-family:宋体;">二叉查找树的节点和二叉树的节点大部分是一样的，不同的是，二叉查找树多了一个值出现的次数。如图</span>1<span style="font-family:宋体;">显示了二叉查找树的节点信息。<br /><img src="http://www.cppblog.com/images/cppblog_com/cxiaojia/bst1.png" width="600" height="148" alt="" /><br /></span></p>  <p><span style="font-family:宋体;">代码如下：</span></p>  <p>&nbsp;</p><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008000; ">//</span><span style="color: #008000; ">二叉查找树节点信息</span><span style="color: #008000; "><br /></span>template&lt;<span style="color: #0000FF; ">class</span>&nbsp;T&gt;<br /><span style="color: #0000FF; ">class</span>&nbsp;TreeNode<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TreeNode():lson(NULL),rson(NULL),freq(1){}<span style="color: #008000; ">//</span><span style="color: #008000; ">初始化</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;T&nbsp;data;<span style="color: #008000; ">//</span><span style="color: #008000; ">值</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;freq;<span style="color: #008000; ">//</span><span style="color: #008000; ">频率</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TreeNode*&nbsp;lson;<span style="color: #008000; ">//</span><span style="color: #008000; ">指向左儿子的坐标</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TreeNode*&nbsp;rson;<span style="color: #008000; ">//</span><span style="color: #008000; ">指向右儿子的坐标</span><span style="color: #008000; "><br /></span>};</div><p>&nbsp;</p>  <p><strong><span style="font-family:宋体;">第二步：二叉查找树类的声明</span></strong></p>  <p><span style="font-family:宋体;">代码如下：</span></p>  <p>&nbsp;</p><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008000; ">//</span><span style="color: #008000; ">二叉查找树类的属性和方法声明</span><span style="color: #008000; "><br /></span>template&lt;<span style="color: #0000FF; ">class</span>&nbsp;T&gt;<br /><span style="color: #0000FF; ">class</span>&nbsp;BST<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">private</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TreeNode&lt;T&gt;*&nbsp;root;<span style="color: #008000; ">//</span><span style="color: #008000; ">根节点</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;insertpri(TreeNode&lt;T&gt;*&nbsp;&amp;node,T&nbsp;x);<span style="color: #008000; ">//</span><span style="color: #008000; ">插入</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TreeNode&lt;T&gt;*&nbsp;findpri(TreeNode&lt;T&gt;*&nbsp;node,T&nbsp;x);<span style="color: #008000; ">//</span><span style="color: #008000; ">查找</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;insubtree(TreeNode&lt;T&gt;*&nbsp;node);<span style="color: #008000; ">//</span><span style="color: #008000; ">中序遍历</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;Deletepri(TreeNode&lt;T&gt;*&nbsp;&amp;node,T&nbsp;x);<span style="color: #008000; ">//</span><span style="color: #008000; ">删除</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;BST():root(NULL){}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;insert(T&nbsp;x);<span style="color: #008000; ">//</span><span style="color: #008000; ">插入接口</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TreeNode&lt;T&gt;*&nbsp;find(T&nbsp;x);<span style="color: #008000; ">//</span><span style="color: #008000; ">查找接口</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;Delete(T&nbsp;x);<span style="color: #008000; ">//</span><span style="color: #008000; ">删除接口</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;traversal();<span style="color: #008000; ">//</span><span style="color: #008000; ">遍历接口</span><span style="color: #008000; "><br /></span>&nbsp;<br />};</div><p>&nbsp;</p>  <p><strong><span style="font-family:宋体;">第三步：插入</span></strong></p>  <p style="text-indent:21.0pt;"><span style="font-family:宋体;">根据二叉查找树的性质，插入一个节点的时候，如果根节点为空，就此节点作为根节点，如果根节点不为空，就要先和根节点比较，如果比根节点的值小，就插入到根节点的左子树中，如果比根节点的值大就插入到根节点的右子树中，如此递归下去，找到插入的位置。重复节点的插入用值域中的</span>freq<span style="font-family:宋体;">标记。如图</span>2<span style="font-family:宋体;">是一个插入的过程。</span></p>  <p><img src="http://www.cppblog.com/images/cppblog_com/cxiaojia/bst2.png" width="634" height="506" alt="" /><br /></p>  <p style="text-indent:21.0pt;"><span style="font-family:宋体;">二叉查找树的时间复杂度要看这棵树的形态，如果比较接近一一棵完全二叉树，那么时间复杂度在</span>O(logn)<span style="font-family:宋体;">左右，如果遇到如图</span>3<span style="font-family:宋体;">这样的二叉树的话，那么时间复杂度就会恢复到线性的</span>O(n)<span style="font-family:宋体;">了。</span></p>  <p><img src="http://www.cppblog.com/images/cppblog_com/cxiaojia/bst3.png" width="216" height="234" alt="" /><br /></p>  <p style="text-indent:21.0pt;"><span style="font-family:宋体;">平衡二叉树会很好的解决如图</span>3<span style="font-family:宋体;">这种情况。</span></p>  <p><span style="font-family:宋体;">插入函数的代码如下：</span></p>  <p>&nbsp;</p><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008000; ">//</span><span style="color: #008000; ">插入</span><span style="color: #008000; "><br /></span>template&lt;<span style="color: #0000FF; ">class</span>&nbsp;T&gt;<br /><span style="color: #0000FF; ">void</span>&nbsp;BST&lt;T&gt;::insertpri(TreeNode&lt;T&gt;*&nbsp;&amp;node,T&nbsp;x)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(node==NULL)<span style="color: #008000; ">//</span><span style="color: #008000; ">如果节点为空,就在此节点处加入x信息</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;node=<span style="color: #0000FF; ">new</span>&nbsp;TreeNode&lt;T&gt;();<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;node-&gt;data=x;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(node-&gt;data&gt;x)<span style="color: #008000; ">//</span><span style="color: #008000; ">如果x小于节点的值,就继续在节点的左子树中插入x</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;insertpri(node-&gt;lson,x);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">else</span>&nbsp;<span style="color: #0000FF; ">if</span>(node-&gt;data&lt;x)<span style="color: #008000; ">//</span><span style="color: #008000; ">如果x大于节点的值,就继续在节点的右子树中插入x</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;insertpri(node-&gt;rson,x);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">else</span>&nbsp;++(node-&gt;freq);<span style="color: #008000; ">//</span><span style="color: #008000; ">如果相等,就把频率加1</span><span style="color: #008000; "><br /></span>}<br /><span style="color: #008000; ">//</span><span style="color: #008000; ">插入接口</span><span style="color: #008000; "><br /></span>template&lt;<span style="color: #0000FF; ">class</span>&nbsp;T&gt;<br /><span style="color: #0000FF; ">void</span>&nbsp;BST&lt;T&gt;::insert(T&nbsp;x)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;insertpri(root,x);<br />}</div><p>&nbsp;</p>  <p><strong><span style="font-family:宋体;">第四步：查找</span></strong></p>  <p style="text-indent:21.0pt;"><span style="font-family:宋体;">查找的功能和插入差不多一样，按照插入那样的方式递归下去，如果找到了，就返回这个节点的地址，如果没有找到，就返回</span>NULL<span style="font-family:宋体;">。</span></p>  <p><span style="font-family:宋体;">代码如下：</span></p>  <p>&nbsp;</p><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008000; ">//</span><span style="color: #008000; ">查找</span><span style="color: #008000; "><br /></span>template&lt;<span style="color: #0000FF; ">class</span>&nbsp;T&gt;<br />TreeNode&lt;T&gt;*&nbsp;BST&lt;T&gt;::findpri(TreeNode&lt;T&gt;*&nbsp;node,T&nbsp;x)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(node==NULL)<span style="color: #008000; ">//</span><span style="color: #008000; ">如果节点为空说明没找到,返回NULL</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;NULL;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(node-&gt;data&gt;x)<span style="color: #008000; ">//</span><span style="color: #008000; ">如果x小于节点的值,就继续在节点的左子树中查找x</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;findpri(node-&gt;lson,x);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">else</span>&nbsp;<span style="color: #0000FF; ">if</span>(node-&gt;data&lt;x)<span style="color: #008000; ">//</span><span style="color: #008000; ">如果x大于节点的值,就继续在节点的左子树中查找x</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;findpri(node-&gt;rson,x);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">else</span>&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;node;<span style="color: #008000; ">//</span><span style="color: #008000; ">如果相等,就找到了此节点</span><span style="color: #008000; "><br /></span>}<br /><span style="color: #008000; ">//</span><span style="color: #008000; ">查找接口</span><span style="color: #008000; "><br /></span>template&lt;<span style="color: #0000FF; ">class</span>&nbsp;T&gt;<br />TreeNode&lt;T&gt;*&nbsp;BST&lt;T&gt;::find(T&nbsp;x)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;findpri(root,x);<br />}</div><p>&nbsp;</p>  <p><strong><span style="font-family:宋体;">第五步：删除</span></strong></p>  <p style="text-indent:21.0pt;"><span style="font-family:宋体;">删除会麻烦一点，如果是叶子节点的话，直接删除就可以了。如果只有一个孩子的话，就让它的父亲指向它的儿子，然后删除这个节点。图</span>4<span style="font-family:宋体;">显示了一棵初始树和</span>4<span style="font-family:宋体;">节点被删除后的结果。先用一个临时指针指向</span>4<span style="font-family:宋体;">节点，再让</span>4<span style="font-family:宋体;">节点的地址指向它的孩子，这个时候</span>2<span style="font-family:宋体;">节点的右儿子就变成了</span>3<span style="font-family:宋体;">节点，最后删除临时节点指向的空间，也就是</span>4<span style="font-family:宋体;">节点。</span></p>  <p>&nbsp;<img src="http://www.cppblog.com/images/cppblog_com/cxiaojia/bst4.png" width="431" height="241" alt="" /></p>  <p><span style="font-family:宋体;">&nbsp; &nbsp; 删除有两个儿子的节点会比较复杂一些。一般的删除策略是用其右子树最小的数据代替该节点的数据并递归的删除掉右子树中最小数据的节点。因为右子树中数据最小的节点肯定没有左儿子，所以删除的时候容易一些。图</span>5<span style="font-family:宋体;">显示了一棵初始树和</span>2<span style="font-family:宋体;">节点被删除后的结果。首先在</span>2<span style="font-family:宋体;">节点的右子树中找到最小的节点</span>3<span style="font-family:宋体;">，然后把</span>3<span style="font-family:宋体;">的数据赋值给</span>2<span style="font-family:宋体;">节点，这个时候</span>2<span style="font-family:宋体;">节点的数据变为</span>3<span style="font-family:宋体;">，然后的工作就是删除右子树中的</span>3<span style="font-family:宋体;">节点了，采用递归删除。</span></p>  <p><img src="http://www.cppblog.com/images/cppblog_com/cxiaojia/bst5.png" width="431" height="239" alt="" /><br /></p>  <p><span style="font-family:宋体;">&nbsp; &nbsp; 我们发现对</span>2<span style="font-family:宋体;">节点右子树的查找进行了两遍，第一遍找到最小节点并赋值，第二遍删除这个最小的节点，这样的效率并不是很高。你能不能写出只查找一次就可以实现赋值和删除两个功能的函数呢？</span></p>  <p><span style="font-family:宋体;">&nbsp; &nbsp; 如果删除的次数不是很多的话，有一种删除的方法会比较快一点，名字叫懒惰删除法：当一个元素要被删除时，它仍留在树中，只是多了一个删除的标记。这种方法的优点是删除那一步的时间开销就可以避免了，如果重新插入删除的节点的话，插入时也避免了分配空间的时间开销。缺点是树的深度会增加，查找的时间复杂度会增加，插入的时间可能会增加。</span></p>  <p><span style="font-family:宋体;">删除函数代码如下：</span></p>  <p>&nbsp;</p><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008000; ">//</span><span style="color: #008000; ">删除</span><span style="color: #008000; "><br /></span>template&lt;<span style="color: #0000FF; ">class</span>&nbsp;T&gt;<br /><span style="color: #0000FF; ">void</span>&nbsp;BST&lt;T&gt;::Deletepri(TreeNode&lt;T&gt;*&nbsp;&amp;node,T&nbsp;x)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(node==NULL)&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;;<span style="color: #008000; ">//</span><span style="color: #008000; ">没有找到值是x的节点</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(x&nbsp;&lt;&nbsp;node-&gt;data)<br />&nbsp;&nbsp;&nbsp;&nbsp;Deletepri(node-&gt;lson,x);<span style="color: #008000; ">//</span><span style="color: #008000; ">如果x小于节点的值,就继续在节点的左子树中删除x</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">else</span>&nbsp;<span style="color: #0000FF; ">if</span>(x&nbsp;&gt;&nbsp;node-&gt;data)<br />&nbsp;&nbsp;&nbsp;&nbsp;Deletepri(node-&gt;rson,x);<span style="color: #008000; ">//</span><span style="color: #008000; ">如果x大于节点的值,就继续在节点的右子树中删除x</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">else</span><span style="color: #008000; ">//</span><span style="color: #008000; ">如果相等,此节点就是要删除的节点</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(node-&gt;lson&amp;&amp;node-&gt;rson)<span style="color: #008000; ">//</span><span style="color: #008000; ">此节点有两个儿子</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TreeNode&lt;T&gt;*&nbsp;temp=node-&gt;rson;<span style="color: #008000; ">//</span><span style="color: #008000; ">temp指向节点的右儿子</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">while</span>(temp-&gt;lson!=NULL)&nbsp;temp=temp-&gt;lson;<span style="color: #008000; ">//</span><span style="color: #008000; ">找到右子树中值最小的节点<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span><span style="color: #008000; ">//</span><span style="color: #008000; ">把右子树中最小节点的值赋值给本节点</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;node-&gt;data=temp-&gt;data;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;node-&gt;freq=temp-&gt;freq;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;Deletepri(node-&gt;rson,temp-&gt;data);<span style="color: #008000; ">//</span><span style="color: #008000; ">删除右子树中最小值的节点</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">else</span><span style="color: #008000; ">//</span><span style="color: #008000; ">此节点有1个或0个儿子</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;TreeNode&lt;T&gt;*&nbsp;temp=node;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(node-&gt;lson==NULL)<span style="color: #008000; ">//</span><span style="color: #008000; ">有右儿子或者没有儿子</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;node=node-&gt;rson;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">else</span>&nbsp;<span style="color: #0000FF; ">if</span>(node-&gt;rson==NULL)<span style="color: #008000; ">//</span><span style="color: #008000; ">有左儿子</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;node=node-&gt;lson;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;delete(temp);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>;<br />}<br /><span style="color: #008000; ">//</span><span style="color: #008000; ">删除接口</span><span style="color: #008000; "><br /></span>template&lt;<span style="color: #0000FF; ">class</span>&nbsp;T&gt;<br /><span style="color: #0000FF; ">void</span>&nbsp;BST&lt;T&gt;::Delete(T&nbsp;x)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;Deletepri(root,x);<br />}</div><p>&nbsp;</p>  <p><strong><span style="font-family:宋体;">第六步：中序遍历</span></strong></p>  <p style="text-indent:21.0pt;"><span style="font-family:宋体;">遍历的方法和二叉树的方法一样，写这个方法的目的呢，是输出这个二叉查找树的有序序列。</span></p>  <p><span style="font-family:宋体;">代码如下：</span></p>  <p>&nbsp;</p><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #008000; ">//</span><span style="color: #008000; ">中序遍历函数</span><span style="color: #008000; "><br /></span>template&lt;<span style="color: #0000FF; ">class</span>&nbsp;T&gt;<br /><span style="color: #0000FF; ">void</span>&nbsp;BST&lt;T&gt;::insubtree(TreeNode&lt;T&gt;*&nbsp;node)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(node==NULL)&nbsp;<span style="color: #0000FF; ">return</span>;<br />&nbsp;&nbsp;&nbsp;&nbsp;insubtree(node-&gt;lson);<span style="color: #008000; ">//</span><span style="color: #008000; ">先遍历左子树</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;cout&lt;&lt;node-&gt;data&lt;&lt;"&nbsp;";<span style="color: #008000; ">//</span><span style="color: #008000; ">输出根节点</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;insubtree(node-&gt;rson);<span style="color: #008000; ">//</span><span style="color: #008000; ">再遍历右子树</span><span style="color: #008000; "><br /></span>}<br /><span style="color: #008000; ">//</span><span style="color: #008000; ">中序遍历接口</span><span style="color: #008000; "><br /></span>template&lt;<span style="color: #0000FF; ">class</span>&nbsp;T&gt;<br /><span style="color: #0000FF; ">void</span>&nbsp;BST&lt;T&gt;::traversal()<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;insubtree(root);<br />}</div><p>&nbsp;</p>  <p style="text-indent:21.0pt;"><span style="font-family:宋体;">到此，整个代码就完成了，代码中肯定有很多不完善的地方请指出，我会加以完善，谢谢。</span></p>  <p>&nbsp;&nbsp;&nbsp;&nbsp;</p>  <p style="text-indent:21.0pt;"><span style="font-family:宋体;">对于二叉查找树不稳定的时间复杂度的解决方案有不少，平衡二叉树、伸展树和红黑树都可以解决这个问题，但效果是不一样的。</span></p><p><span style="font-family:宋体;"></span></p><img src ="http://www.cppblog.com/cxiaojia/aggbug/186752.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cxiaojia/" target="_blank">C小加</a> 2012-08-09 16:56 <a href="http://www.cppblog.com/cxiaojia/archive/2012/08/09/186752.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>基本数据结构：二叉树（binary tree）</title><link>http://www.cppblog.com/cxiaojia/archive/2012/08/06/186432.html</link><dc:creator>C小加</dc:creator><author>C小加</author><pubDate>Mon, 06 Aug 2012 03:26:00 GMT</pubDate><guid>http://www.cppblog.com/cxiaojia/archive/2012/08/06/186432.html</guid><wfw:comment>http://www.cppblog.com/cxiaojia/comments/186432.html</wfw:comment><comments>http://www.cppblog.com/cxiaojia/archive/2012/08/06/186432.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.cppblog.com/cxiaojia/comments/commentRss/186432.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cxiaojia/services/trackbacks/186432.html</trackback:ping><description><![CDATA[<p align="center" style="text-align:center"><strong><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">基本数据结构：二叉树（binary tree）</span></strong></p>  <p align="center" style="text-align:center"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;color:red">作者：</span><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">C</span><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">小加 &nbsp;<span style="color:red">更新时间：</span>2012-8-6</span></p>  <p><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">二叉树首先是一棵树，每个节点都不能有多于两个的儿子，也就是树的度不能超过2。二叉树的两个儿子分别称为&#8220;左儿子&#8221;和&#8220;右儿子&#8221;，次序不能颠倒。如图1是一个简单的二叉树。<br /><img src="http://www.cppblog.com/images/cppblog_com/cxiaojia/bintree1.png" width="889" height="373" alt="" /><br /></span></p>  <p> </p>  <p><strong><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">二叉树的种类</span></strong></p>  <p style="text-indent:21.0pt;"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">一种是满二叉树，除了最后一层的叶子节点外，每一层的节点都必须有两个儿子节点。如图2是一个满二叉树。<br /><img src="http://www.cppblog.com/images/cppblog_com/cxiaojia/bintree2.png" width="889" height="360" alt="" /><br /></span></p>  <p> </p>  <p style="text-indent:26.25pt;"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">另一种是完全二叉树，一棵二叉树去掉最后一层后剩下的节点组成的树为满二叉树，最后一层的节点从左到右连续，没有空出的节点，这样的树称为完全二叉树。如图3是一棵完全二叉树。<br /><img src="http://www.cppblog.com/images/cppblog_com/cxiaojia/bintree_3.png" width="919" height="353" alt="" /><br /></span></p>  <p> </p>  <p><strong><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">二叉树的实现</span></strong></p>  <p style="text-indent:26.25pt;"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">因为一棵树有最多只有两个儿子，所以我们可以用指针直接指向他们。一个节点包括值（data）、指向左儿子的指针（lson）和指向右儿子的指针（rson）。</span></p>  <p><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; ">struct</span>&nbsp;treenode<br />{<br /><span style="color: #0000FF; ">int</span>&nbsp;data;<br /><span style="color: #0000FF; ">struct</span>&nbsp;treenode*&nbsp;lson;<br /><span style="color: #0000FF; ">struct</span>&nbsp;treenode*&nbsp;rson;<br />&nbsp;<br />}</div></p>  <p style="text-indent:21.0pt;"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">二叉树的插入,删除,查找和链表差不多,不同的是需要指定是左儿子还是右儿子。</span></p>  <p style="text-indent:21.0pt;"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">二叉树的数组实现也很简单，假如说根节点在arr[0]这个位置，那么它的左儿子就在arr[2*0+1]，也就是arr[1]这个位置，它的右儿子在arr[2*0+2] ，也就是arr[2]这个位置。对于下标为i的节点来说，它的左儿子的下标为2*i+1，右儿子的下标为2*i+2。</span></p>  <p style="text-indent:21.0pt;"><strong><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">二叉树的遍历</span></strong></p>  <p style="text-indent:21.0pt;"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">二叉树的遍历有三种，分别为先序遍历，中序遍历和后序遍历。这三种遍历方式是根据根节点的读取顺序来分的：</span></p>  <p style="text-indent:21.0pt;"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">先序遍历，就是最先读取根节点，然后再读取左子树（按照同样的方法读取子树上的节点），最后读取右子树；</span></p>  <p style="text-indent:21.0pt;"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">中序遍历，就是第二个读取根节点，最先要读取的是左子树，然后根节点，最后右子树；</span></p>  <p style="text-indent:21.0pt;"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">后序遍历，就是最后一个读取根节点，最先读取的是左子树，第二个读取右子树，最后读取根节点。</span></p>  <p style="text-indent:21.0pt;"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">先序遍历的递归实现代码：</span></p>  <p><div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all; "><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; ">void</span>&nbsp;insubtree（<span style="color: #0000FF; ">struct</span>&nbsp;treenode*&nbsp;tree）<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;If(tree==NULL)&nbsp;<span style="color: #0000FF; ">return</span>;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout&lt;&lt;tree-&gt;data;<br />&nbsp;&nbsp;&nbsp;&nbsp;insubtree(tree-&gt;lson);<br />insubtree(tree-&gt;rson);<br />}</div></p>  <p style="text-indent:21.0pt;">&nbsp;</p><img src ="http://www.cppblog.com/cxiaojia/aggbug/186432.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cxiaojia/" target="_blank">C小加</a> 2012-08-06 11:26 <a href="http://www.cppblog.com/cxiaojia/archive/2012/08/06/186432.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>基本数据结构：树（tree）</title><link>http://www.cppblog.com/cxiaojia/archive/2012/08/03/186123.html</link><dc:creator>C小加</dc:creator><author>C小加</author><pubDate>Fri, 03 Aug 2012 01:18:00 GMT</pubDate><guid>http://www.cppblog.com/cxiaojia/archive/2012/08/03/186123.html</guid><wfw:comment>http://www.cppblog.com/cxiaojia/comments/186123.html</wfw:comment><comments>http://www.cppblog.com/cxiaojia/archive/2012/08/03/186123.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/cxiaojia/comments/commentRss/186123.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cxiaojia/services/trackbacks/186123.html</trackback:ping><description><![CDATA[<p align="center" style="text-align:center"><strong><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">基本数据结构：树（tree）</span></strong></p>  <p align="center" style="text-align:center"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;color:red">作者：</span><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">C</span><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">小加 <span style="color:red">更新时间：</span>2012-8-3</span></p>  <p style="text-indent:21.0pt;"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">无论是链表，栈还是队列，它们都是线性结构的，每个节点的左边最多一个节点，右边也最多一个节点，对于大量的输入数据，线性表的访问时间太慢，不宜使用。这里我要说一种非线性的数据结构，其大部分操作的运行时间平均为O(logn)。</span></p>  <p style="text-indent:21.0pt;"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">我们涉及到的这种数据结构叫做树。在计算机科学中，树是非常有用的抽象概念。我们形象的去描述一棵树，一个家族的老祖可能有两个儿子，这两个儿子一个有一个儿子，一个有三个儿子，像这样发展下去的一个族谱，就是一个树，如图1所示。</span></p>  <p><img src="http://www.cppblog.com/images/cppblog_com/cxiaojia/tree_1.png" border="0" alt="" width="889" height="378" /><br /><br /></p>  <p style="text-indent:21.0pt;"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">就像一棵真正的树一样，我们把老祖称为树根,两个字儿是分叉开的两个树枝，这两棵树枝可以继续向下分成N个树枝，循环下去，一直到长出叶子为止。</span></p>  <p style="text-indent:21.0pt;"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">我们把老祖或者树根称为根（root）节点，老祖的儿子称为子节点，每个儿子作为根节点又可以形成一棵树，我们把这样的树称为根节点的子树。</span></p>  <p style="text-indent:21.0pt;"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">树的标准定义：</span></p>  <p align="left" style="text-indent: 21pt; "><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;">树（tree）是包含n（n&gt;0）个节点的有穷集合，其中：</span></p>  <p align="left"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">　　（1）每个元素称为节点（node）；</span></p>  <p align="left"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">　　（2）有一个特定的节点被称为根节点或树根（root）。</span></p>  <p align="left" style="text-indent: 21pt; "><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;">（3）除根节点之外的其余数据元素被分为m（m&#8805;0）个互不相交的结合T1，T2，&#8230;&#8230;Tm-1，其中每一个集合Ti（1&lt;=i&lt;=m）本身也是一棵树，被称作原树的子树（subtree）。</span></p>  <p align="left" style="text-indent: 26.25pt; "><span style="font-family: &quot;微软雅黑&quot;,&quot;sans-serif&quot;">树具有以下特点：</span></p>  <p align="left" style="margin-left: 57pt; text-indent: -36pt; "><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;">（1）<span style="font-size: 7pt; line-height: normal; font-family: 'Times New Roman'; ">&nbsp;&nbsp;&nbsp; </span></span><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">每个节点有零个或多个子节点。</span></p>  <p align="left" style="margin-left: 57pt; text-indent: -36pt; "><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;">（2）<span style="font-size: 7pt; line-height: normal; font-family: 'Times New Roman'; ">&nbsp;&nbsp;&nbsp; </span></span><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">每个子节点只有一个父节点。</span></p>  <p align="left" style="margin-left: 57pt; text-indent: -36pt; "><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;">（3）<span style="font-size: 7pt; line-height: normal; font-family: 'Times New Roman'; ">&nbsp;&nbsp;&nbsp; </span></span><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">没有父节点的节点称为根节点。</span></p>  <p align="left"><strong><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">关于树的一些术语</span></strong></p>  <p align="left"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">&nbsp; &nbsp; &nbsp; &nbsp; 节点的度：一个节点含有的子树的个数称为该节点的度；</span></p>  <p align="left"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">&nbsp; &nbsp; &nbsp; &nbsp; 叶节点或终端节点：度为零的节点称为叶节点；</span></p>  <p align="left"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">&nbsp; &nbsp; &nbsp; &nbsp; 非终端节点或分支节点：度不为零的节点；</span></p>  <p align="left"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">&nbsp; &nbsp; &nbsp; &nbsp; 双亲节点或父节点：若一个结点含有子节点，则这个节点称为其子节点的父节点；</span></p>  <p align="left"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">&nbsp; &nbsp; &nbsp; &nbsp; 孩子节点或子节点：一个节点含有的子树的根节点称为该节点的子节点；</span></p>  <p align="left"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">&nbsp; &nbsp; &nbsp; &nbsp; 兄弟节点：具有相同父节点的节点互称为兄弟节点；</span></p>  <p align="left"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">&nbsp; &nbsp; &nbsp; &nbsp; 树的高度或深度：定义一棵树的根结点层次为1，其他节点的层次是其父结点层次加1。一棵树中所有结点的层次的最大值称为这棵树的深度。节点的层次：从根开始定义起，根为第1层，根的子结点为第2层，以此类推；</span></p>  <p align="left"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">&nbsp; &nbsp; &nbsp; &nbsp; 树的度：一棵树中，最大的节点的度称为树的度；</span></p>  <p align="left"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">&nbsp; &nbsp; &nbsp; &nbsp; 节点的祖先：从根到该节点所经分支上的所有节点；</span></p>  <p align="left"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">&nbsp; &nbsp; &nbsp; &nbsp; 子孙：以某节点为根的子树中任一节点都称为该节点的子孙。</span></p>  <p align="left"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">&nbsp; &nbsp; &nbsp; &nbsp; 森林：由m（m&gt;=0）棵互不相交的树的集合称为森林；</span></p>  <p align="left"><strong><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">树的实现</span></strong></p>  <p align="left"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">节点的代码如下:</span></p>  <p align="left"><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><span style="color: #0000FF; ">struct</span>&nbsp;treenode<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;data;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">struct</span>&nbsp;treenode&nbsp;*fistchild;<span style="color: #008000; ">//</span><span style="color: #008000; ">第一个儿子</span><span style="color: #008000; "><br /></span><span style="color: #0000FF; ">struct</span>&nbsp;treenode&nbsp;*nextsibling;<span style="color: #008000; ">//</span><span style="color: #008000; ">下一个兄弟</span><span style="color: #008000; "><br /></span>}</div></p>  <p align="left"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;"><strong>树的应用</strong></span></p>  <p align="left"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">&nbsp; &nbsp; &nbsp; &nbsp;大部分操作系统的目录结构就是采用树结构。</span></p>  <p align="left"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">&nbsp; &nbsp; &nbsp; &nbsp;树的种类有很多，树所扩展出来的很多数据结构都有着很大的作用，比如说红黑树，B树，后缀树等等，这将在日后写到。</span></p><img src ="http://www.cppblog.com/cxiaojia/aggbug/186123.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cxiaojia/" target="_blank">C小加</a> 2012-08-03 09:18 <a href="http://www.cppblog.com/cxiaojia/archive/2012/08/03/186123.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>基本数据结构：队列（queue）</title><link>http://www.cppblog.com/cxiaojia/archive/2012/08/02/186033.html</link><dc:creator>C小加</dc:creator><author>C小加</author><pubDate>Thu, 02 Aug 2012 07:00:00 GMT</pubDate><guid>http://www.cppblog.com/cxiaojia/archive/2012/08/02/186033.html</guid><wfw:comment>http://www.cppblog.com/cxiaojia/comments/186033.html</wfw:comment><comments>http://www.cppblog.com/cxiaojia/archive/2012/08/02/186033.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/cxiaojia/comments/commentRss/186033.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cxiaojia/services/trackbacks/186033.html</trackback:ping><description><![CDATA[<p align="center" style="text-align:center"><strong><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">基本数据结构：队列（queue）</span></strong></p>  <p align="center" style="text-align:center"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;color:red">作者：</span><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">C</span><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">小加 <span style="color:red">更新时间：</span>2012-8-2</span></p>  <p style="text-indent:21.0pt;"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">像栈一样，队列（queue）也是一种线性表，它的特性是先进先出，插入在一端，删除在另一端。就像排队一样，刚来的人入队（push）要排在队尾(rear)，每次出队(pop)的都是队首(front)的人。如图1，描述了一个队列模型。</span></p>  <p><img src="http://www.cppblog.com/images/cppblog_com/cxiaojia/queue1.png" border="0" alt="" width="806" height="269" /><br /></p>  <p style="text-indent:21.0pt;"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">和栈一样，队列也有数组实现和链表实现两种，两种实现都能给出快速的O(1)运行时间，区别在于链表实现指针域要占用空间，频繁的new和delete会消耗不少的时间开销，数组实现唯一的缺点是建立时要确定空间大小。</span></p>  <p style="text-indent:21.0pt;"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">假如一个队列最多只能站10个人，当占满10个人后，第11个人就不能入队，这种情况成为溢出。而如果第一个人出队了，剩下的9个人依然还在原来的位置，队列里空出了一个位置，但第11个人还是不能入队，这种情况成为假溢出。克服假溢出有效的办法是使用循环队列。</span></p>  <p style="text-indent:21.0pt;"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">循环队列就是把队尾和队首连接起来，形成一个环，队尾的下一个位置就是队首，这样可以有效的防止假溢出现象，但队列的实际容量已然固定。</span></p>  <p style="text-indent:21.0pt;"><strong><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">队列的实现</span></strong></p>  <p style="text-indent:21.0pt;"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">队列的数组实现和栈差不多，不同的是，栈用top做下标，队列用front和rear作为下标。</span></p>  <p style="text-indent:21.0pt;"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">我更改了单链表的模板来实现一个简单的队列。代码仅供学习，不足之处还请指明，我会对不足之处进行修改和更新。</span></p>  <p style="text-indent:21.0pt;"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">代码如下：<br /></span></p><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->template&lt;<span style="color: #0000FF; ">class</span>&nbsp;T&gt;<br /><span style="color: #0000FF; ">class</span>&nbsp;queueNode<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;queueNode():next(NULL){}<br />&nbsp;&nbsp;&nbsp;&nbsp;T&nbsp;data;<span style="color: #008000; ">//</span><span style="color: #008000; ">值</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;queueNode*&nbsp;next;<span style="color: #008000; ">//</span><span style="color: #008000; ">指向下一个节点的指针</span><span style="color: #008000; "><br /></span>};<br />template&lt;<span style="color: #0000FF; ">class</span>&nbsp;T&gt;<br /><span style="color: #0000FF; ">class</span>&nbsp;myqueue<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">private</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;queuelength;<br />&nbsp;&nbsp;&nbsp;&nbsp;queueNode&lt;T&gt;*&nbsp;node;<span style="color: #008000; ">//</span><span style="color: #008000; ">临时节点</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;queueNode&lt;T&gt;*&nbsp;rear;<span style="color: #008000; ">//</span><span style="color: #008000; ">队尾</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;queueNode&lt;T&gt;*&nbsp;front;<span style="color: #008000; ">//</span><span style="color: #008000; ">队首</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;myqueue();<span style="color: #008000; ">//</span><span style="color: #008000; ">初始化</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;length();<span style="color: #008000; ">//</span><span style="color: #008000; ">队列元素的个数</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;push(T&nbsp;x);<span style="color: #008000; ">//</span><span style="color: #008000; ">入队</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">bool</span>&nbsp;isEmpty();<span style="color: #008000; ">//</span><span style="color: #008000; ">判断队列是否为空</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;pop();<span style="color: #008000; ">//</span><span style="color: #008000; ">出队</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;T&nbsp;getHead();<span style="color: #008000; ">//</span><span style="color: #008000; ">获得队首元素</span><span style="color: #008000; "><br /></span>&nbsp;<br />};<br />template&lt;<span style="color: #0000FF; ">class</span>&nbsp;T&gt;<br />myqueue&lt;T&gt;::myqueue()<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;node=NULL;<br />&nbsp;&nbsp;&nbsp;&nbsp;rear=NULL;<br />&nbsp;&nbsp;&nbsp;&nbsp;front=NULL;<br />&nbsp;&nbsp;&nbsp;&nbsp;queuelength=0;<br />}<br />template&lt;<span style="color: #0000FF; ">class</span>&nbsp;T&gt;<br />inline&nbsp;unsigned&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;myqueue&lt;T&gt;::length(){<span style="color: #0000FF; ">return</span>&nbsp;queuelength;}<br />&nbsp;<br />template&lt;<span style="color: #0000FF; ">class</span>&nbsp;T&gt;<br /><span style="color: #0000FF; ">void</span>&nbsp;&nbsp;myqueue&lt;T&gt;::push(T&nbsp;x)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;node=<span style="color: #0000FF; ">new</span>&nbsp;queueNode&lt;T&gt;();<span style="color: #008000; ">//</span><span style="color: #008000; ">申请一个新的节点</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;node-&gt;data=x;<span style="color: #008000; ">//</span><span style="color: #008000; ">新节点赋值为x</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(rear==NULL)<span style="color: #008000; ">//</span><span style="color: #008000; ">如果没有尾节点则队列为空,node既为队首,又是队尾</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;front=node;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rear=node;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">else</span><span style="color: #008000; ">//</span><span style="color: #008000; ">如果队列非空</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rear-&gt;next=node;<span style="color: #008000; ">//</span><span style="color: #008000; ">node既为尾节点的下一个节点</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;rear=node;<span style="color: #008000; ">//</span><span style="color: #008000; ">node变成了尾节点,把尾节点赋值为node</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;++queuelength;<span style="color: #008000; ">//</span><span style="color: #008000; ">元素个数+1</span><span style="color: #008000; "><br /></span>}<br />template&lt;<span style="color: #0000FF; ">class</span>&nbsp;T&gt;<br /><span style="color: #0000FF; ">bool</span>&nbsp;&nbsp;myqueue&lt;T&gt;::isEmpty()<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;queuelength==0;<br />}<br />template&lt;<span style="color: #0000FF; ">class</span>&nbsp;T&gt;<br /><span style="color: #0000FF; ">void</span>&nbsp;&nbsp;myqueue&lt;T&gt;::pop()<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(queuelength==0)&nbsp;<span style="color: #0000FF; ">return</span>;<br />&nbsp;&nbsp;&nbsp;&nbsp;node=front;<br />&nbsp;&nbsp;&nbsp;&nbsp;front=front-&gt;next;<br />&nbsp;&nbsp;&nbsp;&nbsp;delete(node);<br />&nbsp;&nbsp;&nbsp;&nbsp;--queuelength;<br />}<br />template&lt;<span style="color: #0000FF; ">class</span>&nbsp;T&gt;<br />T&nbsp;&nbsp;myqueue&lt;T&gt;::getHead()<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;front-&gt;data;<br />}</div><p>&nbsp;</p>  <p style="text-indent:21.0pt;"><strong><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">队列的应用<br /></span></strong></p>  <p style="text-indent:21.0pt;"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">打印机处理作业采用的就是队列结构，它们会按照提交的顺序排列起来。STL也给出了一个强大的队列，我们直接可以去用它。</span></p>  <p style="text-indent:21.0pt;"><strong><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">队列相关问题</span></strong></p>  <p style="text-indent:21.0pt;"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">如何用两个栈模拟一个队列，如果用两个队列模拟一个栈？</span></p><img src ="http://www.cppblog.com/cxiaojia/aggbug/186033.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cxiaojia/" target="_blank">C小加</a> 2012-08-02 15:00 <a href="http://www.cppblog.com/cxiaojia/archive/2012/08/02/186033.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>基本数据结构：栈（stack）</title><link>http://www.cppblog.com/cxiaojia/archive/2012/08/01/185913.html</link><dc:creator>C小加</dc:creator><author>C小加</author><pubDate>Wed, 01 Aug 2012 08:51:00 GMT</pubDate><guid>http://www.cppblog.com/cxiaojia/archive/2012/08/01/185913.html</guid><wfw:comment>http://www.cppblog.com/cxiaojia/comments/185913.html</wfw:comment><comments>http://www.cppblog.com/cxiaojia/archive/2012/08/01/185913.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/cxiaojia/comments/commentRss/185913.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cxiaojia/services/trackbacks/185913.html</trackback:ping><description><![CDATA[<p align="center" style="text-align:center"><strong><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">基本数据结构：栈（stack）</span></strong></p>  <p align="center" style="text-align:center"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;color:red">作者：</span><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">C</span><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">小加 <span style="color:red">更新时间：</span>2012-8-1</span></p>  <p style="text-indent:21.0pt;"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">栈（stack）是限制插入和删除只能在一个位置上进行的线性表，该位置在表的末端，叫做栈顶。添加元素只能在尾节点后添加，删除元素只能删除尾节点，查看节点也只能查看尾节点。添加、删除、查看依次为入栈（push）、出栈（pop）、栈顶节点（top）。形象的说，栈是一个先进后出（LIFO）表，先进去的节点要等到后边进去的节点出来才能出来。</span></p>  <p><img src="http://www.cppblog.com/images/cppblog_com/cxiaojia/stack_1.png" width="921" height="314" alt="" /><br /></p>  <p><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">如图1，是一个栈的形象图，top指针指向的是栈顶节点，所以我们可以通过top访问到2节点，但是0和1节点由于先于2进入这个表，所以是不可见的。如果把0节点当做头节点，2节点当做尾节点，那么栈限制了访问权限，只可以访问尾节点。</span></p>  <p><img src="http://www.cppblog.com/images/cppblog_com/cxiaojia/stack_2.png" width="922" height="298" alt="" /><br /></p>  <p><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">如图2，当添加一个节点3的时候，只能在栈顶节点，也就是尾节点后添加，这样3节点变成了栈顶，2节点变成了不可见节点，访问的时候只能访问到3节点。入栈时限制了插入地址，只能在栈顶添加节点。</span></p>  <p><img src="http://www.cppblog.com/images/cppblog_com/cxiaojia/stack_3.png" width="922" height="305" alt="" /><br /></p>  <p><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">当我们执行出栈的命令时，图2的栈顶元素是3节点，删除的时候只能允许删除栈顶的元素，这样子3节点被删除，top指向删除后的栈顶2节点，如图3所示。</span></p>  <p style="text-indent:21.0pt;"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">栈有两种是实现结构，一种是顺序存储结构，也就是利用数组实现，一种是链式存储结构，可以用单链表实现。数组实现栈很简单，用一个下标标记top来表示栈顶，top==-1时，栈空，top==0时，表示栈里只有一个元素，通过访问top为下标的数组元素即可。出栈top自减，入栈top自加就OK了。</span></p>  <p style="text-indent:21.0pt;"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">单链表实现栈要比单链表的实现简单点。我们通过在表的尾端插入来实现push，通过删除尾节点来实现pop，获取尾节点的元素来表示top。我修改了链表那一章的单链表代码，把头节点当做栈顶节点，实现了一个简单的栈模板，仅供学习所用。代码会不定时更新。<a href="/Files/cxiaojia/stack.rar">代码下载</a></span></p>  <p style="text-indent:21.0pt;"><span style="font-family: 微软雅黑, sans-serif; ">代码如下：<br /></span></p><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><br />template&lt;<span style="color: #0000FF; ">class</span>&nbsp;T&gt;<br /><span style="color: #0000FF; ">class</span>&nbsp;stackNode<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;stackNode():next(NULL){}<br />&nbsp;&nbsp;&nbsp;&nbsp;T&nbsp;data;<span style="color: #008000; ">//</span><span style="color: #008000; ">值</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;stackNode*&nbsp;next;<span style="color: #008000; ">//</span><span style="color: #008000; ">指向下一个节点的指针</span><span style="color: #008000; "><br /></span>};<br />template&lt;<span style="color: #0000FF; ">class</span>&nbsp;T&gt;<br /><span style="color: #0000FF; ">class</span>&nbsp;mystack<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">private</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;stacklength;<br />&nbsp;&nbsp;&nbsp;&nbsp;stackNode&lt;T&gt;*&nbsp;node;<span style="color: #008000; ">//</span><span style="color: #008000; ">临时节点</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;stackNode&lt;T&gt;*&nbsp;headnode;<span style="color: #008000; ">//</span><span style="color: #008000; ">尾结点</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;mystack();<span style="color: #008000; ">//</span><span style="color: #008000; ">初始化</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;length();<span style="color: #008000; ">//</span><span style="color: #008000; ">栈元素的个数</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;push(T&nbsp;x);<span style="color: #008000; ">//</span><span style="color: #008000; ">入栈</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">bool</span>&nbsp;isEmpty();<span style="color: #008000; ">//</span><span style="color: #008000; ">判断栈是否为空</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;pop();<span style="color: #008000; ">//</span><span style="color: #008000; ">出栈</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;T&nbsp;top();<span style="color: #008000; ">//</span><span style="color: #008000; ">获得栈顶元素</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;clear();<span style="color: #008000; ">//</span><span style="color: #008000; ">清空栈</span><span style="color: #008000; "><br /></span><br />};<br />template&lt;<span style="color: #0000FF; ">class</span>&nbsp;T&gt;<br />mystack&lt;T&gt;::mystack()<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;node=NULL;<br />&nbsp;&nbsp;&nbsp;&nbsp;headnode=NULL;<br />&nbsp;&nbsp;&nbsp;&nbsp;stacklength=0;<br />}<br />template&lt;<span style="color: #0000FF; ">class</span>&nbsp;T&gt;<br />inline&nbsp;unsigned&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;mystack&lt;T&gt;::length(){<span style="color: #0000FF; ">return</span>&nbsp;stacklength;}<br />template&lt;<span style="color: #0000FF; ">class</span>&nbsp;T&gt;<br /><span style="color: #0000FF; ">void</span>&nbsp;&nbsp;mystack&lt;T&gt;::push(T&nbsp;x)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;node=<span style="color: #0000FF; ">new</span>&nbsp;stackNode&lt;T&gt;();<br />&nbsp;&nbsp;&nbsp;&nbsp;node-&gt;data=x;<br />&nbsp;&nbsp;&nbsp;&nbsp;node-&gt;next=headnode;<span style="color: #008000; ">//</span><span style="color: #008000; ">把node变成头节点</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;headnode=node;<br />&nbsp;&nbsp;&nbsp;&nbsp;++stacklength;<br />}<br />template&lt;<span style="color: #0000FF; ">class</span>&nbsp;T&gt;<br /><span style="color: #0000FF; ">bool</span>&nbsp;&nbsp;mystack&lt;T&gt;::isEmpty()<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;stacklength==0;<br />}<br />template&lt;<span style="color: #0000FF; ">class</span>&nbsp;T&gt;<br /><span style="color: #0000FF; ">void</span>&nbsp;&nbsp;mystack&lt;T&gt;::pop()<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(isEmpty())&nbsp;<span style="color: #0000FF; ">return</span>;<br />&nbsp;&nbsp;&nbsp;&nbsp;node=headnode;<br />&nbsp;&nbsp;&nbsp;&nbsp;headnode=headnode-&gt;next;<span style="color: #008000; ">//</span><span style="color: #008000; ">头节点变成它的下一个节点</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;delete(node);<span style="color: #008000; ">//</span><span style="color: #008000; ">删除头节点</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;--stacklength;<br />}<br />template&lt;<span style="color: #0000FF; ">class</span>&nbsp;T&gt;<br />T&nbsp;&nbsp;mystack&lt;T&gt;::top()<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(!isEmpty())<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;headnode-&gt;data;<br />}<br />template&lt;<span style="color: #0000FF; ">class</span>&nbsp;T&gt;<br /><span style="color: #0000FF; ">void</span>&nbsp;&nbsp;mystack&lt;T&gt;::clear()<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">while</span>(headnode!=NULL)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;node=headnode;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;headnode=headnode-&gt;next;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;delete(node);<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;node=NULL;<br />&nbsp;&nbsp;&nbsp;&nbsp;headnode=NULL;<br />&nbsp;&nbsp;&nbsp;&nbsp;stacklength=0;<br />}</div><p class="MsoNormal" style="text-indent:21.0pt;mso-char-indent-count:2.0"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">很清楚，除了<span lang="EN-US">clear</span>函数外，所有的方法的时间复杂度都是<span lang="EN-US">O(1)</span>。这种实现方式的缺点在于对<span lang="EN-US">new</span>和<span lang="EN-US">delete</span>的调用的开销是昂贵的，所以采用数组的方式实现会更好一点。<br /><span lang="EN-US"><o:p></o:p></span></span></p>

<p class="MsoNormal" style="text-indent:21.0pt;mso-char-indent-count:2.0"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;"><strong>栈的应用</strong><span lang="EN-US"><o:p></o:p></span></span></p>

<p class="MsoNormal" style="text-indent:21.0pt;mso-char-indent-count:2.0"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">使用栈的时候一般不用自己重新去写，因为<span lang="EN-US">STL</span>给我们实现了一个很安全的栈，可以放心去使用。</span><span style="font-size:10.5pt;mso-bidi-font-size:11.0pt;
font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;mso-bidi-font-family:&quot;Times New Roman&quot;;
mso-bidi-theme-font:minor-bidi;mso-ansi-language:EN-US;mso-fareast-language:
ZH-CN;mso-bidi-language:AR-SA">也可以用数组模拟一个，很简单。</span></p>

<p class="MsoNormal" style="text-indent:21.0pt;mso-char-indent-count:2.0"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">编译器调用函数就用了栈结构，当第一个函数还没执行完毕，调用第二个函数的时候，编译器就会把第一个函数压栈，第二个函数调用完毕的时候，就会取栈顶函数，也就是第一个函数继续执行。<span lang="EN-US"><o:p></o:p></span></span></p>

<p class="MsoNormal" style="text-indent:21.0pt;mso-char-indent-count:2.0"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">平衡符号 <span lang="EN-US"><a href="http://acm.nyist.net/JudgeOnline/problem.php?pid=2">http://acm.nyist.net/JudgeOnline/problem.php?pid=2</a><o:p></o:p></span></span></p>

<p class="MsoNormal" style="text-indent:21.0pt;mso-char-indent-count:2.0"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">中缀转后缀 <span lang="EN-US"><a href="http://acm.nyist.net/JudgeOnline/problem.php?pid=467">http://acm.nyist.net/JudgeOnline/problem.php?pid=467</a><o:p></o:p></span></span></p>

<p class="MsoNormal" style="text-indent:21.0pt;mso-char-indent-count:2.0"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">后缀试求值 <span lang="EN-US"><a href="http://acm.nyist.net/JudgeOnline/problem.php?pid=35">http://acm.nyist.net/JudgeOnline/problem.php?pid=35</a><o:p></o:p></span></span></p>

<p class="MsoNormal" style="text-indent:21.0pt;mso-char-indent-count:2.0"><span lang="EN-US" style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">poj 3250 <a href="http://acm.pku.edu.cn/JudgeOnline/problem?id=3250">http://acm.pku.edu.cn/JudgeOnline/problem?id=3250</a><o:p></o:p></span></p>

<p class="MsoNormal" style="text-indent:21.0pt;mso-char-indent-count:2.0"><span lang="EN-US" style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">poj 1363 <a href="http://acm.pku.edu.cn/JudgeOnline/problem?id=1363">http://acm.pku.edu.cn/JudgeOnline/problem?id=1363</a><o:p></o:p></span></p>

<p class="MsoNormal" style="text-indent:21.0pt;mso-char-indent-count:2.0"><span lang="EN-US" style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">poj 1208 <a href="http://acm.pku.edu.cn/JudgeOnline/problem?id=1208">http://acm.pku.edu.cn/JudgeOnline/problem?id=1208</a><o:p></o:p></span></p>

<p class="MsoNormal" style="text-indent:21.0pt;mso-char-indent-count:2.0"><span lang="EN-US" style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">poj 1686 <a href="http://acm.pku.edu.cn/JudgeOnline/problem?id=1686">http://acm.pku.edu.cn/JudgeOnline/problem?id=1686</a><o:p></o:p></span></p>

<p class="MsoNormal" style="text-indent:21.0pt;mso-char-indent-count:2.0"><span lang="EN-US" style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">poj 3250 <a href="http://acm.pku.edu.cn/JudgeOnline/problem?id=2045">http://acm.pku.edu.cn/JudgeOnline/problem?id=2045</a><o:p></o:p></span></p>

<pre style="text-indent:21.0pt;mso-char-indent-count:2.0;line-height:11.2pt;
background:#FCFEFC"><span lang="EN-US" style="font-size:10.5pt;mso-bidi-font-size:
11.0pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;mso-bidi-font-family:&quot;Times New Roman&quot;;
mso-bidi-theme-font:minor-bidi">hdu 1022 <a href="http://acm.hdu.edu.cn/showproblem.php?pid=1022">http://acm.hdu.edu.cn/showproblem.php?pid=1022</a><o:p></o:p></span></pre><span style="font-family: 微软雅黑, sans-serif; "><br /><br /><br /></span><p>&nbsp;</p><img src ="http://www.cppblog.com/cxiaojia/aggbug/185913.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cxiaojia/" target="_blank">C小加</a> 2012-08-01 16:51 <a href="http://www.cppblog.com/cxiaojia/archive/2012/08/01/185913.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>基本数据结构：链表（list）</title><link>http://www.cppblog.com/cxiaojia/archive/2012/07/31/185760.html</link><dc:creator>C小加</dc:creator><author>C小加</author><pubDate>Tue, 31 Jul 2012 09:41:00 GMT</pubDate><guid>http://www.cppblog.com/cxiaojia/archive/2012/07/31/185760.html</guid><wfw:comment>http://www.cppblog.com/cxiaojia/comments/185760.html</wfw:comment><comments>http://www.cppblog.com/cxiaojia/archive/2012/07/31/185760.html#Feedback</comments><slash:comments>1</slash:comments><wfw:commentRss>http://www.cppblog.com/cxiaojia/comments/commentRss/185760.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cxiaojia/services/trackbacks/185760.html</trackback:ping><description><![CDATA[<p align="center" style="text-align:center"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;"><strong>基本数据结构：链表（list）</strong></span></p>  <p align="center" style="text-align:center"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;color:red">作者：</span><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">C</span><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">小加&nbsp;<span style="color:red">更新时间：</span>2012-7-31</span></p>  <p style="text-indent:20.6pt;"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">谈到链表之前，先说一下线性表。线性表是最基本、最简单、也是最常用的一种</span><a href="http://baike.baidu.com/view/9900.htm" target="_blank"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;color:windowtext;text-decoration: none;text-underline:none">数据结构</span></a><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">。线性表中数据元素之间的关系是一对一的关系，即除了第一个和最后一个数据元素之外，其它数据元素都是首尾相接的。线性表有两种存储方式，一种是顺序存储结构，另一种是链式存储结构。</span></p>  <p style="text-indent:20.45pt;"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">顺序存储结构就是两个相邻的元素在内存中也是相邻的。这种存储方式的优点是查询的时间复杂度为O(1)，通过首地址和偏移量就可以直接访问到某元素，关于查找的适配算法很多，最快可以达到O(logn)。缺点是插入和删除的时间复杂度最坏能达到O(n)，如果你在第一个位置插入一个元素，你需要把数组的每一个元素向后移动一位，如果你在第一个位置删除一个元素，你需要把数组的每一个元素向前移动一位。还有一个缺点，就是当你不确定元素的数量时，你开的数组必须保证能够放下元素最大数量，遗憾的是如果实际数量比最大数量少很多时，你开的数组没有用到的内存就只能浪费掉了。</span></p>  <p style="text-indent:20.45pt;"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">我们常用的数组就是一种典型的顺序存储结构，如图1。</span></p><img src="http://www.cppblog.com/images/cppblog_com/cxiaojia/list_1.png" width="650" height="330" alt="" /><br /><p style="text-indent:20.6pt;"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">链式存储结构就是两个相邻的元素在内存中可能不是相邻的，每一个元素都有一个指针域，指针域一般是存储着到下一个元素的指针。这种存储方式的优点是插入和删除的时间复杂度为O(1)，不会浪费太多内存，添加元素的时候才会申请内存，删除元素会释放内存，。缺点是访问的时间复杂度最坏为O(n)，关于查找的算法很少，一般只能遍历，这样时间复杂度也是线性（O(n)）的了,频繁的申请和释放内存也会消耗时间。</span></p>  <p style="text-indent:20.6pt;"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">顺序表的特性是随机读取，也就是访问一个元素的时间复杂度是O(1)，链式表的特性是插入和删除的时间复杂度为O(1)。要根据实际情况去选取适合自己的存储结构。</span></p>  <p style="text-indent:20.6pt;"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">链表就是链式存储的线性表。根据指针域的不同，链表分为单向链表、双向链表、循环链表等等。</span></p>  <p style="margin-left:43.15pt;text-indent:-22.5pt;"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;">一、 </span><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">单向链表（slist）</span></p>  <p style="text-indent:20.45pt;"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">链表中最简单的一种是单向链表，每个元素包含两个域，值域和指针域，我们把这样的元素称之为节点。每个节点的指针域内有一个指针，指向下一个节点，而最后一个节点则指向一个空值。如图2就是一个单向链表。</span></p><img src="http://www.cppblog.com/images/cppblog_com/cxiaojia/list_2.png" border="0" alt="" width="747" height="271" /><br /><p style="text-indent:20.45pt;"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">一个单向链表的节点被分成两个部分。第一个部分保存或者显示关于节点的信息，第二个部分存储下一个节点的地址。单向链表只可向一个方向遍历。</span></p>  <p style="text-indent:20.45pt;"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">我写了一个简单的C++版单向链表类模板，就用这段代码讲解一下一个具体的单向链表该怎么写（代码仅供学习），当然首先你要具备C++基础知识和简单的模板元编程。<br /><a href="/Files/cxiaojia/slist.zip">完整代码</a><br /></span></p>  <p style="text-indent:20.45pt;"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">首先我们要写一个节点类，链表中的每一个节点就是一个节点类的对象。如图3。<br /></span></p><img src="http://www.cppblog.com/images/cppblog_com/cxiaojia/list_3.png" width="771" height="266" alt="" /><br /><p style="text-indent:20.45pt;"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">代码如下：</span></p><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><br />template&lt;<span style="color: #0000FF; ">class</span>&nbsp;T&gt;<br /><span style="color: #0000FF; ">class</span>&nbsp;slistNode<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;slistNode(){next=NULL;}<span style="color: #008000; ">//</span><span style="color: #008000; ">初始化</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;T&nbsp;data;<span style="color: #008000; ">//</span><span style="color: #008000; ">值</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;slistNode*&nbsp;next;<span style="color: #008000; ">//</span><span style="color: #008000; ">指向下一个节点的指针</span><span style="color: #008000; "><br /></span>};</div><p style="text-indent:20.45pt;"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">第二步，写单链表类的声明，包括属性和方法。</span></p>  <p style="text-indent:20.45pt;"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">代码如下：</span></p><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />--><br />template&lt;<span style="color: #0000FF; ">class</span>&nbsp;T&gt;<br /><span style="color: #0000FF; ">class</span>&nbsp;myslist<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">private</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;listlength;<br />&nbsp;&nbsp;&nbsp;&nbsp;slistNode&lt;T&gt;*&nbsp;node;<span style="color: #008000; ">//</span><span style="color: #008000; ">临时节点</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;slistNode&lt;T&gt;*&nbsp;lastnode;<span style="color: #008000; ">//</span><span style="color: #008000; ">头结点</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;slistNode&lt;T&gt;*&nbsp;headnode;<span style="color: #008000; ">//</span><span style="color: #008000; ">尾节点</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">public</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;myslist();<span style="color: #008000; ">//</span><span style="color: #008000; ">初始化</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;length();<span style="color: #008000; ">//</span><span style="color: #008000; ">链表元素的个数</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;add(T&nbsp;x);<span style="color: #008000; ">//</span><span style="color: #008000; ">表尾添加元素</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;traversal();<span style="color: #008000; ">//</span><span style="color: #008000; ">遍历整个链表并打印</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">bool</span>&nbsp;isEmpty();<span style="color: #008000; ">//</span><span style="color: #008000; ">判断链表是否为空</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;slistNode&lt;T&gt;*&nbsp;find(T&nbsp;x);<span style="color: #008000; ">//</span><span style="color: #008000; ">查找第一个值为x的节点,返回节点的地址,找不到返回NULL</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;Delete(T&nbsp;x);<span style="color: #008000; ">//</span><span style="color: #008000; ">删除第一个值为x的节点</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;insert(T&nbsp;x,slistNode&lt;T&gt;*&nbsp;p);<span style="color: #008000; ">//</span><span style="color: #008000; ">在p节点后插入值为x的节点</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;insertHead(T&nbsp;x);<span style="color: #008000; ">//</span><span style="color: #008000; ">在链表的头部插入节点</span><span style="color: #008000; "><br /></span>};</div><br /><p style="text-indent:20.45pt;"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">第三步，写构造函数，初始化链表类的属性。</span></p>  <p style="text-indent:20.45pt;"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">代码如下：</span></p><div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all; "><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->template&lt;<span style="color: #0000FF; ">class</span>&nbsp;T&gt;<br />myslist&lt;T&gt;::myslist()<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;node=NULL;<br />&nbsp;&nbsp;&nbsp;&nbsp;lastnode=NULL;<br />&nbsp;&nbsp;&nbsp;&nbsp;headnode=NULL;<br />&nbsp;&nbsp;&nbsp;&nbsp;listlength=0;<br />}</div><p style="text-indent:20.45pt;"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">第四步，实现add()方法。</span></p>  <p style="text-indent:20.45pt;"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">代码如下：</span></p><div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all; "><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->template&lt;<span style="color: #0000FF; ">class</span>&nbsp;T&gt;<br /><span style="color: #0000FF; ">void</span>&nbsp;&nbsp;myslist&lt;T&gt;::add(T&nbsp;x)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;node=<span style="color: #0000FF; ">new</span>&nbsp;slistNode&lt;T&gt;();<span style="color: #008000; ">//</span><span style="color: #008000; ">申请一个新的节点</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;node-&gt;data=x;<span style="color: #008000; ">//</span><span style="color: #008000; ">新节点赋值为x</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(lastnode==NULL)<span style="color: #008000; ">//</span><span style="color: #008000; ">如果没有尾节点则链表为空,node既为头结点,又是尾节点</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;headnode=node;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lastnode=node;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">else</span><span style="color: #008000; ">//</span><span style="color: #008000; ">如果链表非空</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lastnode-&gt;next=node;<span style="color: #008000; ">//</span><span style="color: #008000; ">node既为尾节点的下一个节点</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lastnode=node;<span style="color: #008000; ">//</span><span style="color: #008000; ">node变成了尾节点,把尾节点赋值为node</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;++listlength;<span style="color: #008000; ">//</span><span style="color: #008000; ">元素个数+1</span><span style="color: #008000; "><br /></span>}</div><p style="text-indent:20.45pt;"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">第五步，实现traversal()函数，遍历并输出节点信息。</span></p>  <p style="text-indent:20.45pt;"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">代码如下：<br /></span></p><div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all; "><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->template&lt;<span style="color: #0000FF; ">class</span>&nbsp;T&gt;<br /><span style="color: #0000FF; ">void</span>&nbsp;&nbsp;myslist&lt;T&gt;::traversal()<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;node=headnode;<span style="color: #008000; ">//</span><span style="color: #008000; ">用临时节点指向头结点</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">while</span>(node!=NULL)<span style="color: #008000; ">//</span><span style="color: #008000; ">遍历链表并输出</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;cout&lt;&lt;node-&gt;data&lt;&lt;ends;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;node=node-&gt;next;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;cout&lt;&lt;endl;<br />}</div><p style="text-indent:20.45pt;"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">第六步，实现isEmpty()函数，判断链表是否为空，返回真为空，假则不空。</span></p>  <p style="text-indent:20.45pt;"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">代码如下：</span></p><div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all; "><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->template&lt;<span style="color: #0000FF; ">class</span>&nbsp;T&gt;<br /><span style="color: #0000FF; ">bool</span>&nbsp;&nbsp;myslist&lt;T&gt;::isEmpty()<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;listlength==0;<br />}</div><p style="text-indent:20.45pt;"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">第七步，实现find()函数。</span></p>  <p style="text-indent: 20.45pt; "><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">代码如下：<br /></span></p><div style="background-color: #eeeeee; font-size: 13px; border: 1px solid #cccccc; padding: 4px 5px 4px 4px; width: 98%; word-break: break-all; "><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->template&lt;<span style="color: #0000FF; ">class</span>&nbsp;T&gt;<br />slistNode&lt;T&gt;*&nbsp;myslist&lt;T&gt;::find(T&nbsp;x)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;node=headnode;<span style="color: #008000; ">//</span><span style="color: #008000; ">用临时节点指向头结点</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">while</span>(node!=NULL&amp;&amp;node-&gt;data!=x)<span style="color: #008000; ">//</span><span style="color: #008000; ">遍历链表,遇到值相同的节点跳出</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;node=node-&gt;next;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;node;<span style="color: #008000; ">//</span><span style="color: #008000; ">返回找到的节点的地址,如果没有找到则返回NULL</span><span style="color: #008000; "><br /></span>}</div><p style="text-indent:20.45pt;"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">第八步，实现delete()函数，删除第一个值为x的节点，如图4。</span></p><img src="http://www.cppblog.com/images/cppblog_com/cxiaojia/list_4.png" width="771" height="259" alt="" /><br /><p style="text-indent:20.45pt;"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">代码如下：<br /></span></p><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->template&lt;<span style="color: #0000FF; ">class</span>&nbsp;T&gt;<br /><span style="color: #0000FF; ">void</span>&nbsp;&nbsp;myslist&lt;T&gt;::Delete(T&nbsp;x)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;slistNode&lt;T&gt;*&nbsp;temp=headnode;<span style="color: #008000; ">//</span><span style="color: #008000; ">申请一个临时节点指向头节点</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(temp==NULL)&nbsp;<span style="color: #0000FF; ">return</span>;<span style="color: #008000; ">//</span><span style="color: #008000; ">如果头节点为空,则该链表无元素,直接返回</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(temp-&gt;data==x)<span style="color: #008000; ">//</span><span style="color: #008000; ">如果头节点的值为要删除的值,则删除投节点</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;headnode=temp-&gt;next;<span style="color: #008000; ">//</span><span style="color: #008000; ">把头节点指向头节点的下一个节点</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(temp-&gt;next==NULL)&nbsp;lastnode=NULL;<span style="color: #008000; ">//</span><span style="color: #008000; ">如果链表中只有一个节点,删除之后就没有节点了,把尾节点置为空</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;delete(temp);<span style="color: #008000; ">//</span><span style="color: #008000; ">删除头节点</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">while</span>(temp-&gt;next!=NULL&amp;&amp;temp-&gt;next-&gt;data!=x)<span style="color: #008000; ">//</span><span style="color: #008000; ">遍历链表找到第一个值与x相等的节点,temp表示这个节点的上一个节点</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;temp=temp-&gt;next;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(temp-&gt;next==NULL)&nbsp;<span style="color: #0000FF; ">return</span>;<span style="color: #008000; ">//</span><span style="color: #008000; ">如果没有找到则返回</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(temp-&gt;next==lastnode)<span style="color: #008000; ">//</span><span style="color: #008000; ">如果找到的时候尾节点</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;lastnode=temp;<span style="color: #008000; ">//</span><span style="color: #008000; ">把尾节点指向他的上一个节点</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;delete(temp-&gt;next);<span style="color: #008000; ">//</span><span style="color: #008000; ">删除尾节点</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;temp-&gt;next=NULL;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">else</span><span style="color: #008000; ">//</span><span style="color: #008000; ">如果不是尾节点,如图4</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;node=temp-&gt;next;<span style="color: #008000; ">//</span><span style="color: #008000; ">用临时节点node指向要删除的节点</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;temp-&gt;next=node-&gt;next;<span style="color: #008000; ">//</span><span style="color: #008000; ">要删除的节点的上一个节点指向要删除节点的下一个节点</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;delete(node);<span style="color: #008000; ">//</span><span style="color: #008000; ">删除节点</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;node=NULL;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />}</div><p class="MsoNormal" style="text-indent:20.45pt;mso-char-indent-count:1.95"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">第九步，实现<span lang="EN-US">insert()</span>和<span lang="EN-US">insertHead()</span>函数，在<span lang="EN-US">p</span>节点后插入值为<span lang="EN-US">x</span>的节点。如图<span lang="EN-US">5</span>。<span lang="EN-US"><o:p></o:p></span></span></p><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;"><img src="http://www.cppblog.com/images/cppblog_com/cxiaojia/list_5.png" width="769" height="296" alt="" /><br /><br /></span><p>&nbsp;</p><p style="text-indent:20.45pt;"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">代码如下：</span></p><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->template&lt;<span style="color: #0000FF; ">class</span>&nbsp;T&gt;<br /><span style="color: #0000FF; ">void</span>&nbsp;&nbsp;myslist&lt;T&gt;::insert(T&nbsp;x,slistNode&lt;T&gt;*&nbsp;p)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(p==NULL)&nbsp;<span style="color: #0000FF; ">return</span>;<br />&nbsp;&nbsp;&nbsp;&nbsp;node=<span style="color: #0000FF; ">new</span>&nbsp;slistNode&lt;T&gt;();<span style="color: #008000; ">//</span><span style="color: #008000; ">申请一个新的空间</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;node-&gt;data=x;<span style="color: #008000; ">//</span><span style="color: #008000; ">如图5</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;node-&gt;next=p-&gt;next;<br />&nbsp;&nbsp;&nbsp;&nbsp;p-&gt;next=node;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(node-&gt;next==NULL)<span style="color: #008000; ">//</span><span style="color: #008000; ">如果node为尾节点</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;lastnode=node;<br />}<br />template&lt;<span style="color: #0000FF; ">class</span>&nbsp;T&gt;<br /><span style="color: #0000FF; ">void</span>&nbsp;&nbsp;myslist&lt;T&gt;::insertHead(T&nbsp;x)<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;node=<span style="color: #0000FF; ">new</span>&nbsp;slistNode&lt;T&gt;();<br />&nbsp;&nbsp;&nbsp;&nbsp;node-&gt;data=x;<br />&nbsp;&nbsp;&nbsp;&nbsp;node-&gt;next=headnode;<br />&nbsp;&nbsp;&nbsp;&nbsp;headnode=node;<br />}</div><br /><p style="text-indent:20.45pt;"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">最终，我们完成一个简单的单向链表。此单向链表代码还有很多待完善的地方，以后会修改代码并不定时更新。</span></p>  <p style="margin-left:43.15pt;text-indent:-22.5pt;"><span style="font-family: 微软雅黑, sans-serif; ">二、 </span><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">双向链表</span></p>  <p style="margin-left:20.7pt; text-indent:21.0pt;"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">双向链表的指针域有两个指针，每个数据结点分别指向直接后继和直接前驱。单向链表只能从表头开始向后遍历，而双向链表不但可以从前向后遍历，也可以从后向前遍历。除了双向遍历的优点，双向链表的删除的时间复杂度会降为O（1），因为直接通过目的指针就可以找到前驱节点，单向链表得从表头开始遍历寻找前驱节点。缺点是每个节点多了一个指针的空间开销。如图6就是一个双向链表。</span></p><img src="http://www.cppblog.com/images/cppblog_com/cxiaojia/list_6.png" width="813" height="236" alt="" /><br /><br /><p style="margin-left:43.15pt;text-indent:-22.5pt;"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;">三、 </span><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">循环链表</span></p>  <p style="margin-left:20.7pt; text-indent:21.0pt;"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">循环链表就是让链表的最后一个节点指向第一个节点，这样就形成了一个圆环，可以循环遍历。单向循环链表可以单向循环遍历，双向循环链表的头节点的指针也要指向最后一个节点，这样的可以双向循环遍历。如图7就是一个双向循环链表。</span></p><img src="http://www.cppblog.com/images/cppblog_com/cxiaojia/list_7.png" width="736" height="257" alt="" /><br /><p>&nbsp;</p><p style="margin-left:43.15pt;text-indent:-22.5pt;"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;">四、 </span><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">链表相关问题</span></p>  <p style="margin-top:1.85pt;margin-right:0cm;margin-bottom:1.85pt;margin-left: 20.7pt;text-indent:5.55pt;line-height:12.15pt;background:white"><span style="font-size: 10.5pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;Times New Roman&quot;;">1</span><span style="font-size:10.5pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;Times New Roman&quot;;">、如何判断一个单链表有环</span></p>  <p style="margin-top:1.85pt;margin-right:0cm;margin-bottom:1.85pt;margin-left: 0cm;text-indent:20.65pt;line-height:12.15pt;background:white"><span style="font-size:10.5pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;Times New Roman&quot;;">&nbsp; 2</span><span style="font-size:10.5pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;Times New Roman&quot;;">、如何判断一个环的入口点在哪里</span></p>  <p style="margin-top:1.85pt;margin-right:0cm;margin-bottom:1.85pt;margin-left: 20.65pt;line-height:12.15pt;background:white"><span style="font-size:10.5pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;Times New Roman&quot;;">&nbsp; 3</span><span style="font-size:10.5pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;Times New Roman&quot;;">、如何知道环的长度</span></p>  <p style="margin-top:1.85pt;margin-right:0cm;margin-bottom:1.85pt;margin-left: 20.65pt;line-height:12.15pt;background:white"><span style="font-size:10.5pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;Times New Roman&quot;;">&nbsp; 4</span><span style="font-size:10.5pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;Times New Roman&quot;;">、如何知道两个单链表（无环）是否相交</span></p>  <p style="margin-top:1.85pt;margin-right:0cm;margin-bottom:1.85pt;margin-left: 20.65pt;line-height:12.15pt;background:white"><span style="font-size:10.5pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;Times New Roman&quot;;">&nbsp; 5</span><span style="font-size:10.5pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;Times New Roman&quot;;">、如果两个单链表（无环）相交，如何知道它们相交的第一个节点是什么</span></p>  <p style="margin-top:1.85pt;margin-right:0cm;margin-bottom:1.85pt;margin-left: 20.65pt;line-height:12.15pt;background:white"><span style="font-size:10.5pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;Times New Roman&quot;;">&nbsp; 6</span><span style="font-size:10.5pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;Times New Roman&quot;;">、如何知道两个单链表（有环）是否相交</span></p>  <p style="margin-top:1.85pt;margin-right:0cm;margin-bottom:1.85pt;margin-left: 20.65pt;line-height:12.15pt;background:white"><span style="font-size:10.5pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;Times New Roman&quot;;">&nbsp; 7</span><span style="font-size:10.5pt;font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;Times New Roman&quot;;">、如果两个单链表（有环）相交，如何知道它们相交的第一个节点是什么</span></p><br />&nbsp; &nbsp; &nbsp; &nbsp;<a href="http://blog.csdn.net/vividonly/article/details/6673758" style="text-decoration: underline; " title="答案" target="_blank">答案</a><br /><br /><br /><img src ="http://www.cppblog.com/cxiaojia/aggbug/185760.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cxiaojia/" target="_blank">C小加</a> 2012-07-31 17:41 <a href="http://www.cppblog.com/cxiaojia/archive/2012/07/31/185760.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>hash_map哈希映照容器的实现</title><link>http://www.cppblog.com/cxiaojia/archive/2012/04/18/171901.html</link><dc:creator>C小加</dc:creator><author>C小加</author><pubDate>Wed, 18 Apr 2012 12:18:00 GMT</pubDate><guid>http://www.cppblog.com/cxiaojia/archive/2012/04/18/171901.html</guid><wfw:comment>http://www.cppblog.com/cxiaojia/comments/171901.html</wfw:comment><comments>http://www.cppblog.com/cxiaojia/archive/2012/04/18/171901.html#Feedback</comments><slash:comments>3</slash:comments><wfw:commentRss>http://www.cppblog.com/cxiaojia/comments/commentRss/171901.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cxiaojia/services/trackbacks/171901.html</trackback:ping><description><![CDATA[<div><p>hash_map<span style="font-family: 宋体;">，顾名思义，就是利用</span>hash_set<span style="font-family:宋体;">存储结构的写</span>map<span style="font-family:宋体;">映照容器，普通的</span>map<span style="font-family:宋体;">用的是红黑树存储结构写的。元素的检索时间对比，</span>hash_set<span style="font-family:宋体;">近似为</span>O(1)<span style="font-family:宋体;">，红黑树为</span>O(logn)<span style="font-family:宋体;">。</span>Hash_map<span style="font-family:宋体;">的空间开销要比</span>map <span style="font-family:宋体;">的空间开销大，尤其是我用数组模拟指针写的</span>hash_map<span style="font-family:宋体;">。</span></p>  <p><span style="font-family:宋体;">所以，如果有必要采取映射结构的时候，能用</span>hash_map<span style="font-family:宋体;">就别用</span>map<span style="font-family:宋体;">。</span></p>  <p><span style="font-family:宋体;">需要注意的是，</span>hash_map<span style="font-family:宋体;">遍历出来的元素不是有序的。</span></p>  <p>Hash_map<span style="font-family: 宋体;">和普通</span>hash_set<span style="font-family:宋体;">相比的话，</span>hash_map<span style="font-family:宋体;">比</span>hash_set<span style="font-family:宋体;">多了一张</span>value<span style="font-family:宋体;">表，也就是映射表。</span></p>  <p>&nbsp;</p>  <p><span style="font-family:宋体;">下面是</span>hash_map<span style="font-family:宋体;">的模板，和</span>hash_set<span style="font-family: 宋体; ">的模板差不多。<br /><br /></span></p><div style="background-color:#eeeeee;font-size:13px;border:1px solid #CCCCCC;padding-right: 5px;padding-bottom: 4px;padding-left: 4px;padding-top: 4px;width: 98%;word-break:break-all"><!--<br /><br />Code highlighting produced by Actipro CodeHighlighter (freeware)<br />http://www.CodeHighlighter.com/<br /><br />-->template&lt;<span style="color: #0000FF; ">class</span>&nbsp;KeyType,<span style="color: #0000FF; ">int</span>&nbsp;MaxHash&gt;<br /><span style="color: #0000FF; ">struct</span>&nbsp;HashFunction<br />{<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;<span style="color: #0000FF; ">operator</span>()(<span style="color: #0000FF; ">const</span>&nbsp;KeyType&amp;&nbsp;key)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;h=key%MaxHash;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>&nbsp;(h&lt;0)&nbsp;h+=MaxHash;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;h;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />};<br /><br />template&lt;<span style="color: #0000FF; ">class</span>&nbsp;KeyType,<span style="color: #0000FF; ">class</span>&nbsp;ValueType,<span style="color: #0000FF; ">int</span>&nbsp;KeyContain,<span style="color: #0000FF; ">int</span>&nbsp;MaxHash,<span style="color: #0000FF; ">class</span>&nbsp;HashFun=HashFunction&lt;KeyType,MaxHash&gt;&nbsp;&gt;<br /><span style="color: #0000FF; ">class</span>&nbsp;HashMap<br />{<br /><span style="color: #0000FF; ">public</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;HashMap():hashfun(){Clear();}<br />&nbsp;&nbsp;&nbsp;&nbsp;ValueType&amp;&nbsp;<span style="color: #0000FF; ">operator</span>[](<span style="color: #0000FF; ">const</span>&nbsp;KeyType&amp;&nbsp;key)<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;h=hashfun(key);<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;pos=head[h];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">for</span>(;pos!=0;pos=next[pos])<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">if</span>(keys[pos]==key)<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;values[pos];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;next[++top]=head[h];<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;head[h]=top;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;keys[top]=key;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;values[top]=ValueType();<span style="color: #008000; ">//</span><span style="color: #008000; ">初始化</span><span style="color: #008000; "><br /></span>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;++sz;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">return</span>&nbsp;values[top];<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">void</span>&nbsp;Clear()<br />&nbsp;&nbsp;&nbsp;&nbsp;{<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;memset(head,0,<span style="color: #0000FF; ">sizeof</span>(head));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;memset(next,0,(top+1)*<span style="color: #0000FF; ">sizeof</span>(<span style="color: #0000FF; ">int</span>));<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;top=0;<br />&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;sz=0;<br />&nbsp;&nbsp;&nbsp;&nbsp;}<br />&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;size()&nbsp;<span style="color: #0000FF; ">const</span>&nbsp;{<span style="color: #0000FF; ">return</span>&nbsp;sz;}<br /><br /><span style="color: #0000FF; ">private</span>:<br />&nbsp;&nbsp;&nbsp;&nbsp;unsigned&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;sz;<br />&nbsp;&nbsp;&nbsp;&nbsp;HashFun&nbsp;hashfun;<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;head[MaxHash];<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;next[KeyContain];<br />&nbsp;&nbsp;&nbsp;&nbsp;KeyType&nbsp;keys[KeyContain];<br />&nbsp;&nbsp;&nbsp;&nbsp;ValueType&nbsp;values[KeyContain];<br />&nbsp;&nbsp;&nbsp;&nbsp;<span style="color: #0000FF; ">int</span>&nbsp;top;<br />};</div><p>&nbsp;</p></div><img src ="http://www.cppblog.com/cxiaojia/aggbug/171901.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cxiaojia/" target="_blank">C小加</a> 2012-04-18 20:18 <a href="http://www.cppblog.com/cxiaojia/archive/2012/04/18/171901.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>区间某个数出现的次数</title><link>http://www.cppblog.com/cxiaojia/archive/2012/03/26/168993.html</link><dc:creator>C小加</dc:creator><author>C小加</author><pubDate>Mon, 26 Mar 2012 04:55:00 GMT</pubDate><guid>http://www.cppblog.com/cxiaojia/archive/2012/03/26/168993.html</guid><wfw:comment>http://www.cppblog.com/cxiaojia/comments/168993.html</wfw:comment><comments>http://www.cppblog.com/cxiaojia/archive/2012/03/26/168993.html#Feedback</comments><slash:comments>0</slash:comments><wfw:commentRss>http://www.cppblog.com/cxiaojia/comments/commentRss/168993.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cxiaojia/services/trackbacks/168993.html</trackback:ping><description><![CDATA[<div><p><span style="font-family:宋体;">给你一串数字，让你求出某个子串中某个数字出现的次数。</span></p>  <p><span style="font-family:宋体;">用邻接表储存每个数出现的位置，然后对邻接表进行二分查找，找出区间。</span></p></div><img src ="http://www.cppblog.com/cxiaojia/aggbug/168993.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cxiaojia/" target="_blank">C小加</a> 2012-03-26 12:55 <a href="http://www.cppblog.com/cxiaojia/archive/2012/03/26/168993.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>优秀博客推荐：各种数据结构与算法知识入门经典（不断更新)</title><link>http://www.cppblog.com/cxiaojia/archive/2011/11/16/rumen.html</link><dc:creator>C小加</dc:creator><author>C小加</author><pubDate>Wed, 16 Nov 2011 07:58:00 GMT</pubDate><guid>http://www.cppblog.com/cxiaojia/archive/2011/11/16/rumen.html</guid><wfw:comment>http://www.cppblog.com/cxiaojia/comments/160269.html</wfw:comment><comments>http://www.cppblog.com/cxiaojia/archive/2011/11/16/rumen.html#Feedback</comments><slash:comments>7</slash:comments><wfw:commentRss>http://www.cppblog.com/cxiaojia/comments/commentRss/160269.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cxiaojia/services/trackbacks/160269.html</trackback:ping><description><![CDATA[<p align="center" style="text-align:center"></p><div></div><p>&nbsp;</p>  <p align="center" style="text-align:center"><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;;color:red">作者：</span><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">C</span><span style="font-family:&quot;微软雅黑&quot;,&quot;sans-serif&quot;">小加&nbsp;<span style="color:red">更新时间：</span>2012-8-16</span></p>欢迎<span style="color: red; ">自荐</span>和<span style="color: red; ">推荐</span>链接。请于留言处告知。<br /><br /><span style="background-color: #ffff00; ">基本算法</span><br />贪心算法：<a href="http://www.cnblogs.com/chinazhangjie/archive/2010/11/23/1885330.html" title="贪心算法" target="_blank">贪心算法</a>&nbsp;作者：<span class="Apple-style-span" style="color: #ff0000; ">独酌逸醉<br />&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<a href="http://www.cppblog.com/3522021224/archive/2007/06/16/26429.aspx" title="贪心算法精讲" target="_blank">贪心算法精讲</a>&nbsp;</span><span class="Apple-style-span" style="color: #000000; ">作者：<span class="Apple-style-span" style="font-family: Arial; line-height: 18px; white-space: nowrap; color: #ff0000; "><strong>3522021224</strong></span><br /></span>递归和分治：<a href="http://blog.csdn.net/zhoudaxia/article/details/5765084" title="递归与分治策略" target="_blank">递归与分治策略</a>&nbsp;作者：<span class="Apple-style-span" style="font-family: Arial, Console, Verdana, 'Courier New'; font-weight: bold; line-height: 13px; color: #ff0000; ">zhoudaxia</span><br /><br /><span style="background-color: #ffff00; ">图论</span><br />图的遍历（DFS和BFS）：&nbsp;&nbsp;<a href="http://jefferent.iteye.com/blog/1122934">图的遍历</a> 作者：<span class="Apple-style-span" style="font-family: Helvetica, Tahoma, Arial, sans-serif; line-height: 18px; color: red; ">jefferent</span><br />最小生成树（Prim算法和Kruskal算法）：&nbsp;<a href="http://www.cnblogs.com/chinazhangjie/archive/2010/12/02/1894314.html" target="_blank">贪心算法--最小生成树</a>&nbsp;作者：<span style="color: red; ">独酌逸醉</span><br /><span style="color: #333333; font-family: Arial, Helvetica, simsun, u5b8bu4f53; line-height: 25px; ">Dijkstra算法：&nbsp;<a href="http://2728green-rock.blog.163.com/blog/static/43636790200901211848284/" title="最短路径之Dijkstra算法详细讲解  " target="_blank">最短路径之Dijkstra算法详细讲解</a>&nbsp;作者：</span><span style="cursor: pointer; "><a target="_blank"  m2a"="" href="http://blog.163.com/2728green-rock/" style="cursor: pointer; "><font class="Apple-style-span" color="#3c910d"><span class="Apple-style-span" style="line-height: normal;">绿岩<br /></span></font></a></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<a href="http://www.wutianqi.com/?p=1890" title="最短路径算法&#8212;Dijkstra(迪杰斯特拉)算法分析与实现(C/C++)">最短路径算法&#8212;Dijkstra(迪杰斯特拉)算法分析与实现(C/C++)</a>&nbsp;作者：<span class="Apple-style-span" style="color: #ff0000; font-family: 'Lucida Grande', Arial, Helvetica, sans-serif; line-height: 13px; ">tankywoo</span><br /><span class="Apple-style-span" style="font-family: Arial, Helvetica, simsun, u5b8bu4f53; line-height: 24px; "><span style="line-height: 25px; ">Bellman-Ford</span></span><span class="Apple-style-span" style="font-family: Arial, Helvetica, simsun, u5b8bu4f53; line-height: 24px; "><span style="line-height: 25px; ">算法：<a href="http://www.wutianqi.com/?p=1912" title="最短路径算法&#8212;Bellman-Ford(贝尔曼-福特)算法分析与实现(C/C++)" target="_blank">最短路径算法&#8212;Bellman-Ford(贝尔曼-福特)算法分析与实现(C/C++)</a>&nbsp; 作者：<span class="Apple-style-span" style="font-family: 'Lucida Grande', Arial, Helvetica, sans-serif; line-height: 15px; color: red; ">tankywoo</span><br /></span></span><span class="Apple-style-span" style="color: #333333; font-family: Arial, Helvetica, simsun, u5b8bu4f53; line-height: 24px; ">Floyd-Warshall算法：<a href="http://www.wutianqi.com/?p=1903" title="最短路径算法&#8212;Floyd(弗洛伊德)算法分析与实现(C/C++)">最短路径算法&#8212;Floyd(弗洛伊德)算法分析与实现(C/C++)</a>&nbsp;作者：<span class="Apple-style-span" style="color: #ff0000; font-family: 'Lucida Grande', Arial, Helvetica, sans-serif; line-height: 13px; ">tankywoo</span><br /></span><span class="Apple-style-span" style="color: #333333; font-family: Arial, Helvetica, simsun, u5b8bu4f53; line-height: 24px; ">Johnson算法：<a href="http://blog.csdn.net/huliang82/article/details/4166588" title="Johnson 算法">Johnson 算法</a>&nbsp;作者：<span class="Apple-style-span" style="font-family: Arial, Console, Verdana, 'Courier New'; font-weight: bold; line-height: 13px; color: red; ">huliang82</span><br /></span><font class="Apple-style-span" color="#333333" face="Arial, Helvetica, simsun, u5b8bu4f53"><span class="Apple-style-span" style="line-height: 24px;">A*算法：</span></font><a href="http://yangxy84.blog.163.com/blog/static/70844302009313114846776/" title="A*算法详解" style="color: #333333; font-family: Arial, Helvetica, simsun, u5b8bu4f53; line-height: 24px; ">A*算法详解</a><font class="Apple-style-span" color="#333333" face="Arial, Helvetica, simsun, u5b8bu4f53"><span class="Apple-style-span" style="line-height: 24px;">&nbsp;作者：</span></font><span class="Apple-style-span" style="color: #444444; font-family: verdana, 'courier new'; line-height: normal; "><a target="_blank"  m2a"="" href="http://blog.163.com/yangxy84/" style="color: #936e3f; cursor: pointer; text-decoration: none; "><span style="color: red; ">愚人有节</span></a></span><font class="Apple-style-span" color="#333333" face="Arial, Helvetica, simsun, u5b8bu4f53"><span class="Apple-style-span" style="line-height: 24px;"><br /></span></font><span class="Apple-style-span" style="color: #333333; font-family: Arial, Helvetica, simsun, u5b8bu4f53; line-height: 24px; ">拓扑排序：<a href="http://blog.csdn.net/midgard/article/details/4101025" title="拓扑排序">拓扑排序 &nbsp;</a>作者：<div style="display: inline !important; "><span style="font-family: Arial, Console, Verdana, 'Courier New'; font-size: 12px; font-weight: bold; line-height: 14px; color: red; ">midgard</span></div><br /></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;<a href="http://www.cnblogs.com/shanyou/archive/2006/11/16/562861.html" title="如何去理解 拓扑排序算法">如何去理解 拓扑排序算法</a>&nbsp;作者：<span class="Apple-style-span" style="font-family: verdana, 'ms song', 宋体, Arial, 微软雅黑, Helvetica, sans-serif; line-height: normal; color: red; "><strong style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; ">张善友</strong></span><br /><span class="Apple-style-span" style="color: #333333; font-family: Arial, Helvetica, simsun, u5b8bu4f53; line-height: 24px; ">关键路径：<a href="http://www.cnblogs.com/navorse/articles/1893863.html" title="关键路径" target="_blank">关键路径</a>&nbsp;作者：<span class="Apple-style-span" style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; line-height: 16px; color: #000000; "><a href="http://home.cnblogs.com/u/navorse/" style="color: navy; text-decoration: none; padding-top: 1px; padding-right: 1px; padding-bottom: 1px; padding-left: 1px; font-size: 11.5px; font-style: italic; "><span style="color: red; ">navorse</span></a></span><br /></span><font class="Apple-style-span" color="#333333" face="Arial, Helvetica, simsun, u5b8bu4f53"><span class="Apple-style-span" style="line-height: 24px;">欧拉路：</span></font><a href="http://hi.baidu.com/luyade1987/blog/item/f2304d0fd6b4922f6059f3ab.html" target="_blank" title="欧拉路问题" style="color: #333333; font-family: Arial, Helvetica, simsun, u5b8bu4f53; line-height: 24px; ">欧拉路问题</a><font class="Apple-style-span" color="#333333" face="Arial, Helvetica, simsun, u5b8bu4f53"><span class="Apple-style-span" style="line-height: 24px;">&nbsp;作者：</span></font><span class="Apple-style-span" style="line-height: 24px; font-family: tahoma, arial, 宋体, sans-serif; color: #000000; "><a href="http://hi.baidu.com/luyade1987/home" style="text-decoration: none; color: #5fa207; "><span style="font-size: 14px; color: red; ">MaiK</span></a></span><font class="Apple-style-span" color="#333333" face="Arial, Helvetica, simsun, u5b8bu4f53"><span class="Apple-style-span" style="line-height: 24px;"><br /></span></font><span class="Apple-style-span" style="color: #333333; font-family: Arial, Helvetica, simsun, u5b8bu4f53; line-height: 24px; ">差分约束：<a href="http://fuliang.iteye.com/blog/368214" title="差分约束系统">差分约束系统</a>&nbsp;作者：<span class="Apple-style-span" style="font-family: Helvetica, Tahoma, Arial, sans-serif; font-weight: bold; line-height: 18px; color: red; ">fuliang</span><br /></span><span class="Apple-style-span" style="color: #333333; font-family: Arial, Helvetica, simsun, u5b8bu4f53; line-height: 24px; ">二分图最大匹配：<a href="http://starforever.blog.hexun.com/3963571_d.html" target="_blank" title="二分图匹配总结">二分图匹配总结</a>&nbsp;作者：<span class="Apple-style-span" style="color: #3b3b3b; line-height: 36px; font-family: Simsun; "><a href="http://hexun.com/starforever/default.html" title="访问北极天南星的个人门户" target="_blank" style="color: #0048aa; text-decoration: none; background-image: none; background-attachment: initial; background-origin: initial; background-clip: initial; background-color: initial; "><span style="color: red; ">北极天南星<br /></span></a></span>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;<a href="http://blog.163.com/baobao_zhang@126/blog/static/482523672008631103625967/" target="_blank">二分图匹配算法总结</a>&nbsp;作者：<span class="Apple-style-span" style="color: #000000; line-height: normal; "><a target="_blank"  m2a"="" href="http://blog.163.com/baobao_zhang@126/" style="cursor: pointer; text-decoration: none; color: #2886e4; "><span style="color: red; ">z7m8v6</span></a></span><br /></span><span class="Apple-style-span" style="color: #333333; font-family: Arial, Helvetica, simsun, u5b8bu4f53; line-height: 24px; ">网络流：<a href="http://chhaj5236.blog.163.com/blog/static/1128810812009827112857794/" target="_blank" title="网络流基础">网络流基础</a>&nbsp;作者：<span class="Apple-style-span" style="font-family: verdana, 'courier new'; color: #000000; line-height: normal; "><span style="cursor: pointer; color: red; ">chhaj523</span></span><br /></span><font class="Apple-style-span" color="#333333" face="Arial, Helvetica, simsun, u5b8bu4f53"><span class="Apple-style-span" style="line-height: 24px; "><br /></span></font><span style="background-color: yellow; "><font class="Apple-style-span" color="#333333" face="Arial, Helvetica, simsun, u5b8bu4f53"><span class="Apple-style-span" style="line-height: 25px; ">数据结构<br /></span><span class="Apple-style-span" style="line-height: 25px; background-color: #ffffff; ">链表:<a title="基本数据结构：链表（list）" href="http://www.cppblog.com/cxiaojia/archive/2012/07/31/185760.html"><span style="background-color: #ffffff; ">基本数据结构：链表（list）</span></a></span><span class="Apple-style-span" style="line-height: 25px; background-color: #ffffff; ">&nbsp;作者:</span><span class="Apple-style-span" style="line-height: 25px; background-color: #ffffff; color: red; ">C小加<br /></span><span class="Apple-style-span" style="line-height: 25px; background-color: #ffffff; ">栈:</span></font></span>
<span style="font-family: Verdana, Geneva, Arial, Helvetica, sans-serif; font-size: 13px; line-height: 19px; text-align: center; background-color: #ffffff; "><span style="font-family: 微软雅黑, sans-serif; "><a href="http://www.cppblog.com/cxiaojia/archive/2012/08/01/185913.html" target="_blank">基本数据结构：栈（stack）</a></span></span>&nbsp;作者:<span style="color: #ff0000; font-family: Arial, Helvetica, simsun, u5b8bu4f53; line-height: 25px; background-color: #ffffff; ">C小加</span>&nbsp;<br />队列:<a title="基本数据结构：队列（queue）" href="http://www.cppblog.com/cxiaojia/archive/2012/08/02/186033.html" target="_blank">基本数据结构：队列（queue）</a>&nbsp;作者:<span style="color: #ff0000; font-family: Arial, Helvetica, simsun, u5b8bu4f53; line-height: 25px; background-color: #ffffff; ">C小加</span>&nbsp;<br />&nbsp;树:<a title="基本数据结构：树（tree）" href="http://www.cppblog.com/cxiaojia/archive/2012/08/03/186123.html" target="_blank">基本数据结构：树（tree）</a>&nbsp;作者:<span style="color: #ff0000; font-family: Arial, Helvetica, simsun, u5b8bu4f53; line-height: 25px; background-color: #ffffff; ">C小加</span>&nbsp;&nbsp;<br />二叉树:<a href="http://www.cppblog.com/cxiaojia/archive/2012/08/06/186432.html" target="_blank" title="基本数据结构：二叉树（binary tree）">基本数据结构：二叉树（binary tree）</a>作者:<span style="color: #ff0000; font-family: Arial, Helvetica, simsun, u5b8bu4f53; line-height: 25px; background-color: #ffffff; ">C小加</span>&nbsp;<br />二叉查找树:<a title="一步一步写二叉查找树" href="http://www.cppblog.com/cxiaojia/archive/2012/08/09/186752.html" target="_blank">一步一步写二叉查找树</a>&nbsp;&nbsp;作者:<span style="color: #ff0000; font-family: Arial, Helvetica, simsun, u5b8bu4f53; line-height: 25px; background-color: #ffffff; ">C小加</span>&nbsp;&nbsp;<br /><span style="background-color: yellow; "><font class="Apple-style-span" color="#333333" face="Arial, Helvetica, simsun, u5b8bu4f53"><span class="Apple-style-span" style="line-height: 25px; "><span class="Apple-style-span" style="font-family: verdana, 'courier new'; line-height: 19px; color: #000000; background-color: #ffffff; ">并查集：<a href="http://www.cnblogs.com/cherish_yimi/archive/2009/10/11/1580839.html" title="并查集--学习详解">并查集--学习详解</a>&nbsp;作者：<span class="Apple-style-span" style="font-family: 宋体; color: red; ">yx_th000</span><br /></span></span></font></span><span class="Apple-style-span" style="line-height: 19px; ">哈希表：<a href="http://www.cnblogs.com/jiewei915/archive/2010/08/09/1796042.html" title="哈希表">哈希表</a>&nbsp;作者：</span><span class="Apple-style-span" style="line-height: 19px; color: red; ">猎人杰</span><span class="Apple-style-span" style="line-height: 19px; "></span><br /><span class="Apple-style-span" style="line-height: 19px; ">二分查找：<a href="http://www.cnblogs.com/xiaosuo/archive/2010/04/07/1687231.html" title="查找（二）：二分查找">查找（二）：二分查找</a>&nbsp;作者：<span class="Apple-style-span" style="color: #88866f; font-family: verdana, 'ms song', Arial, Helvetica, sans-serif; line-height: 21px; "><a href="http://home.cnblogs.com/u/xiaosuo/" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; color: #464646; text-decoration: none; "><span style="color: red; ">xiaosuo</span></a></span><br /></span><span class="Apple-style-span" style="line-height: 19px;">哈夫曼树：</span><a href="http://www.cppblog.com/Cass/archive/2011/10/02/157353.aspx" title="哈夫曼树" style="line-height: 19px; ">哈夫曼树</a><span class="Apple-style-span" style="line-height: 19px;">&nbsp;作者：</span><span class="Apple-style-span" style="line-height: 19px; color: red; ">angle<br /><span class="Apple-style-span" style="color: #000000; ">平衡二叉树：&nbsp;<a href="http://www.cnblogs.com/fornever/archive/2011/11/15/2249492.html" target="_blank">平衡二叉树（解惑）</a> 作者：<span style="color: red; ">Never</span></span><br /></span>树状数组：<a href="http://hi.baidu.com/%D0%DC%C3%A8yingcai/blog/item/b329184ef0aa85f5d62afce1.html" target="_blank">树状数组总结</a> 作者：<span class="Apple-style-span" style="font-family: Arial; line-height: 18px; white-space: nowrap; color: red; ">熊猫yingcai</span><br />线段树：&nbsp;<a href="http://duanple.blog.163.com/blog/static/70971767200922110494318" target="_blank">线段树总结</a> 作者：<span style="color: red; ">星星</span><br />归并排序求逆序数：<a href="http://www.cppblog.com/jake1036/archive/2011/04/06/143531.html" title="利用归并排序求逆序数">利用归并排序求逆序数</a>&nbsp; 作者：<a href="http://www.cppblog.com/jake1036/" style="color: #999966; font-family: verdana, arial, sans-serif; font-size: 12px; line-height: 19px; background-color: #ffffff; "><span style="color: red; ">kahn<br /><br /></span></a><br /><span style="background-color: #ffff00; ">动态规划（DP）</span><br />简单动态规划：<a href="http://www.cnblogs.com/brokencode/archive/2011/06/26/2090702.html" title="动态规划">动态规划</a>&nbsp;作者：<span class="Apple-style-span" style="color: #333333; font-family: verdana, 宋体, Arial; line-height: 18px; "><a href="http://home.cnblogs.com/u/brokencode/" style="margin-top: 0px; margin-right: 0px; margin-bottom: 0px; margin-left: 0px; padding-top: 0px; padding-right: 0px; padding-bottom: 0px; padding-left: 0px; text-decoration: none; color: #333333; "><span style="color: red; ">brokencode</span></a></span><br />背包问题：《背包九讲》<br /><br /><br /><span style="background-color: #ffff00; ">数学</span><br />遗传算法：&nbsp;<a href="http://www.cnblogs.com/heaad/archive/2010/12/23/1914725.html" title="遗传算法入门">遗传算法入门</a>&nbsp;作者：<span style="color: red; ">heaad</span><br />容斥原理：<a href="http://www.cppblog.com/vici/archive/2011/09/05/155103.html" title="容斥原理（翻译）" target="_blank">容斥原理（翻译）</a>&nbsp;作者：<span style="background-color: #ffffff; font-family: verdana, Arial, helvetica, sans-seriff; font-size: 13px; line-height: 20px; text-align: right; color: red; ">vici</span><font color="#333333" face="Arial"><span style="line-height: 24px;"><br /></span></font><span class="Apple-style-span" style="color: #333333; font-family: Arial; line-height: 24px; ">母函数：<a href="http://blog.csdn.net/zhangxiang0125/article/details/6177930" title="母函数入门小结" target="_blank">母函数入门小结</a>&nbsp;作者：</span><span style="background-color: #ffffff; font-family: Arial, Console, Verdana, 'Courier New'; font-size: 12px; font-weight: bold; line-height: 14px; text-align: center; color: red; ">zhangxiang0125<br /></span><span class="Apple-style-span" style="color: #333333; font-family: Arial; line-height: 24px; ">秦九韶算法：<a href="http://blog.csdn.net/simonezhlx/article/details/5443714" title="秦九韶算法">秦九韶算法</a>&nbsp;作者：</span><span style="background-color: #ffffff; font-family: Arial, Console, Verdana, 'Courier New'; font-size: 12px; font-weight: bold; line-height: 14px; text-align: center; color: red; ">simonezhlx</span><span class="Apple-style-span" style="color: #333333; font-family: Arial; line-height: 24px; "><br /></span><span class="Apple-style-span" style="color: #333333; font-family: Arial; line-height: 24px; ">高斯消元法：</span><br /><span class="Apple-style-span" style="color: #333333; font-family: Arial; line-height: 24px; ">欧几里得定理（GCD）：</span><br /><span class="Apple-style-span" style="color: #333333; font-family: Arial; line-height: 24px; ">扩展欧几里得定理：</span><br /><span class="Apple-style-span" style="color: #333333; font-family: Arial; line-height: 24px; ">中国剩余定理：</span><br /><span class="Apple-style-span" style="color: #333333; font-family: Arial; line-height: 24px; ">概率问题：</span><br /><font class="Apple-style-span" color="#ff0000"><br /></font><span style="background-color: #ffff00; ">计算几何</span><br />几何公式：<br />离散化：&nbsp;<a href="http://www.matrix67.com/blog/archives/108" target="_blank">什么是离散化？</a>&nbsp;作者：<span style="color: red; ">matrix67</span><br />扫描线算法：<br />叉积和点积：<br />凸包：<br /><br /><br /><span><div><span style="color: red; "></span></div></span><span><br /></span><img src ="http://www.cppblog.com/cxiaojia/aggbug/160269.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cxiaojia/" target="_blank">C小加</a> 2011-11-16 15:58 <a href="http://www.cppblog.com/cxiaojia/archive/2011/11/16/rumen.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item><item><title>KMP算法中关于next数组的探究</title><link>http://www.cppblog.com/cxiaojia/archive/2011/09/20/kmp.html</link><dc:creator>C小加</dc:creator><author>C小加</author><pubDate>Tue, 20 Sep 2011 10:11:00 GMT</pubDate><guid>http://www.cppblog.com/cxiaojia/archive/2011/09/20/kmp.html</guid><wfw:comment>http://www.cppblog.com/cxiaojia/comments/156343.html</wfw:comment><comments>http://www.cppblog.com/cxiaojia/archive/2011/09/20/kmp.html#Feedback</comments><slash:comments>7</slash:comments><wfw:commentRss>http://www.cppblog.com/cxiaojia/comments/commentRss/156343.html</wfw:commentRss><trackback:ping>http://www.cppblog.com/cxiaojia/services/trackbacks/156343.html</trackback:ping><description><![CDATA[&nbsp;&nbsp;&nbsp;&nbsp; 摘要: 从《严书》上看到了KMP算法，看了一遍没懂，但觉得挺神奇的，就花费了几天时间深入的理解。算法的原理其实不难，难的就是那个巧妙的next数组，这个next数组很吸引我，我的大部分时间也都是花费在这个数组上面的。这个next数组是KMP里面一个很关键的地方，对于在数据结构书上看过一遍整个算法流程的人，能够把next数组搞明白，整个KMP算法的整体思想就差不多理解了。然后在一些细节上面深入思考一下，就可...&nbsp;&nbsp;<a href='http://www.cppblog.com/cxiaojia/archive/2011/09/20/kmp.html'>阅读全文</a><img src ="http://www.cppblog.com/cxiaojia/aggbug/156343.html" width = "1" height = "1" /><br><br><div align=right><a style="text-decoration:none;" href="http://www.cppblog.com/cxiaojia/" target="_blank">C小加</a> 2011-09-20 18:11 <a href="http://www.cppblog.com/cxiaojia/archive/2011/09/20/kmp.html#Feedback" target="_blank" style="text-decoration:none;">发表评论</a></div>]]></description></item></channel></rss>