<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>我想网 &#187; Algorithm</title>
	<atom:link href="http://www.iwanna.cn/topics/develope/algorithm/feed/" rel="self" type="application/rss+xml" />
	<link>http://www.iwanna.cn</link>
	<description></description>
	<lastBuildDate>Sat, 31 Jul 2010 15:12:14 +0000</lastBuildDate>
	<generator>http://wordpress.org/?v=2.9.2</generator>
	<language>en</language>
	<sy:updatePeriod>hourly</sy:updatePeriod>
	<sy:updateFrequency>1</sy:updateFrequency>
			<item>
		<title>一些重要的算法</title>
		<link>http://www.iwanna.cn/archives/2010/07/23/4695/</link>
		<comments>http://www.iwanna.cn/archives/2010/07/23/4695/#comments</comments>
		<pubDate>Fri, 23 Jul 2010 14:36:50 +0000</pubDate>
		<dc:creator>seasun</dc:creator>
				<category><![CDATA[Algorithm]]></category>

		<guid isPermaLink="false">http://www.iwanna.cn/?p=4695</guid>
		<description><![CDATA[下面是一些比较重要的算法，原文罗列了32个，但我觉得有很多是数论里的或是比较生僻的，和计算机的不相干，所以没有选取。下面的这些，有的我们经常在用，有的基本不用。有的很常见，有的很偏。不过了解一下也是好事。也欢迎你留下你觉得有意义的算法。（注：本篇文章并非翻译，其中的算法描述 大部份摘自Wikipedia，因为维基百科描述的很专业了）


A*搜寻算法
俗称A星算法。这是一种在图形平面上， 有多个节点的路径，求出最低通过成本的算法。常用于游戏中的NPC的移动计算，或线上游戏的BOT的移动计算上。该算法像Dijkstra算法一样，可以找到一条最短路径；也像BFS一样，进行启发式 的搜索。
Beam Search
束搜索(beam  search) 方法是解决优化问题的一种启发式方法,它是在分枝定界方法基础上发展起来的,它使用启发式方法估计k 个最好的路径,仅从这k  个路径出发向下搜索,即每一层只有满意的结点会被保留,其它的结点则被永久抛弃,从而比分枝定界法能大大节省运行时间。束搜索于20 世纪70  年代中期首先被应用于人工智能领域,1976 年Lowerre  在其称为HARPY的语音识别系统中第一次使用了束搜索方法,他的目标是并行地搜索几个潜在的最优决策路径以减少回溯,并快速地获得一个解。
二分取中查找算法
一种在有序数组中查找某一特定元素 的搜索算法。搜素过程从数组的中间元素开始，如果中间元素正好是要查找的元素，则搜素过程结束；如果某一特定元素大于或者小于中间元素，则在数组大于或小 于中间元素的那一半中查找，而且跟开始一样从中间元素开始比较。这种搜索算法每一次比较都使搜索范围缩小一半。
Branch and bound
分支定界  (branch and bound)  算法是一种在问题的解空间树上搜索问题的解的方法。但与回溯算法不同，分支定界算法采用广度优先或最小耗费优先的方法搜索解空间树，并且，在分支定界算法 中，每一个活结点只有一次机会成为扩展结点。
数据压缩
数据压缩是通过减少计算机中所存储数据或者通 信传播中数据的冗余度，达到增大数据密度，最终使数据的存储空间减少的技术。数据压缩在文件存储和分布式系统领域有着十分广泛的应用。数据压缩也代表着尺 寸媒介容量的增大和网络带宽的扩展。
Diffie–Hellman密钥协商
Diffie–Hellman  key exchange，简称“D–H”，  是一种安全协议。它可以让双方在完全没有对方任何预先信息的条件下通过不安全信道建立起一个密钥。这个密钥可以在后续的通讯中作为对称密钥来加密通讯内 容。
Dijkstra’s 算法
迪科斯彻算法 （Dijkstra）是由荷兰计算机科学家艾 兹格·迪科斯彻（Edsger Wybe  Dijkstra）发明的。算法解决的是有向图中单个源点到其他顶点的最短路径问题。举例来说，如果图中的顶点表示城市，而边上的权重表示著城市间开车行 经的距离，迪科斯彻算法可以用来找到两个城市之间的最短路径。
动态规划
动态规划是一种在数学和计算机科学中使用 的，用于求解包含重叠子问题的最优化问 题的方法。其基本思想是，将原问题分解为相似的子问题，在求解的过程中通过子问题的解求出原问题的解。动态规划的思想是多种算法的基础，被广泛应用于计算 机科学和工程领域。比较著名的应用实例有：求解最 短路径问题，背 包问题，项 目管理，网络流优 化等。这里也有一篇文章说得比较详细。
欧几里得算法
在数学中，辗转相除法，又称欧几里得算 法，是求最 大公约数的算法。辗转相除法首次出现于欧 几里得的《几 何原本》（第VII卷，命题i和ii）中，而在中国则可以追溯至东汉出现的《九 章算术》。
最大期望（EM）算法
在统计计算中，最大期望 [...]]]></description>
			<content:encoded><![CDATA[<p>下面是一些比较重要的算法，<a href="http://www.risc.jku.at/people/ckoutsch/stuff/e_algorithms.html" target="_blank">原文</a>罗列了32个，但我觉得有很多是数论里的或是比较生僻的，和计算机的不相干，所以没有选取。下面的这些，有的我们经常在用，有的基本不用。有的很常见，有的很偏。不过了解一下也是好事。也欢迎你留下你觉得有意义的算法。（注：本篇文章并非翻译，其中的算法描述 大部份摘自Wikipedia，因为维基百科描述的很专业了）<br />
<span id="more-4695"></span></p>
<ol>
<li><big><a href="http://zh.wikipedia.org/zh-cn/A*%E6%90%9C%E5%AF%BB%E7%AE%97%E6%B3%95" target="_blank"><strong>A*搜寻算法</strong><br />
</a></big>俗称A星算法。这是一种在图形平面上， 有多个节点的路径，求出最低通过成本的算法。常用于游戏中的NPC的移动计算，或线上游戏的BOT的移动计算上。该算法像<a title="Dijkstra算法" href="http://zh.wikipedia.org/zh-cn/Dijkstra%E7%AE%97%E6%B3%95" target="_blank">Dijkstra算法</a>一样，可以找到一条最短路径；也像<a title="BFS" href="http://zh.wikipedia.org/zh-cn/BFS" target="_blank">BFS</a>一样，进行启发式 的搜索。</li>
<li><big><a href="http://en.wikipedia.org/wiki/Beam_search" target="_blank"><strong>Beam Search</strong></a></big><br />
束搜索(beam  search) 方法是解决优化问题的一种启发式方法,它是在分枝定界方法基础上发展起来的,它使用启发式方法估计k 个最好的路径,仅从这k  个路径出发向下搜索,即每一层只有满意的结点会被保留,其它的结点则被永久抛弃,从而比分枝定界法能大大节省运行时间。束搜索于20 世纪70  年代中期首先被应用于人工智能领域,1976 年Lowerre  在其称为HARPY的语音识别系统中第一次使用了束搜索方法,他的目标是并行地搜索几个潜在的最优决策路径以减少回溯,并快速地获得一个解。</li>
<li><big><a href="http://zh.wikipedia.org/zh-cn/%E6%8A%98%E5%8D%8A%E6%90%9C%E7%B4%A2%E7%AE%97%E6%B3%95" target="_blank"><strong>二分取中查找算法</strong></a></big><br />
一种在有序数组中查找某一特定元素 的搜索算法。搜素过程从数组的中间元素开始，如果中间元素正好是要查找的元素，则搜素过程结束；如果某一特定元素大于或者小于中间元素，则在数组大于或小 于中间元素的那一半中查找，而且跟开始一样从中间元素开始比较。这种搜索算法每一次比较都使搜索范围缩小一半。</li>
<li><big><a href="http://en.wikipedia.org/wiki/Branch_and_bound" target="_blank"><strong>Branch and bound</strong></a></big><br />
分支定界  (branch and bound)  算法是一种在问题的解空间树上搜索问题的解的方法。但与回溯算法不同，分支定界算法采用广度优先或最小耗费优先的方法搜索解空间树，并且，在分支定界算法 中，每一个活结点只有一次机会成为扩展结点。</li>
<li><big><a href="http://en.wikipedia.org/wiki/Data_compression" target="_blank"><strong>数据压缩</strong></a><br />
</big>数据压缩是通过减少计算机中所存储数据或者通 信传播中数据的冗余度，达到增大数据密度，最终使数据的存储空间减少的技术。数据压缩在文件存储和分布式系统领域有着十分广泛的应用。数据压缩也代表着尺 寸媒介容量的增大和网络带宽的扩展。</li>
<li><big><a href="http://zh.wikipedia.org/zh-cn/Diffie-Hellman%E5%AF%86%E9%92%A5%E4%BA%A4%E6%8D%A2" target="_blank"><strong>Diffie–Hellman密钥协商</strong></a><br />
</big>Diffie–Hellman  key exchange，简称“D–H”，  是一种安全协议。它可以让双方在完全没有对方任何预先信息的条件下通过不安全信道建立起一个密钥。这个密钥可以在后续的通讯中作为对称密钥来加密通讯内 容。</li>
<li><big><a href="http://zh.wikipedia.org/zh-cn/%E8%BF%AA%E7%A7%91%E6%96%AF%E5%BD%BB%E7%AE%97%E6%B3%95" target="_blank"><strong>Dijkstra’s 算法</strong></a><br />
</big>迪科斯彻算法 （Dijkstra）是由荷兰计算机科学家<a title="艾兹格·迪科斯彻" href="http://zh.wikipedia.org/zh-cn/%E8%89%BE%E8%8C%B2%E6%A0%BC%C2%B7%E8%BF%AA%E7%A7%91%E6%96%AF%E5%BE%B9">艾 兹格·迪科斯彻</a>（Edsger Wybe  Dijkstra）发明的。算法解决的是有向图中单个源点到其他顶点的最短路径问题。举例来说，如果图中的顶点表示城市，而边上的权重表示著城市间开车行 经的距离，迪科斯彻算法可以用来找到两个城市之间的最短路径。</li>
<li><big><a href="http://zh.wikipedia.org/zh-cn/%E5%8A%A8%E6%80%81%E8%A7%84%E5%88%92" target="_blank"><strong>动态规划</strong></a><br />
</big>动态规划是一种在数学和计算机科学中使用 的，用于求解包含重叠子问题的<a title="最优化" href="http://zh.wikipedia.org/zh-cn/%E6%9C%80%E4%BC%98%E5%8C%96">最优化</a>问 题的方法。其基本思想是，将原问题分解为相似的子问题，在求解的过程中通过子问题的解求出原问题的解。动态规划的思想是多种算法的基础，被广泛应用于计算 机科学和工程领域。比较著名的应用实例有：求解<a title="最短路径" href="http://zh.wikipedia.org/zh-cn/%E6%9C%80%E7%9F%AD%E8%B7%AF%E5%BE%84">最 短路径</a>问题，<a title="背包问题" href="http://zh.wikipedia.org/zh-cn/%E8%83%8C%E5%8C%85%E9%97%AE%E9%A2%98">背 包问题</a>，<a title="项目管理" href="http://zh.wikipedia.org/zh-cn/%E9%A1%B9%E7%9B%AE%E7%AE%A1%E7%90%86">项 目管理</a>，<a title="网络流" href="http://zh.wikipedia.org/zh-cn/%E7%BD%91%E7%BB%9C%E6%B5%81">网络流</a>优 化等。这里也有<a href="http://www.cnblogs.com/drizzlecrj/archive/2007/10/26/939159.html" target="_blank">一篇文章</a>说得比较详细。</li>
<li><big><a href="http://zh.wikipedia.org/zh-cn/%E8%BC%BE%E8%BD%89%E7%9B%B8%E9%99%A4%E6%B3%95" target="_blank"><strong>欧几里得算法</strong></a><br />
</big>在数学中，辗转相除法，又称欧几里得算 法，是求<a title="最大公约数" href="http://zh.wikipedia.org/zh-cn/%E6%9C%80%E5%A4%A7%E5%85%AC%E7%BA%A6%E6%95%B0">最 大公约数</a>的算法。辗转相除法首次出现于<a title="欧几里得" href="http://zh.wikipedia.org/zh-cn/%E6%AC%A7%E5%87%A0%E9%87%8C%E5%BE%97">欧 几里得</a>的《<a title="几何原本" href="http://zh.wikipedia.org/zh-cn/%E5%87%A0%E4%BD%95%E5%8E%9F%E6%9C%AC">几 何原本</a>》（第VII卷，命题i和ii）中，而在中国则可以追溯至东汉出现的《<a title="九章算术" href="http://zh.wikipedia.org/zh-cn/%E4%B9%9D%E7%AB%A0%E7%AE%97%E6%9C%AF">九 章算术</a>》。</li>
<li><big><a href="http://zh.wikipedia.org/zh-cn/%E6%9C%80%E5%A4%A7%E6%9C%9F%E6%9C%9B%E7%AE%97%E6%B3%95" target="_blank"><strong>最大期望（EM）算法</strong></a><br />
</big>在统计计算中，最大期望 （EM）算法是在<a title="概率" href="http://zh.wikipedia.org/zh-cn/%E6%A6%82%E7%8E%87">概率</a>（<a title="en:probability" href="http://en.wikipedia.org/wiki/probability">probabilistic</a>） 模型中寻找参数最大似然估计的算法，其中概率模型依赖于无法观测的隐藏变量（<a title="en:latent variable" href="http://en.wikipedia.org/wiki/latent_variable">Latent Variable</a>）。 最大期望经常用在<a title="机器学习" href="http://zh.wikipedia.org/zh-cn/%E6%9C%BA%E5%99%A8%E5%AD%A6%E4%B9%A0">机 器学习</a>和<a title="计算机视觉" href="http://zh.wikipedia.org/zh-cn/%E8%AE%A1%E7%AE%97%E6%9C%BA%E8%A7%86%E8%A7%89">计 算机视觉</a>的<a title="数据聚类" href="http://zh.wikipedia.org/zh-cn/%E6%95%B0%E6%8D%AE%E8%81%9A%E7%B1%BB">数 据聚类</a>（<a title="en:data clustering" href="http://en.wikipedia.org/wiki/data_clustering">Data Clustering</a>） 领域。最大期望算法经过两个步骤交替进行计算，第一步是计算期望（E），利用对隐藏变量的现有估计值，计算其最大似然估计值；第二步是最大化（M），最大 化在 E 步上求得的最大似然值来计算参数的值。M 步上找到的参数估计值被用于下一个 E 步计算中，这个过程不断交替进行。</li>
<li><big><a href="http://zh.wikipedia.org/zh-cn/%E5%BF%AB%E9%80%9F%E5%82%85%E9%87%8C%E5%8F%B6%E5%8F%98%E6%8D%A2" target="_blank"><strong>快速傅里叶变换</strong></a><strong> (FFT)</strong><br />
</big>快 速傅里叶变换（Fast Fourier Transform，FFT），是<a title="离散傅里叶变换" href="http://zh.wikipedia.org/zh-cn/%E7%A6%BB%E6%95%A3%E5%82%85%E9%87%8C%E5%8F%B6%E5%8F%98%E6%8D%A2">离 散傅里叶变换</a>的快速算法，也可用于计算离散傅里叶变换的逆变换。快速傅里叶变换有广泛的应用，如<a title="数字信号处理" href="http://zh.wikipedia.org/zh-cn/%E6%95%B0%E5%AD%97%E4%BF%A1%E5%8F%B7%E5%A4%84%E7%90%86">数 字信号处理</a>、计算<a title="大整数乘法（尚未撰写）" href="http://zh.wikipedia.org/w/index.php?title=%E5%A4%A7%E6%95%B4%E6%95%B0%E4%B9%98%E6%B3%95&amp;action=edit&amp;redlink=1">大 整数乘法</a>、求解<a title="偏微分方程" href="http://zh.wikipedia.org/zh-cn/%E5%81%8F%E5%BE%AE%E5%88%86%E6%96%B9%E7%A8%8B">偏 微分方程</a>等等。本条目只描述各种快速算法，对于离散傅里叶变换的性质和应用，请参见<a title="离散傅里叶变换" href="http://zh.wikipedia.org/zh-cn/%E7%A6%BB%E6%95%A3%E5%82%85%E9%87%8C%E5%8F%B6%E5%8F%98%E6%8D%A2">离 散傅里叶变换</a>。</li>
<li><big><a href="http://zh.wikipedia.org/zh-cn/%E6%95%A3%E5%88%97%E5%87%BD%E6%95%B8" target="_blank"><strong>哈希函数</strong></a><br />
</big>Hash  Function是一种从任何一种数据中创建小的数字“指纹”的方法。该函数将数据打乱混合，重新创建一个叫做散列值的指纹。散列值通常用来代表一个短的 随机字母和数字组成的字符串。好的散列函数在输入域中很少出现散列冲突。在散列表和数据处理中，不抑制冲突来区别数据，会使得数据库记录更难找到。</li>
<li><big><a href="http://zh.wikipedia.org/zh-cn/%E5%A0%86%E7%A9%8D%E6%8E%92%E5%BA%8F" target="_blank"><strong>堆排序</strong></a><br />
</big><strong>Heapsort </strong>是 指利用<a title="堆 (数据结构)" href="http://zh.wikipedia.org/zh-cn/%E5%A0%86_%28%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%29">堆 积树</a>（<a title="堆 (数据结构)" href="http://zh.wikipedia.org/zh-cn/%E5%A0%86_%28%E6%95%B0%E6%8D%AE%E7%BB%93%E6%9E%84%29">堆</a>） 这种数据结构所设计的一种排序算法。堆积树是一个近似<a title="完全二叉树" href="http://zh.wikipedia.org/zh-cn/%E5%AE%8C%E5%85%A8%E4%BA%8C%E5%8F%89%E6%A0%91">完 全二叉树</a>的结构，并同时满足<em>堆积属性</em>：即子结点的键值或索引总是小于（或者大于）它的父结点。</li>
<li><big><a href="http://zh.wikipedia.org/zh-cn/%E5%BD%92%E5%B9%B6%E6%8E%92%E5%BA%8F" target="_blank"><strong>归并排序</strong></a><br />
</big><strong>Merge sort</strong>是 建立在归并操作上的一种有效的<a title="排序" href="http://zh.wikipedia.org/zh-cn/%E6%8E%92%E5%BA%8F">排序</a><a title="算法" href="http://zh.wikipedia.org/zh-cn/%E7%AE%97%E6%B3%95">算法</a>。 该算法是采用<a title="分治法" href="http://zh.wikipedia.org/zh-cn/%E5%88%86%E6%B2%BB%E6%B3%95">分治法</a>（Divide  and Conquer）的一个非常典型的应用。</li>
<li><big><a href="http://en.wikipedia.org/wiki/RANSAC" target="_blank"><strong>RANSAC  算法</strong></a><br />
</big>RANSAC 是”RANdom SAmple  Consensus”的缩写。该算法是用于从一组观测数据中估计数学模型参数的迭代方法，由Fischler and Bolles在1981  提出，它是一种非确定性算法，因为它只能以一定的概率得到合理的结果，随着迭代次数的增加，这种概率是增加的。  该算法的基本假设是观测数据集中存在”inliers”（那些对模型参数估计起到支持作用的点）和”outliers”（不符合模型的点），并且这组观测 数据受到噪声影响。RANSAC 假设给定一组”inliers”数据就能够得到最优的符合这组点的模型。</li>
<li><big><a href="http://zh.wikipedia.org/zh-tw/RSA%E5%8A%A0%E5%AF%86%E6%BC%94%E7%AE%97%E6%B3%95" target="_blank"><strong>RSA加密演算法</strong></a></big><br />
这是一个公钥加密算法，也是世界上 第一个适合用来做签名的算法。今天的RSA已经专利失效，其被广泛地用于电子商务加密，大家都相信，只要密钥足够长，这个算法就会是安全的</li>
<li><big><a href="http://zh.wikipedia.org/zh-cn/%E5%B9%B6%E6%9F%A5%E9%9B%86" target="_blank"><strong>并查集Union-find</strong></a><br />
</big>并查集是一种树型的数据结 构，用于处理一些不相交集合（Disjoint Sets）的合并及查询问题。常常在使用中以森林来表示。</li>
<li><big><a href="http://blog.52nlp.org/hmm-learn-best-practices-six-viterbi-algorithm-1" target="_blank"><strong>Viterbi algorithm</strong></a><br />
</big>寻找最可能的隐 藏状态序列(Finding most probable sequence of hidden states)</li>
</ol>
<p><strong>附录</strong></p>
<ul>
<li>关于这个世界上的算法，你可以看看Wikipedia的这个网页：<a href="http://en.wikipedia.org/wiki/List_of_algorithms">http://en.wikipedia.org/wiki/List_of_algorithms</a></li>
<li>关于排序算法，你可以看看本站的这几篇文章《<a rel="bookmark" href="http://coolshell.cn/?p=536" target="_blank">一个显示排序过程的Python脚本</a>》、 《<a rel="bookmark" href="http://coolshell.cn/?p=399" target="_blank">一个排 序算法比较的网站</a>》</li>
</ul>
<hr />
<p>© <a href="http://www.iwanna.cn">我想网</a> Akon 所有 , 2010. |
<a href="http://www.iwanna.cn/archives/2010/07/23/4695/">永久链接</a> |
<a href="http://www.iwanna.cn/archives/2010/07/23/4695/#comments">没有评论</a> |
提交到
<a rel="nofollow" target="_blank" href="http://www.google.com/reader/view/feed/http://www.iwanna.cn/archives/2010/07/23/4695/">Google Reader</a>
<a rel="nofollow" target="_blank" href="http://www.xianguo.com/subscribe.php?url=http://www.iwanna.cn/archives/2010/07/23/4695/">鲜果</a>
<a rel="nofollow" target="_blank" href="http://www.zhuaxia.com/add_channel.php?url=http://www.iwanna.cn/archives/2010/07/23/4695/">抓虾</a>
<hr />
</p>
	标签：<a href="http://www.iwanna.cn/topics/develope/algorithm/" title="Algorithm" rel="tag nofollow">Algorithm</a>, <a href="http://www.iwanna.cn/tags/algorithm/" title="Algorithm" rel="tag nofollow">Algorithm</a><br />

	<h2 class="related_post">您可能会感兴趣的其他文章</h2>
	<ul class="st-related-posts">
	<li><a href="http://www.iwanna.cn/archives/2009/03/31/71/" title="递归－三角数字 (2009年03月31日)">递归－三角数字</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/06/08/3769/" title="用PHP数组对百万数据进行排重 (2010年06月8日)">用PHP数组对百万数据进行排重</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/07/21/4661/" title="浅谈递归过程以及递归的优化 (2010年07月21日)">浅谈递归过程以及递归的优化</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/07/23/4680/" title="检查素数的正则表达式 (2010年07月23日)">检查素数的正则表达式</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/03/31/69/" title="排序－选择 (2009年03月31日)">排序－选择</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/03/31/75/" title="排序－插入 (2009年03月31日)">排序－插入</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/03/31/73/" title="排序－冒泡 (2009年03月31日)">排序－冒泡</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/05/03/929/" title="排序算法汇总 (2009年05月3日)">排序算法汇总</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/04/09/323/" title="全文检索中近义词、关联词的解决方案 (2009年04月9日)">全文检索中近义词、关联词的解决方案</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/07/13/4513/" title="一个显示排序过程的Python脚本 (2010年07月13日)">一个显示排序过程的Python脚本</a> </li>
</ul>


<p><small>Feed enhanced by <a href='http://planetozh.com/blog/my-projects/wordpress-plugin-better-feed-rss/'>Better Feed</a> from  <a href='http://planetozh.com/blog/'>Ozh</a></small></p>
]]></content:encoded>
			<wfw:commentRss>http://www.iwanna.cn/archives/2010/07/23/4695/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>检查素数的正则表达式</title>
		<link>http://www.iwanna.cn/archives/2010/07/23/4680/</link>
		<comments>http://www.iwanna.cn/archives/2010/07/23/4680/#comments</comments>
		<pubDate>Fri, 23 Jul 2010 04:14:14 +0000</pubDate>
		<dc:creator>seasun</dc:creator>
				<category><![CDATA[Algorithm]]></category>
		<category><![CDATA[RegEx]]></category>

		<guid isPermaLink="false">http://www.iwanna.cn/?p=4680</guid>
		<description><![CDATA[一般来说，我们会使用正规表达式来做字符串匹配，今天在网上浏览的时候，看到了有人用正则表达式来检查一个数字是否为素数（质数），让我非常感兴趣，这个正则表达式如入所示：
检查素数的正则表达式/^1?$&#124;^(11+?) +$/
要使用这个正规则表达式，你需要把自然数转成多个1的字符串，如：2 要写成 “11”， 3 要写成 “111”, 17 要写成“11111111111111111”，这种工作使用一些脚本语言可以轻松的完成。

一开始我对这个表达式持怀疑态度，但仔细研究了一下这个表达式，发现是非常合理的，下面，让我带你来细细剖析一下是这个表达式的工作原理。
首先，我们看到这个表达式中有“&#124;”，也就是说这个表达式可以分成两个部分：/^1?$/ 和 /^(11+?)\1+$/

第一部分：/^1?$/， 这个部分相信不用我多说了，其表示匹配“非空串”以及字串中不只一个“1”的字符串。
第二部分：/^(11+?)\1+$/，这个部分是整个表达式的关键部分。其可以分成两个部分，(11+?) 和\1+$，前半部很简单了，匹配以“11”开头的并重复0或n个1的字符串，后面的部分意思是把前半部分作为一个字串去匹配还剩下的字符串1次或多次（这句话的意思是——剩余的字串的1的个数要是前面字串1个数的整数倍）。

通过上面的分析，我们知道，第二部分是最重要的，对于第二部分，举几个例子，
示例一：判断自然数8。我们可以知道，8转成我们的格式就是“11111111”，对于(11+?)，其匹配了“11”，于是还剩下“111111”，而\1+$正好匹配了剩下的“111111”，因为，“11”这个模式在“111111”出现了三次，符合模式匹配，返回true。取反（^），所以，得到false，于是这个数不是质数。
示例二：判断自然数11。转成我们需要的格式是“11111111111”（十一个1），对于(11+?)，其匹配了“11”（前两个1），还剩下“111111111”（九个1），而\1+$无 法为“11”匹配那“九个1”，因为“11”这个模式并没有在“九个1”这个串中正好出现N次。于是，我们的正则表达式引擎会尝试下一种方法，先匹配 “111”（前三个1），然后把“111”作为模式去匹配剩下的“11111111”（八个1），很明显，那“八个1”并没有匹配“三个1”多次。所以， 引擎会继续向下尝试……直至返回false。
通过示例二，我们可以得到这样的等价数算算法，正则表达式会匹配这若干个1中有没有出现“二个1”的整数倍，“三个1”的整数倍，“四个1”的整数倍……，而，这正好是我们需要的算素数的算法。现在大家明白了吧。
下面，我们用perl来使用这个正规则表达式不停地输出素数：（关于perl的语法我就不多说了）
perl -e'$&#124;++;(1 x$_)!~/^1?$&#124;^(11+?)\1+$/&#38;&#38;print"$_ "while ++$_'
另外，让我们来举一反三，根据上述的这种方法，我们甚至可以用正则表达式来求证某方式是否有解，如：

二元方程：17x + 12y = 51   判断其是否有解的正则表达式是：^(.*)\1{16}(.*)\2{11}$
三元方程：11x + 2y + 5z = 115 判断其是否有解的正则表达式是：^(.*)\1{10}(.*)\2{1}(.*)\3{4}$

大家不妨自己做做练习，为什么上述的两个正则表达式可以判断方程是否有解。如果无法参透其中的奥妙的话，你可以读读这篇英文文章。

© 我想网 Akon 所有 , 2010. &#124;
永久链接 &#124;
没有评论 &#124;
提交到
Google Reader
鲜果
抓虾


	标签：Algorithm, Algorithm, RegEx, RegEx

	您可能会感兴趣的其他文章
	
	高级正则表达式的重要概念 
	递归－三角数字 
	用PHP数组对百万数据进行排重 
	浅谈递归过程以及递归的优化 
	正则表达式入门 
	排序－选择 
	排序－插入 
	排序－冒泡 
	排序算法汇总 
	常用的正则表达式 



Feed [...]]]></description>
			<content:encoded><![CDATA[<p>一般来说，我们会<strong><a href="http://www.iwanna.cn/archives/2010/07/23/4680/" title="检查素数的正则表达式">使用正规表达式来做字符串匹配</a></strong>，今天在网上浏览的时候，看到了有人用正则表达式来检查一个数字是否为素数（质数），让我非常感兴趣，这个正则表达式如入所示：<br />
<img title="检查素数的正则表达式" src="http://images.uheed.com/iwanna/2010/07/23/regexpr-for-prime-number.jpg" alt="检查素数的正则表达式 | iwanna.cn 我想网" width="450" height="45" />检查素数的正则表达式/^1?$|^(11+?) +$/</p>
<p>要使用这个正规则表达式，你需要把自然数转成多个1的字符串，如：2 要写成 “11”， 3 要写成 “111”, 17 要写成“11111111111111111”，这种工作使用一些脚本语言可以轻松的完成。<br />
<span id="more-4680"></span><br />
一开始我对这个表达式持怀疑态度，但仔细研究了一下这个表达式，发现是非常合理的，下面，让我带你来细细剖析一下是这个表达式的工作原理。</p>
<p>首先，我们看到这个表达式中有“|”，也就是说这个表达式可以分成两个部分：/^1?$/ 和 /^(11+?)\1+$/</p>
<ul>
<li><strong>第一部分：/^1?$/</strong>， 这个部分相信不用我多说了，其表示匹配“非空串”以及字串中不只一个“1”的字符串。</li>
<li><strong>第二部分：/^(11+?)\1+$/</strong>，这个部分是整个表达式的关键部分。其可以分成两个部分，<strong>(11+?)</strong> 和<strong>\1+$</strong>，前半部很简单了，匹配以“11”开头的并重复0或n个1的字符串，后面的部分意思是把前半部分作为一个字串去匹配还剩下的字符串1次或多次（这句话的意思是——剩余的字串的1的个数要是前面字串1个数的整数倍）。</li>
</ul>
<p>通过上面的分析，我们知道，第二部分是最重要的，对于第二部分，举几个例子，</p>
<p><strong>示例一：判断自然数8</strong>。我们可以知道，8转成我们的格式就是“11111111”，对于<strong>(11+?)</strong>，其匹配了“11”，于是还剩下“111111”，而<strong>\1+$</strong>正好匹配了剩下的“111111”，因为，“11”这个模式在“111111”出现了三次，符合模式匹配，返回true。取反（^），所以，得到false，于是这个数不是质数。</p>
<p><strong>示例二：判断自然数11</strong>。转成我们需要的格式是“11111111111”（十一个1），对于<strong>(11+?)</strong>，其匹配了“11”（前两个1），还剩下“111111111”（九个1），而<strong>\1+$</strong>无 法为“11”匹配那“九个1”，因为“11”这个模式并没有在“九个1”这个串中正好出现N次。于是，我们的正则表达式引擎会尝试下一种方法，先匹配 “111”（前三个1），然后把“111”作为模式去匹配剩下的“11111111”（八个1），很明显，那“八个1”并没有匹配“三个1”多次。所以， 引擎会继续向下尝试……直至返回false。</p>
<p>通过示例二，我们可以得到这样的等价数算算法，正则表达式会匹配这若干个1中有没有出现“二个1”的整数倍，“三个1”的整数倍，“四个1”的整数倍……，而，这正好是我们需要的算素数的算法。现在大家明白了吧。</p>
<p>下面，我们用perl来使用这个正规则表达式不停地输出素数：（关于perl的语法我就不多说了）</p>
<pre>perl -e'$|++;(1 x$_)!~/^1?$|^(11+?)\1+$/&amp;&amp;print"$_ "while ++$_'</pre>
<p>另外，让我们来举一反三，根据上述的这种方法，我们甚至可以用正则表达式来求证某方式是否有解，如：</p>
<ul>
<li><strong>二元方程</strong>：17x + 12y = 51   判断其是否有解的正则表达式是：<strong>^</strong><strong>(</strong><strong>.*</strong><strong>)</strong><strong>\1{16}</strong><strong>(</strong><strong>.*</strong><strong>)</strong><strong>\2{11}$</strong></li>
<li><strong>三元方程</strong>：11x + 2y + 5z = 115 判断其是否有解的正则表达式是：<strong>^</strong><strong>(</strong><strong>.*</strong><strong>)</strong><strong>\1{10}</strong><strong>(</strong><strong>.*</strong><strong>)</strong><strong>\2{1}</strong><strong>(</strong><strong>.*</strong><strong>)</strong><strong>\3{4}$</strong></li>
</ul>
<p>大家不妨自己做做练习，为什么上述的两个正则表达式可以判断方程是否有解。如果无法参透其中的奥妙的话，你可以读读这篇<a href="http://blog.stevenlevithan.com/archives/algebra-with-regexes" target="_blank">英文文章</a>。</p>
<hr />
<p>© <a href="http://www.iwanna.cn">我想网</a> Akon 所有 , 2010. |
<a href="http://www.iwanna.cn/archives/2010/07/23/4680/">永久链接</a> |
<a href="http://www.iwanna.cn/archives/2010/07/23/4680/#comments">没有评论</a> |
提交到
<a rel="nofollow" target="_blank" href="http://www.google.com/reader/view/feed/http://www.iwanna.cn/archives/2010/07/23/4680/">Google Reader</a>
<a rel="nofollow" target="_blank" href="http://www.xianguo.com/subscribe.php?url=http://www.iwanna.cn/archives/2010/07/23/4680/">鲜果</a>
<a rel="nofollow" target="_blank" href="http://www.zhuaxia.com/add_channel.php?url=http://www.iwanna.cn/archives/2010/07/23/4680/">抓虾</a>
<hr />
</p>
	标签：<a href="http://www.iwanna.cn/topics/develope/algorithm/" title="Algorithm" rel="tag nofollow">Algorithm</a>, <a href="http://www.iwanna.cn/tags/algorithm/" title="Algorithm" rel="tag nofollow">Algorithm</a>, <a href="http://www.iwanna.cn/tags/regex/" title="RegEx" rel="tag nofollow">RegEx</a>, <a href="http://www.iwanna.cn/topics/develope/regex-develope/" title="RegEx" rel="tag nofollow">RegEx</a><br />

	<h2 class="related_post">您可能会感兴趣的其他文章</h2>
	<ul class="st-related-posts">
	<li><a href="http://www.iwanna.cn/archives/2009/06/02/1652/" title="高级正则表达式的重要概念 (2009年06月2日)">高级正则表达式的重要概念</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/03/31/71/" title="递归－三角数字 (2009年03月31日)">递归－三角数字</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/06/08/3769/" title="用PHP数组对百万数据进行排重 (2010年06月8日)">用PHP数组对百万数据进行排重</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/07/21/4661/" title="浅谈递归过程以及递归的优化 (2010年07月21日)">浅谈递归过程以及递归的优化</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/04/09/318/" title="正则表达式入门 (2009年04月9日)">正则表达式入门</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/03/31/69/" title="排序－选择 (2009年03月31日)">排序－选择</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/03/31/75/" title="排序－插入 (2009年03月31日)">排序－插入</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/03/31/73/" title="排序－冒泡 (2009年03月31日)">排序－冒泡</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/05/03/929/" title="排序算法汇总 (2009年05月3日)">排序算法汇总</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/04/09/321/" title="常用的正则表达式 (2009年04月9日)">常用的正则表达式</a> </li>
</ul>


<p><small>Feed enhanced by <a href='http://planetozh.com/blog/my-projects/wordpress-plugin-better-feed-rss/'>Better Feed</a> from  <a href='http://planetozh.com/blog/'>Ozh</a></small></p>
]]></content:encoded>
			<wfw:commentRss>http://www.iwanna.cn/archives/2010/07/23/4680/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>浅谈递归过程以及递归的优化</title>
		<link>http://www.iwanna.cn/archives/2010/07/21/4661/</link>
		<comments>http://www.iwanna.cn/archives/2010/07/21/4661/#comments</comments>
		<pubDate>Wed, 21 Jul 2010 15:11:08 +0000</pubDate>
		<dc:creator>seasun</dc:creator>
				<category><![CDATA[Algorithm]]></category>

		<guid isPermaLink="false">http://www.iwanna.cn/?p=4661</guid>
		<description><![CDATA[近日翻看SICP，看到递归的部分，深有感触，遂记下所想所悟，如果有批评直言，望不吝赐教。
递归是实现程序计算过程中的描述过程 的基本模式之一，在讨论递归的问题前我们必须十分小心，因为递归包含两个方面的内容，一个是递归的计算过程，一个是递归过程，后者是语法上的事实而前者是 概念上的计算过程，事实上在程序上我们也许是使用循环来实现的。
一般在讨论递归的时候都喜欢用斐波那契数来作为例 子，我们也不要免俗。我们将斐波那契数的定义如下图来说明：


实现的代码：
def  Fib(n):
if (n&#60;1):
return 0
elif (n&#60;3):
return 1
else:
return Fib(n-1)+Fib(n-2)
我们可以看出，这个算法几乎就是对上图定义的直译，我们假设 n=6，那么得到的计算过程就是，要计算Fib(6)就得计算Fib(5)和Fib(4)，以此类推，如下图：

我们可以看到过程如同一棵倒置的树，这 种方式被称之为树形递归，也被称之为线性递归。这种递归的方式非常的直白，很好理解其计算过程，一般很多人写递归都会下意识的采用这种方式。但是缺点也是 很明显的，从其计算过程可以看出，经过了很多冗余的计算，并且消耗了大量的调用堆栈，这个消耗是指数级增长的，经常有人说调用堆栈很容易在很短的递归过程 就耗光了，多半就是采用了线性递归造成的。线性递归的过程可用下图描述，可以清晰的看到展开收拢的过程：

除了这种递归方式还有 另外一种实现递归的方式，同样是上面的斐波那契数作为例子，这次我们不按照斐波那契的定义入手，我们从正常产生数列的过程入手来实现，0，1，的情况很简 单可以直接返回，之后的计算过程就是累加，我们在递归的过程中要保持状态，这个状态要保持三个数，也就是上两个数和迭代的步数，所以我们定义的方法为
def  Fib(n,b1=1,b2=1,c=3):
if n&#60;3:
return 1
else:
if n==c:
return b1+b2
else:
return Fib(n,b1=b2,b2=b1+b2,c=c+1)
这 种方法我们在每一次递归的过程中保持了上一次计算的状态，所以称之为“线性迭代过程”，也就是俗称的尾递归。由于每一步计算都保持了状态所以消除了冗余计 算，所以这种方式的效率明显高于前一种，其计算过程如下
fib(6)
fib  0,0,1
fib   0,1,2
fib  1,2,3
fib  2,3,4
fib  3,5,5
fib   5,8,6
这两种递归方式之间是可以转换的，凡是可以通过固定数量状态来描述中间计算过程的递归过程都可以通过线性迭代来表示。
我们可以发现，其实尾递归的过程和循环基本上是等价的，我们可以将尾递归的过程很方便到用循环来代替，所以很多的语言对尾递归提供了编译级别的优化，也就是 将尾递归在编译期转化成循环的代码。不过对于没有提供尾递归优化的语言来说也是很有意义的，比如python的默认调用堆栈长度是1000，如果用线性递 归很快就会消耗光，但是尾递归就不会，比如尾递归的Fib函数，用Fib(1001)调用没问题的而且跑得飞快，Fib(1002)的时候才堆栈溢出。但 是如果是线性递归的方式计算n=30的时候就能明显感觉到速度变慢，40以上基本就挂了。
这里我无意对比两种方式的优劣，也许线性递归性能 有差距但是它的可读性非常的强，几乎就等同于公式的直接描述，所以可以根据计算规模来合理选用。

© 我想网 Akon 所有 , 2010. &#124;
永久链接 &#124;
没有评论 &#124;
提交到
Google Reader
鲜果
抓虾


	标签：Algorithm, Algorithm

	您可能会感兴趣的其他文章
	
	递归－三角数字 
	用PHP数组对百万数据进行排重 [...]]]></description>
			<content:encoded><![CDATA[<p>近日翻看SICP，看到递归的部分，深有感触，遂记下所想所悟，如果有批评直言，望不吝赐教。</p>
<p>递归是实现程序计算过程中的描述过程 的基本模式之一，在讨论递归的问题前我们必须十分小心，因为递归包含两个方面的内容，一个是递归的计算过程，一个是递归过程，后者是语法上的事实而前者是 概念上的计算过程，事实上在程序上我们也许是使用循环来实现的。</p>
<p>一般在讨论递归的时候都喜欢用斐波那契数来作为例 子，我们也不要免俗。我们将斐波那契数的定义如下图来说明：<br />
<span id="more-4661"></span><br />
<img src="http://images.uheed.com/iwanna/2010/07/21/digui-3.png" border="0" alt="浅谈递归过程以及递归的优化 | iwanna.cn 我想网" width="409" height="105" /></p>
<p>实现的代码：</p>
<p>def  Fib(n):</p>
<p>if (n&lt;1):</p>
<p>return 0</p>
<p>elif (n&lt;3):</p>
<p>return 1</p>
<p>else:</p>
<p>return Fib(n-1)+Fib(n-2)</p>
<p>我们可以看出，这个算法几乎就是对上图定义的直译，我们假设 n=6，那么得到的计算过程就是，要计算Fib(6)就得计算Fib(5)和Fib(4)，以此类推，如下图：</p>
<p><img src="http://images.uheed.com/iwanna/2010/07/21/digui-2.png" border="0" alt="浅谈递归过程以及递归的优化 | iwanna.cn 我想网" width="608" height="420" /></p>
<p>我们可以看到过程如同一棵倒置的树，这 种方式被称之为树形递归，也被称之为线性递归。这种递归的方式非常的直白，很好理解其计算过程，一般很多人写递归都会下意识的采用这种方式。但是缺点也是 很明显的，从其计算过程可以看出，经过了很多冗余的计算，并且消耗了大量的调用堆栈，这个消耗是指数级增长的，经常有人说调用堆栈很容易在很短的递归过程 就耗光了，多半就是采用了线性递归造成的。线性递归的过程可用下图描述，可以清晰的看到展开收拢的过程：</p>
<p><img src="http://images.uheed.com/iwanna/2010/07/21/digui-1.png" border="0" alt="浅谈递归过程以及递归的优化 | iwanna.cn 我想网" width="461" height="298" /></p>
<p>除了这种递归方式还有 另外一种实现递归的方式，同样是上面的斐波那契数作为例子，这次我们不按照斐波那契的定义入手，我们从正常产生数列的过程入手来实现，0，1，的情况很简 单可以直接返回，之后的计算过程就是累加，我们在递归的过程中要保持状态，这个状态要保持三个数，也就是上两个数和迭代的步数，所以我们定义的方法为</p>
<p>def  Fib(n,b1=1,b2=1,c=3):</p>
<p>if n&lt;3:</p>
<p>return 1</p>
<p>else:</p>
<p>if n==c:</p>
<p>return b1+b2</p>
<p>else:</p>
<p>return Fib(n,b1=b2,b2=b1+b2,c=c+1)</p>
<p>这 种方法我们在每一次递归的过程中保持了上一次计算的状态，所以称之为“线性迭代过程”，也就是俗称的尾递归。由于每一步计算都保持了状态所以消除了冗余计 算，所以这种方式的效率明显高于前一种，其计算过程如下</p>
<p>fib(6)</p>
<p>fib  0,0,1</p>
<p>fib   0,1,2</p>
<p>fib  1,2,3</p>
<p>fib  2,3,4</p>
<p>fib  3,5,5</p>
<p>fib   5,8,6</p>
<p>这两种递归方式之间是可以转换的，凡是可以通过固定数量状态来描述中间计算过程的递归过程都可以通过线性迭代来表示。</p>
<p>我们可以发现，其实尾递归的过程和循环基本上是等价的，我们可以将尾递归的过程很方便到用循环来代替，所以很多的语言对尾递归提供了编译级别的优化，也就是 将尾递归在编译期转化成循环的代码。不过对于没有提供尾递归优化的语言来说也是很有意义的，比如<a href="http://www.iwanna.cn/tags/python/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with Python">python</a>的默认调用堆栈长度是1000，如果用线性递 归很快就会消耗光，但是尾递归就不会，比如尾递归的Fib函数，用Fib(1001)调用没问题的而且跑得飞快，Fib(1002)的时候才堆栈溢出。但 是如果是线性递归的方式计算n=30的时候就能明显感觉到速度变慢，40以上基本就挂了。</p>
<p>这里我无意对比两种方式的优劣，也许线性递归性能 有差距但是它的可读性非常的强，几乎就等同于公式的直接描述，所以可以根据计算规模来合理选用。</p>
<hr />
<p>© <a href="http://www.iwanna.cn">我想网</a> Akon 所有 , 2010. |
<a href="http://www.iwanna.cn/archives/2010/07/21/4661/">永久链接</a> |
<a href="http://www.iwanna.cn/archives/2010/07/21/4661/#comments">没有评论</a> |
提交到
<a rel="nofollow" target="_blank" href="http://www.google.com/reader/view/feed/http://www.iwanna.cn/archives/2010/07/21/4661/">Google Reader</a>
<a rel="nofollow" target="_blank" href="http://www.xianguo.com/subscribe.php?url=http://www.iwanna.cn/archives/2010/07/21/4661/">鲜果</a>
<a rel="nofollow" target="_blank" href="http://www.zhuaxia.com/add_channel.php?url=http://www.iwanna.cn/archives/2010/07/21/4661/">抓虾</a>
<hr />
</p>
	标签：<a href="http://www.iwanna.cn/topics/develope/algorithm/" title="Algorithm" rel="tag nofollow">Algorithm</a>, <a href="http://www.iwanna.cn/tags/algorithm/" title="Algorithm" rel="tag nofollow">Algorithm</a><br />

	<h2 class="related_post">您可能会感兴趣的其他文章</h2>
	<ul class="st-related-posts">
	<li><a href="http://www.iwanna.cn/archives/2009/03/31/71/" title="递归－三角数字 (2009年03月31日)">递归－三角数字</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/06/08/3769/" title="用PHP数组对百万数据进行排重 (2010年06月8日)">用PHP数组对百万数据进行排重</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/07/23/4680/" title="检查素数的正则表达式 (2010年07月23日)">检查素数的正则表达式</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/03/31/69/" title="排序－选择 (2009年03月31日)">排序－选择</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/03/31/75/" title="排序－插入 (2009年03月31日)">排序－插入</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/03/31/73/" title="排序－冒泡 (2009年03月31日)">排序－冒泡</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/05/03/929/" title="排序算法汇总 (2009年05月3日)">排序算法汇总</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/04/09/323/" title="全文检索中近义词、关联词的解决方案 (2009年04月9日)">全文检索中近义词、关联词的解决方案</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/07/23/4695/" title="一些重要的算法 (2010年07月23日)">一些重要的算法</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/07/13/4513/" title="一个显示排序过程的Python脚本 (2010年07月13日)">一个显示排序过程的Python脚本</a> </li>
</ul>


<p><small>Feed enhanced by <a href='http://planetozh.com/blog/my-projects/wordpress-plugin-better-feed-rss/'>Better Feed</a> from  <a href='http://planetozh.com/blog/'>Ozh</a></small></p>
]]></content:encoded>
			<wfw:commentRss>http://www.iwanna.cn/archives/2010/07/21/4661/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>一个显示排序过程的Python脚本</title>
		<link>http://www.iwanna.cn/archives/2010/07/13/4513/</link>
		<comments>http://www.iwanna.cn/archives/2010/07/13/4513/#comments</comments>
		<pubDate>Tue, 13 Jul 2010 13:26:20 +0000</pubDate>
		<dc:creator>seasun</dc:creator>
				<category><![CDATA[Algorithm]]></category>
		<category><![CDATA[Python]]></category>

		<guid isPermaLink="false">http://www.iwanna.cn/?p=4513</guid>
		<description><![CDATA[之前向大家介绍过《一个排序算法比较的网站》，那个网站用动画演示了各种排序算法，并分析了各种排序算法。这里，要向大家推荐一个 Python脚本，其可以把排序的过程给显示出来。
下图是“冒泡排序”的一个示例，其中：

折线表示了各个元素的位置变化。
折线的深浅表示了元素的大小。越深则越大。



同样，还有其它一些排序算法的图片：
堆排序（Heap Sort）

选择排序（Selection）

快速排序（Quick）

Shell排序

插入排序（Insertion）

你可以使用如下的Python代码来制作这些图片：（需要 Cairo图片库支持）
Python 排序脚本
这个脚本参数如下：

-a 表示使用什么样的算法，取值为"quick", "heap", "selection",  "insertion", "bubble", "shell"。
-n 表示要排序的数据个数。
-f 表示输入文件。
-p 表示文件前缀。
-d 表示输出顺序。
-x 图片宽度。
-y 图片高度。
-l 所有线的宽度。
-b 边界宽度。

使用示例如下：
./visualise.py -l 6 -x 700 -y  300 -n 15 

© 我想网 Akon 所有 , 2010. &#124;
永久链接 &#124;
没有评论 &#124;
提交到
Google Reader
鲜果
抓虾


	标签：Algorithm, Algorithm, Python, Python

	您可能会感兴趣的其他文章
	
	递归－三角数字 
	用PHP数组对百万数据进行排重 
	浅谈递归过程以及递归的优化 
	检查素数的正则表达式 
	排序－选择 
	排序－插入 
	排序－冒泡 
	排序算法汇总 
	国外PHP开发者放弃PHP而改用Python 
	全文检索中近义词、关联词的解决方案 



Feed enhanced by Better [...]]]></description>
			<content:encoded><![CDATA[<p>之前向大家介绍过《<a rel="bookmark" href="http://www.iwanna.cn/archives/2010/07/13/4511/" title="一个排序算法比较的网站">一个排序算法比较的网站</a>》，那个网站用动画演示了各种排序算法，并分析了各种排序算法。这里，要向大家推荐一个 <a href="http://www.iwanna.cn/tags/python/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with Python">Python</a>脚本，其可以把排序的过程给显示出来。</p>
<p>下图是“<strong>冒泡排序</strong>”的一个示例，其中：</p>
<ol>
<li>折线表示了各个元素的位置变化。</li>
<li>折线的深浅表示了元素的大小。越深则越大。</li>
</ol>
<p><span id="more-4513"></span><br />
<a href="http://images.uheed.com/iwanna/2010/07/13/pythod-sort/bubble.png"><img title="bubble" src="http://images.uheed.com/iwanna/2010/07/13/pythod-sort/bubble.png" alt="bubble" width="600" height="225" /></a></p>
<p>同样，还有其它一些排序算法的图片：</p>
<p><strong>堆排序（Heap Sort）</strong></p>
<p><a href="http://images.uheed.com/iwanna/2010/07/13/pythod-sort/heap.png"><img title="heap" src="http://images.uheed.com/iwanna/2010/07/13/pythod-sort/heap.png" alt="heap" width="600" height="225" /></a></p>
<p><strong>选择排序（Selection）</strong></p>
<p><a href="http://images.uheed.com/iwanna/2010/07/13/pythod-sort/selection.png"><img title="selection" src="http://images.uheed.com/iwanna/2010/07/13/pythod-sort/selection.png" alt="selection" width="600" height="225" /></a></p>
<p><strong>快速排序（Quick）</strong></p>
<p><a href="http://images.uheed.com/iwanna/2010/07/13/pythod-sort/quick.png"><img title="quick" src="http://images.uheed.com/iwanna/2010/07/13/pythod-sort/quick.png" alt="quick" width="600" height="225" /></a></p>
<p><strong>Shell排序</strong></p>
<p><a href="http://images.uheed.com/iwanna/2010/07/13/pythod-sort/shell.png"><img title="shell" src="http://images.uheed.com/iwanna/2010/07/13/pythod-sort/shell.png" alt="shell" width="600" height="225" /></a></p>
<p><strong>插入排序（Insertion）</strong></p>
<p><a href="http://images.uheed.com/iwanna/2010/07/13/pythod-sort/listinsertion.png"><img title="listinsertion" src="http://images.uheed.com/iwanna/2010/07/13/pythod-sort/listinsertion.png" alt="listinsertion" width="600" height="225" /></a></p>
<p>你可以使用如下的<a href="http://www.iwanna.cn/tags/python/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with Python">Python</a>代码来制作这些图片：（需要 <a onclick="pageTracker._trackPageview('/outgoing/cairographics.org/?referer=http%3A%2F%2Fcoolshell.cn%2F%3Fp%3D2583');" href="http://cairographics.org/">Cairo</a>图片库支持）</p>
<p><a href="http://images.uheed.com/iwanna/2010/07/13/pythod-sort/visualise.py"><strong>Python 排序脚本</strong></a></p>
<p>这个脚本<code>参数如下：</code></p>
<ul>
<li><code>-a 表示使用什么样的算法，取值为"quick", "heap", "selection",  "insertion", "bubble", "shell"。</code></li>
<li><code>-n 表示要排序的数据个数。</code></li>
<li><code>-f 表示输入文件。</code></li>
<li><code>-p 表示文件前缀。</code></li>
<li><code>-d 表示输出顺序。</code></li>
<li><code>-x 图片宽度。</code></li>
<li><code>-y 图片高度。</code></li>
<li><code>-l 所有线的宽度。</code></li>
<li><code>-b 边界宽度。</code></li>
</ul>
<p><code>使用示例如下：</code></p>
<p><code>./visualise.py -l 6 -x 700 -y  300 -n 15 </code></p>
<hr />
<p>© <a href="http://www.iwanna.cn">我想网</a> Akon 所有 , 2010. |
<a href="http://www.iwanna.cn/archives/2010/07/13/4513/">永久链接</a> |
<a href="http://www.iwanna.cn/archives/2010/07/13/4513/#comments">没有评论</a> |
提交到
<a rel="nofollow" target="_blank" href="http://www.google.com/reader/view/feed/http://www.iwanna.cn/archives/2010/07/13/4513/">Google Reader</a>
<a rel="nofollow" target="_blank" href="http://www.xianguo.com/subscribe.php?url=http://www.iwanna.cn/archives/2010/07/13/4513/">鲜果</a>
<a rel="nofollow" target="_blank" href="http://www.zhuaxia.com/add_channel.php?url=http://www.iwanna.cn/archives/2010/07/13/4513/">抓虾</a>
<hr />
</p>
	标签：<a href="http://www.iwanna.cn/topics/develope/algorithm/" title="Algorithm" rel="tag nofollow">Algorithm</a>, <a href="http://www.iwanna.cn/tags/algorithm/" title="Algorithm" rel="tag nofollow">Algorithm</a>, <a href="http://www.iwanna.cn/topics/develope/python/" title="Python" rel="tag nofollow">Python</a>, <a href="http://www.iwanna.cn/tags/python/" title="Python" rel="tag nofollow">Python</a><br />

	<h2 class="related_post">您可能会感兴趣的其他文章</h2>
	<ul class="st-related-posts">
	<li><a href="http://www.iwanna.cn/archives/2009/03/31/71/" title="递归－三角数字 (2009年03月31日)">递归－三角数字</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/06/08/3769/" title="用PHP数组对百万数据进行排重 (2010年06月8日)">用PHP数组对百万数据进行排重</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/07/21/4661/" title="浅谈递归过程以及递归的优化 (2010年07月21日)">浅谈递归过程以及递归的优化</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/07/23/4680/" title="检查素数的正则表达式 (2010年07月23日)">检查素数的正则表达式</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/03/31/69/" title="排序－选择 (2009年03月31日)">排序－选择</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/03/31/75/" title="排序－插入 (2009年03月31日)">排序－插入</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/03/31/73/" title="排序－冒泡 (2009年03月31日)">排序－冒泡</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/05/03/929/" title="排序算法汇总 (2009年05月3日)">排序算法汇总</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/06/11/3900/" title="国外PHP开发者放弃PHP而改用Python (2010年06月11日)">国外PHP开发者放弃PHP而改用Python</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/04/09/323/" title="全文检索中近义词、关联词的解决方案 (2009年04月9日)">全文检索中近义词、关联词的解决方案</a> </li>
</ul>


<p><small>Feed enhanced by <a href='http://planetozh.com/blog/my-projects/wordpress-plugin-better-feed-rss/'>Better Feed</a> from  <a href='http://planetozh.com/blog/'>Ozh</a></small></p>
]]></content:encoded>
			<wfw:commentRss>http://www.iwanna.cn/archives/2010/07/13/4513/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>一个排序算法比较的网站</title>
		<link>http://www.iwanna.cn/archives/2010/07/13/4511/</link>
		<comments>http://www.iwanna.cn/archives/2010/07/13/4511/#comments</comments>
		<pubDate>Tue, 13 Jul 2010 13:21:08 +0000</pubDate>
		<dc:creator>seasun</dc:creator>
				<category><![CDATA[Algorithm]]></category>

		<guid isPermaLink="false">http://www.iwanna.cn/?p=4511</guid>
		<description><![CDATA[下面这个网站是一个非常丰富的排序算法的网站。
Sorting Algorithm Animations
http://www.sorting-algorithms.com/
这是一个非常不错的排序算法的网站，当你打开这个网站的时候，请不要因为看到很多个图片的大红叉而鄙视它。你先点击网页上方的 Problem Size，选择一个尺寸，20，30，40还是50，都行，于是你就可以看到下面整个大表中有图片显示出来了。如下所示：


其中，

列。是代表每一个排序算法，有“插入”“选择”“冒泡”“Shell”，“合并Merge”，“堆排 序”，“快速排序”，“快速3排序”。单击每个一算法的链接，你可以看到这个算法的详细解释，其中包括，算法的伪代码，算法的复杂度，相关的讨论，重点， 以及该算法的相关参考文档。
行。是不同的数据样本，第一个是“随机样本”，第二个是“几乎排好序的样本”，第三个是 “最差的样本（反序）”，第四个是“有一些相同项的样本”。这些样本在不同的算法上都会有不同的表现。
单元格。每个单元格都是一个图片。简单的用鼠标单击一下每个图片，可以动画地演示算法整个 过程。其中两个小红箭头表示了正在需要“交换顺序的数据”。

这个网站，还是做得很8错的。希望大家喜欢。

© 我想网 Akon 所有 , 2010. &#124;
永久链接 &#124;
没有评论 &#124;
提交到
Google Reader
鲜果
抓虾


	标签：Algorithm, Algorithm

	您可能会感兴趣的其他文章
	
	递归－三角数字 
	用PHP数组对百万数据进行排重 
	浅谈递归过程以及递归的优化 
	检查素数的正则表达式 
	排序－选择 
	排序－插入 
	排序－冒泡 
	排序算法汇总 
	全文检索中近义词、关联词的解决方案 
	一些重要的算法 



Feed enhanced by Better Feed from  Ozh
]]></description>
			<content:encoded><![CDATA[<p>下面这个网站是一个非常丰富的排序算法的网站。</p>
<h4>Sorting <a href="http://www.iwanna.cn/tags/algorithm/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with Algorithm">Algorithm</a> Animations<br />
<a href="http://www.sorting-algorithms.com/">http://www.sorting-algorithms.com/</a></h4>
<p>这是一个非常不错的排序算法的网站，当你打开这个网站的时候，请不要因为看到很多个图片的大红叉而鄙视它。你先点击网页上方的 Problem Size，选择一个尺寸，20，30，40还是50，都行，于是你就可以看到下面整个大表中有图片显示出来了。如下所示：</p>
<p><a href="http://images.uheed.com/iwanna/2010/07/13/sort.jpg" title="一个排序算法比较的网站"><img title="sort" src="http://images.uheed.com/iwanna/2010/07/13/sort-300x160.jpg" alt="一个排序算法比较的网站" width="300" height="160" /></a><br />
<span id="more-4511"></span><br />
其中，</p>
<ul>
<li><strong>列。</strong>是代表每一个排序算法，有“插入”“选择”“冒泡”“Shell”，“合并Merge”，“堆排 序”，“快速排序”，“快速3排序”。单击每个一算法的链接，你可以看到这个算法的详细解释，其中包括，算法的伪代码，算法的复杂度，相关的讨论，重点， 以及该算法的相关参考文档。</li>
<li><strong>行。</strong>是不同的数据样本，第一个是“随机样本”，第二个是“几乎排好序的样本”，第三个是 “最差的样本（反序）”，第四个是“有一些相同项的样本”。这些样本在不同的算法上都会有不同的表现。</li>
<li><strong>单元格</strong>。每个单元格都是一个图片。简单的用鼠标单击一下每个图片，可以动画地演示算法整个 过程。其中两个小红箭头表示了正在需要“交换顺序的数据”。</li>
</ul>
<p>这个网站，还是做得很8错的。希望大家喜欢。</p>
<hr />
<p>© <a href="http://www.iwanna.cn">我想网</a> Akon 所有 , 2010. |
<a href="http://www.iwanna.cn/archives/2010/07/13/4511/">永久链接</a> |
<a href="http://www.iwanna.cn/archives/2010/07/13/4511/#comments">没有评论</a> |
提交到
<a rel="nofollow" target="_blank" href="http://www.google.com/reader/view/feed/http://www.iwanna.cn/archives/2010/07/13/4511/">Google Reader</a>
<a rel="nofollow" target="_blank" href="http://www.xianguo.com/subscribe.php?url=http://www.iwanna.cn/archives/2010/07/13/4511/">鲜果</a>
<a rel="nofollow" target="_blank" href="http://www.zhuaxia.com/add_channel.php?url=http://www.iwanna.cn/archives/2010/07/13/4511/">抓虾</a>
<hr />
</p>
	标签：<a href="http://www.iwanna.cn/topics/develope/algorithm/" title="Algorithm" rel="tag nofollow">Algorithm</a>, <a href="http://www.iwanna.cn/tags/algorithm/" title="Algorithm" rel="tag nofollow">Algorithm</a><br />

	<h2 class="related_post">您可能会感兴趣的其他文章</h2>
	<ul class="st-related-posts">
	<li><a href="http://www.iwanna.cn/archives/2009/03/31/71/" title="递归－三角数字 (2009年03月31日)">递归－三角数字</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/06/08/3769/" title="用PHP数组对百万数据进行排重 (2010年06月8日)">用PHP数组对百万数据进行排重</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/07/21/4661/" title="浅谈递归过程以及递归的优化 (2010年07月21日)">浅谈递归过程以及递归的优化</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/07/23/4680/" title="检查素数的正则表达式 (2010年07月23日)">检查素数的正则表达式</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/03/31/69/" title="排序－选择 (2009年03月31日)">排序－选择</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/03/31/75/" title="排序－插入 (2009年03月31日)">排序－插入</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/03/31/73/" title="排序－冒泡 (2009年03月31日)">排序－冒泡</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/05/03/929/" title="排序算法汇总 (2009年05月3日)">排序算法汇总</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/04/09/323/" title="全文检索中近义词、关联词的解决方案 (2009年04月9日)">全文检索中近义词、关联词的解决方案</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/07/23/4695/" title="一些重要的算法 (2010年07月23日)">一些重要的算法</a> </li>
</ul>


<p><small>Feed enhanced by <a href='http://planetozh.com/blog/my-projects/wordpress-plugin-better-feed-rss/'>Better Feed</a> from  <a href='http://planetozh.com/blog/'>Ozh</a></small></p>
]]></content:encoded>
			<wfw:commentRss>http://www.iwanna.cn/archives/2010/07/13/4511/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>用PHP数组对百万数据进行排重</title>
		<link>http://www.iwanna.cn/archives/2010/06/08/3769/</link>
		<comments>http://www.iwanna.cn/archives/2010/06/08/3769/#comments</comments>
		<pubDate>Tue, 08 Jun 2010 01:09:48 +0000</pubDate>
		<dc:creator>seasun</dc:creator>
				<category><![CDATA[Algorithm]]></category>
		<category><![CDATA[PHP]]></category>

		<guid isPermaLink="false">http://www.iwanna.cn/?p=3769</guid>
		<description><![CDATA[在平时的工作中，经常接到要对网站的会员进行站内信、手机短信、email进行群发信息的通知，用户列表一般由别的同事提供，当中难免会有重复，为了避免重复发送，所以我在进行发送信息前要对他们提供的用户列表进行排重，下面我以uid列表来讲讲我是如何利用php数组进行排重的。
假如得到一个uid列表，数量在百万行以上，格式如下：
10001000
10001001
10001002
......
10001000
......
10001111
其实利用php数组的特性，很好进行排重，我们先来看一下php数组的定义：PHP 中的数组实际上是一个有序映射。映射是一种把 values 关联到  keys  的类型。此类型在很多方面做了优化，因此可以把它当成真正的数组，或列表（向量），散列表（是映射的一种实现），字典，集合，栈，队列以及更多可能性。数组元素的值也可以是另一个数组。树形结构和多维数组也是允许的。

在php的数组中，键（keys）也称为索引，具有唯一性，我们正可以利用这一特性进行排重，示例代码如下：
&#60;?php
//定义一个数组，用于存放排重后的结果
$result = array();
//读取uid列表文件
$fp = fopen('test.txt', 'r');

while(!feof($fp))
{
    $uid = fgets($fp);
    $uid = trim($uid);
    $uid = trim($uid, "\r");
    $uid = trim($uid, "\n");

    if($uid == '')
    {
       [...]]]></description>
			<content:encoded><![CDATA[<p>在平时的工作中，经常接到要对网站的会员进行站内信、手机短信、email进行群发信息的通知，用户列表一般由别的同事提供，当中难免会有重复，为了避免重复发送，所以我在进行发送信息前要对他们提供的用户列表进行排重，下面我以uid列表来讲讲我是如何利用<a href="http://www.iwanna.cn/tags/php/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with PHP">php</a>数组进行排重的。</p>
<p>假如得到一个uid列表，数量在百万行以上，格式如下：</p>
<pre>10001000
10001001
10001002
......
10001000
......
10001111</pre>
<p>其实利用<a href="http://www.iwanna.cn/tags/php/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with PHP">php</a>数组的特性，很好进行排重，我们先来看一下<a href="http://www.iwanna.cn/tags/php/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with PHP">php</a>数组的定义：<a href="http://www.iwanna.cn/tags/php/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with PHP">PHP</a> 中的数组实际上是一个有序映射。映射是一种把 values 关联到  keys  的类型。此类型在很多方面做了优化，因此可以把它当成真正的数组，或列表（向量），散列表（是映射的一种实现），字典，集合，栈，队列以及更多可能性。数组元素的值也可以是另一个数组。树形结构和多维数组也是允许的。<br />
<span id="more-3769"></span><br />
在<a href="http://www.iwanna.cn/tags/php/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with PHP">php</a>的数组中，键（keys）也称为索引，具有唯一性，我们正可以利用这一特性进行排重，示例代码如下：</p>
<pre>&lt;?<a href="http://www.iwanna.cn/tags/php/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with PHP">php</a>
//定义一个数组，用于存放排重后的结果
$result = array();
//读取uid列表文件
$fp = fopen('test.txt', 'r');

while(!feof($fp))
{
    $uid = fgets($fp);
    $uid = trim($uid);
    $uid = trim($uid, "\r");
    $uid = trim($uid, "\n");

    if($uid == '')
    {
        continue;
    }
    //以uid为key去看该值是否存在
    if(empty($result[$uid]))
    {
        $result[$uid] = 1;
    }
}

fclose($fp);

//将结果保存到文件
$content = '';
foreach($result as $k =&gt; $v)
{
    $content .= $k."\n";
}
$fp = fopen('result.txt', 'w');
fwrite($fp, $content);
fclose($fp);
?&gt;</pre>
<p>20多行代码，就可以对百万以上的数据进行排重，效率也不错，非常实用。手机号、email，也可以采用这种方式进行排重。</p>
<p>还有，这可方法还可以用于两个文件进行排重的工作，如果你有两个uid列表文件，格式和上面的uid列表一样，示例程序如下：</p>
<pre>&lt;?<a href="http://www.iwanna.cn/tags/php/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with PHP">php</a>
//定义数组，用于存放排重后的结果
$result = array();
//读取第一个uid列表文件，放入$result_1
$fp = fopen('test_1.txt', 'r');

while(!feof($fp))
{
    $uid = fgets($fp);
    $uid = trim($uid);
    $uid = trim($uid, "\r");
    $uid = trim($uid, "\n");

    if($uid == '')
    {
        continue;
    }
    //以uid为key写入$result，如有重复就会覆盖
    $result[$uid] = 1;
}

fclose($fp);

//读取第二个uid列表文件，并进行排重操作
$fp = fopen('test_2.txt', 'r');
while(!feof($fp))
{
    $uid = fgets($fp);
    $uid = trim($uid);
    $uid = trim($uid, "\r");
    $uid = trim($uid, "\n");

    if($uid == '')
    {
        continue;
    }
    //以uid为key去看该值是否存在
    if(empty($result[$uid]))
    {
        $result[$uid] = 1;
    }
}
fclose($fp);

//$result里保存的就排重以后的结果，可以输出到文件，代码省略
?&gt;</pre>
<p>仔细想想，不难发现，利用数组的这一特性还可以解决我们工作中的更多问题。</p>
<hr />
<p>© <a href="http://www.iwanna.cn">我想网</a> Akon 所有 , 2010. |
<a href="http://www.iwanna.cn/archives/2010/06/08/3769/">永久链接</a> |
<a href="http://www.iwanna.cn/archives/2010/06/08/3769/#comments">没有评论</a> |
提交到
<a rel="nofollow" target="_blank" href="http://www.google.com/reader/view/feed/http://www.iwanna.cn/archives/2010/06/08/3769/">Google Reader</a>
<a rel="nofollow" target="_blank" href="http://www.xianguo.com/subscribe.php?url=http://www.iwanna.cn/archives/2010/06/08/3769/">鲜果</a>
<a rel="nofollow" target="_blank" href="http://www.zhuaxia.com/add_channel.php?url=http://www.iwanna.cn/archives/2010/06/08/3769/">抓虾</a>
<hr />
</p>
	标签：<a href="http://www.iwanna.cn/topics/develope/algorithm/" title="Algorithm" rel="tag nofollow">Algorithm</a>, <a href="http://www.iwanna.cn/tags/algorithm/" title="Algorithm" rel="tag nofollow">Algorithm</a>, <a href="http://www.iwanna.cn/topics/develope/php/" title="PHP" rel="tag nofollow">PHP</a>, <a href="http://www.iwanna.cn/tags/php/" title="PHP" rel="tag nofollow">PHP</a><br />

	<h2 class="related_post">您可能会感兴趣的其他文章</h2>
	<ul class="st-related-posts">
	<li><a href="http://www.iwanna.cn/archives/2009/03/31/71/" title="递归－三角数字 (2009年03月31日)">递归－三角数字</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/04/02/149/" title="设计模式之单例模式 (2009年04月2日)">设计模式之单例模式</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/07/31/2088/" title="论述PHP开发框架: What, When, Why and Which? (2009年07月31日)">论述PHP开发框架: What, When, Why and Which?</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/06/08/3767/" title="腾讯PHP程序员面试题目 (2010年06月8日)">腾讯PHP程序员面试题目</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/04/03/171/" title="简易Wordpress模板代码帮助手册中文版 (2009年04月3日)">简易Wordpress模板代码帮助手册中文版</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/07/05/1933/" title="用 PHP 读取和编写 XML DOM (2009年07月5日)">用 PHP 读取和编写 XML DOM</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/06/20/4102/" title="深入理解PHP之匿名函数 (2010年06月20日)">深入理解PHP之匿名函数</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/07/21/4661/" title="浅谈递归过程以及递归的优化 (2010年07月21日)">浅谈递归过程以及递归的优化</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/07/23/4680/" title="检查素数的正则表达式 (2010年07月23日)">检查素数的正则表达式</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/08/20/2171/" title="最快的 PHP 模板引擎 Blitz Templates (2009年08月20日)">最快的 PHP 模板引擎 Blitz Templates</a> </li>
</ul>


<p><small>Feed enhanced by <a href='http://planetozh.com/blog/my-projects/wordpress-plugin-better-feed-rss/'>Better Feed</a> from  <a href='http://planetozh.com/blog/'>Ozh</a></small></p>
]]></content:encoded>
			<wfw:commentRss>http://www.iwanna.cn/archives/2010/06/08/3769/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>SNS中好友动态功能的设计思路</title>
		<link>http://www.iwanna.cn/archives/2010/06/01/3570/</link>
		<comments>http://www.iwanna.cn/archives/2010/06/01/3570/#comments</comments>
		<pubDate>Tue, 01 Jun 2010 04:16:40 +0000</pubDate>
		<dc:creator>seasun</dc:creator>
				<category><![CDATA[Algorithm]]></category>
		<category><![CDATA[Technology]]></category>
		<category><![CDATA[程序开发]]></category>
		<category><![CDATA[SNS]]></category>

		<guid isPermaLink="false">http://www.iwanna.cn/?p=3570</guid>
		<description><![CDATA[现在大部分SNS网站都有一个功能，就是显示好友的活动状态，比如你的好友上传了一张照片、分享了一篇文章等等动作，都可以显示在你的页 面里，这样大大增强了社区的互动性，也成为现在SNS网站的主要特征，对于这样一个功能，从设计角度，还是值得思考的，并不简单，特别是用户越来越多，信 息海量增长的时候，我未必能提出十全十美的方案，但我们可以由简如繁梳理一下思路。
首先我们要定义用户的活动消息，也可以理解为一个事件，就是我们举的例子：用户上传照片、与别人结为好友、修改了个人资料等等，动作各有不同，但需 要在结构上通用，我们先设计一个
ID //消息ID
UserID //用户ID
MsgType //消息类型，比如加好友、上传照片等不同的类型
EventMsg //消息的内容，这里我们可以用Json的数据格式来描述出不同的活动内容
CreateTime //消息创建时间

这个结构也是个数据库的结构，当用户做个一个动作之后，就会创建这样一个消息，并保存在数据库中，当显示好友的活动信息时，就从这张表里查询自己好 友id的数据，并按时间显示，这个做法是一个最简单的实现，但会出现一些问题，当你与一个用户成为好友之后，该好友之前发生的动作会显示出来，而不是在成 为好友时点之后的动作，同样，切断好友关系之后也有类似的问题，如果从业务角度和用户体验上可以接受的话，也没什么，但由于信息是按时间排序，有时候会给 用户错乱的感觉，还有，这个信息不能删除，如果删除了所有好友就看不到这条信息了，但在Facebook里是则是可以删除好友的动作信息的，这个方法还有 一个问题是，所有信息都放在一张大表里，在信息爆炸增长，个人好友也很多的情况下，查询效率会非常低，产生严重的性能障碍，如果对这张表做水平切分，则在 实现上复杂了许多，性能也未必好很多，接下来我们再思考是否有更好的解决办法。
在SNS的理论里，个人好友的合理数量在150个左右（最近有文章说Facebook的人均好友数是120人），SNS网站应该是有好友数量的限制的，我们就按人均 150个好友来设想，是否可以在用户发生某些动作之后，针对他的所有好友都写入一条信息，所能解决的是，信息是在用户成为好友时点之后写入，用户可以删除 好友的活动信息，不影响其他用户的显示，在显示时查询效率要高很多，但是负面效应也十分明显，一个用户的动作有平均150个写入，对于数据库来说开销也非 常大，我们想想在这样的设计下，是否可以提高性能。
首先看数据库设计，我们要把信息表和信息与用户的对应表分开，我们上面定义的数据结构保留，我们定义它的表名为Event，我们再新建一张表 EventUser，结构如下
ID  //主键
EventID //Event表的ID
FriendUserID //好友的ID
CreateTime //消息创建时间
对FriendUserID做索引，当用户发生动作时，首先将动作信息写入Event表，之后查找用户的所有好友，将EventID、好友ID逐条 写入EventUser表，当要显示自己的好友活动信息是，查询EventUser中FriendUserID等于自己ID的信息，并和Event表做一 个Join查询就可以了。
进一步提升性能的方法，将Event里的信息缓存，比如用Memcached，EventID做为Key，内容做为Value，这样，查询 EventUser是就不用Join  Event表，而是从缓存里读取，由于要记录给每个好友的信息，所以EventUser会变得非常大，平均要比我们最初设计的数据容量大150倍，我们对 EventUser表做水平切分，根据用户ID做Hash算法，基本上能均匀的分配到所有的表中，至于EventUser水平切分的算法还有多种，根据实 际情况来定，总的来说就是把数据分摊掉，同时EventUser里的数据可以不永久保存，做定期删除，可以保持数据容量在一个合理的范围内。
对于用户动作之后的数据写入，可以采用异步的方法，在发生动作时，抛出一个消息，由另外一个线程在做写入操作，如果对每个动作平均150次的写入仍 存顾虑，我们可以针对每个用户开出一块内存空间，或是缓存，里面保存最后50条最新的好友动作，并在每条记录里做一个持久化标志，当有50条信息都标志是 “未持久化”时，做一次数据库的写入，然后把信息置为“已持久化”，这种非实时写入的方式，可以提高一定的数据库效率，显示时，先从内存中取出，再查数据 库。
还有一些问题，对不不同消息类型的处理方式不同，比如用户修改个人资料，并不是每次发生这样的动作都要做一次给朋友做一次“群发”的操作，如果遇到 这个人在短时间内做了多次修改个人资料的操作，就给朋友发出多个消息，会产生垃圾信息，让人觉得很怪异，所以对于这样的操作会有一定的时效性，比如在一天 之内的修改个人资料，就是一个消息，这时候的处理是更新，而不是插入。
以上是我对SNS中好友动态功能的设计思路，可能还有一些未想到的问题，还需要认真思考。

© 我想网 Akon 所有 , 2010. &#124;
永久链接 &#124;
没有评论 &#124;
提交到
Google Reader
鲜果
抓虾


	标签：Algorithm, SNS, Technology, 程序开发

	您可能会感兴趣的其他文章
	
	集大成者的两款Adobe AIR平台上的社交网络 
	让网站“社会化”的5点建议(SNS) 
	美刊总结SNS网络6大规则：要有一定程度的不透明 
	社区产品的三个关键点 
	社交网络时代的营销 
	社交网站的设计 
	社交媒体(SNS)对搜索引擎优化的6大好处 
	目前微博同步的最佳解决方案 
	深色调社交图标：免费且高质量的社交媒体图标集 [...]]]></description>
			<content:encoded><![CDATA[<p>现在大部分<a href="http://www.iwanna.cn/tags/sns/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with SNS">SNS</a>网站都有一个功能，就是显示好友的活动状态，比如你的好友上传了一张照片、分享了一篇文章等等动作，都可以显示在你的页 面里，这样大大增强了社区的互动性，也成为现在<a href="http://www.iwanna.cn/tags/sns/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with SNS">SNS</a>网站的主要特征，对于这样一个功能，从设计角度，还是值得思考的，并不简单，特别是用户越来越多，信 息海量增长的时候，我未必能提出十全十美的方案，但我们可以由简如繁梳理一下思路。</p>
<p>首先我们要定义用户的活动消息，也可以理解为一个事件，就是我们举的例子：用户上传照片、与别人结为好友、修改了个人资料等等，动作各有不同，但需 要在结构上通用，我们先设计一个</p>
<p>ID //消息ID<br />
UserID //用户ID<br />
MsgType //消息类型，比如加好友、上传照片等不同的类型<br />
EventMsg //消息的内容，这里我们可以用Json的数据格式来描述出不同的活动内容<br />
CreateTime //消息创建时间<br />
<span id="more-3570"></span><br />
这个结构也是个数据库的结构，当用户做个一个动作之后，就会创建这样一个消息，并保存在数据库中，当显示好友的活动信息时，就从这张表里查询自己好 友id的数据，并按时间显示，这个做法是一个最简单的实现，但会出现一些问题，当你与一个用户成为好友之后，该好友之前发生的动作会显示出来，而不是在成 为好友时点之后的动作，同样，切断好友关系之后也有类似的问题，如果从业务角度和用户体验上可以接受的话，也没什么，但由于信息是按时间排序，有时候会给 用户错乱的感觉，还有，这个信息不能删除，如果删除了所有好友就看不到这条信息了，但在Facebook里是则是可以删除好友的动作信息的，这个方法还有 一个问题是，所有信息都放在一张大表里，在信息爆炸增长，个人好友也很多的情况下，查询效率会非常低，产生严重的性能障碍，如果对这张表做水平切分，则在 实现上复杂了许多，性能也未必好很多，接下来我们再思考是否有更好的解决办法。</p>
<p>在<a href="http://www.iwanna.cn/tags/sns/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with SNS">SNS</a>的理论里，个人好友的合理数量在150个左右（<a href="http://tech.sina.com.cn/i/2009-03-02/07232868882.shtml" target="_blank">最近有文章说Facebook的人均好友数是120人</a>），<a href="http://www.iwanna.cn/tags/sns/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with SNS">SNS</a>网站应该是有好友数量的限制的，我们就按人均 150个好友来设想，是否可以在用户发生某些动作之后，针对他的所有好友都写入一条信息，所能解决的是，信息是在用户成为好友时点之后写入，用户可以删除 好友的活动信息，不影响其他用户的显示，在显示时查询效率要高很多，但是负面效应也十分明显，一个用户的动作有平均150个写入，对于数据库来说开销也非 常大，我们想想在这样的设计下，是否可以提高性能。</p>
<p>首先看数据库设计，我们要把信息表和信息与用户的对应表分开，我们上面定义的数据结构保留，我们定义它的表名为Event，我们再新建一张表 EventUser，结构如下</p>
<p>ID  //主键<br />
EventID //Event表的ID<br />
FriendUserID //好友的ID<br />
CreateTime //消息创建时间</p>
<p>对FriendUserID做索引，当用户发生动作时，首先将动作信息写入Event表，之后查找用户的所有好友，将EventID、好友ID逐条 写入EventUser表，当要显示自己的好友活动信息是，查询EventUser中FriendUserID等于自己ID的信息，并和Event表做一 个Join查询就可以了。</p>
<p>进一步提升性能的方法，将Event里的信息缓存，比如用Memcached，EventID做为Key，内容做为Value，这样，查询 EventUser是就不用Join  Event表，而是从缓存里读取，由于要记录给每个好友的信息，所以EventUser会变得非常大，平均要比我们最初设计的数据容量大150倍，我们对 EventUser表做水平切分，根据用户ID做Hash算法，基本上能均匀的分配到所有的表中，至于EventUser水平切分的算法还有多种，根据实 际情况来定，总的来说就是把数据分摊掉，同时EventUser里的数据可以不永久保存，做定期删除，可以保持数据容量在一个合理的范围内。</p>
<p>对于用户动作之后的数据写入，可以采用异步的方法，在发生动作时，抛出一个消息，由另外一个线程在做写入操作，如果对每个动作平均150次的写入仍 存顾虑，我们可以针对每个用户开出一块内存空间，或是缓存，里面保存最后50条最新的好友动作，并在每条记录里做一个持久化标志，当有50条信息都标志是 “未持久化”时，做一次数据库的写入，然后把信息置为“已持久化”，这种非实时写入的方式，可以提高一定的数据库效率，显示时，先从内存中取出，再查数据 库。</p>
<p>还有一些问题，对不不同消息类型的处理方式不同，比如用户修改个人资料，并不是每次发生这样的动作都要做一次给朋友做一次“群发”的操作，如果遇到 这个人在短时间内做了多次修改个人资料的操作，就给朋友发出多个消息，会产生垃圾信息，让人觉得很怪异，所以对于这样的操作会有一定的时效性，比如在一天 之内的修改个人资料，就是一个消息，这时候的处理是更新，而不是插入。</p>
<p>以上是我对<a href="http://www.iwanna.cn/tags/sns/" class="st_tag internal_tag" rel="tag nofollow" title="Posts tagged with SNS">SNS</a>中好友动态功能的设计思路，可能还有一些未想到的问题，还需要认真思考。</p>
<hr />
<p>© <a href="http://www.iwanna.cn">我想网</a> Akon 所有 , 2010. |
<a href="http://www.iwanna.cn/archives/2010/06/01/3570/">永久链接</a> |
<a href="http://www.iwanna.cn/archives/2010/06/01/3570/#comments">没有评论</a> |
提交到
<a rel="nofollow" target="_blank" href="http://www.google.com/reader/view/feed/http://www.iwanna.cn/archives/2010/06/01/3570/">Google Reader</a>
<a rel="nofollow" target="_blank" href="http://www.xianguo.com/subscribe.php?url=http://www.iwanna.cn/archives/2010/06/01/3570/">鲜果</a>
<a rel="nofollow" target="_blank" href="http://www.zhuaxia.com/add_channel.php?url=http://www.iwanna.cn/archives/2010/06/01/3570/">抓虾</a>
<hr />
</p>
	标签：<a href="http://www.iwanna.cn/topics/develope/algorithm/" title="Algorithm" rel="tag nofollow">Algorithm</a>, <a href="http://www.iwanna.cn/tags/sns/" title="SNS" rel="tag nofollow">SNS</a>, <a href="http://www.iwanna.cn/topics/news/technology_news/" title="Technology" rel="tag nofollow">Technology</a>, <a href="http://www.iwanna.cn/topics/develope/" title="程序开发" rel="tag nofollow">程序开发</a><br />

	<h2 class="related_post">您可能会感兴趣的其他文章</h2>
	<ul class="st-related-posts">
	<li><a href="http://www.iwanna.cn/archives/2009/04/20/723/" title="集大成者的两款Adobe AIR平台上的社交网络 (2009年04月20日)">集大成者的两款Adobe AIR平台上的社交网络</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/01/07/2448/" title="让网站“社会化”的5点建议(SNS) (2010年01月7日)">让网站“社会化”的5点建议(SNS)</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/10/14/2303/" title="美刊总结SNS网络6大规则：要有一定程度的不透明 (2009年10月14日)">美刊总结SNS网络6大规则：要有一定程度的不透明</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/06/01/3604/" title="社区产品的三个关键点 (2010年06月1日)">社区产品的三个关键点</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/07/09/4441/" title="社交网络时代的营销 (2010年07月9日)">社交网络时代的营销</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/06/11/3884/" title="社交网站的设计 (2010年06月11日)">社交网站的设计</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/05/06/2952/" title="社交媒体(SNS)对搜索引擎优化的6大好处 (2010年05月6日)">社交媒体(SNS)对搜索引擎优化的6大好处</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/06/06/3737/" title="目前微博同步的最佳解决方案 (2010年06月6日)">目前微博同步的最佳解决方案</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/05/22/3294/" title="深色调社交图标：免费且高质量的社交媒体图标集 (2010年05月22日)">深色调社交图标：免费且高质量的社交媒体图标集</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/11/02/2357/" title="机会或陷阱,国内SNS网站全面总结 (2009年11月2日)">机会或陷阱,国内SNS网站全面总结</a> </li>
</ul>


<p><small>Feed enhanced by <a href='http://planetozh.com/blog/my-projects/wordpress-plugin-better-feed-rss/'>Better Feed</a> from  <a href='http://planetozh.com/blog/'>Ozh</a></small></p>
]]></content:encoded>
			<wfw:commentRss>http://www.iwanna.cn/archives/2010/06/01/3570/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>排序算法汇总</title>
		<link>http://www.iwanna.cn/archives/2009/05/03/929/</link>
		<comments>http://www.iwanna.cn/archives/2009/05/03/929/#comments</comments>
		<pubDate>Sun, 03 May 2009 08:35:54 +0000</pubDate>
		<dc:creator>seasun</dc:creator>
				<category><![CDATA[Algorithm]]></category>

		<guid isPermaLink="false">http://www.iwanna.cn/?p=929</guid>
		<description><![CDATA[一  排序的基本概念
所谓排序,就是要整理文件中的记录,使之按关键字递增(或递减)次序排列起来.  其确切定义如下:
输入: n个记录R1,R2,…,Rn,其相应的关键字分别为K1,K2,…,Kn.
输出: Ril,Ri2,…,Rin,使得Ki1 ≤ Ki2 ≤ … ≤ Kin.(或Ki1 ≥  Ki2 ≥ … ≥ Kin.)

二  排序的分类
1. 按是否涉及数据的内、外存交换分为
内部排序: 内部排序(简称内排序),是带排序纪录存放在计算机内存中进行的排序过程.  细分又可为插入排序、选择排序、交换排序、归并排序和基数排序.
外部排序:  外部排序(简称外排序),是带排序纪录的数量很大,以至于内存一次不能容纳全部纪录,在排序过程中,只有部分数被调入内存,并借助内存调整数在外存中的存放顺序的排序方法.
2. 按策略划分内部排序方法
可以分为五类: 插入排序、选择排序、交换排序、归并排序和基数排序.
三  排序算法的基本操作
1. 比较两个关键字的大小
2. 改变指向记录的指针或移动记录本身
注意: 第2种基本操作的实现依赖于待排序记录的存储方式.
四  排序算法的性能评价
1. 评价排序算法好坏的标准
(1)执行时间和所需的辅助空间
(2)算法本身的复杂程度
2. 排序算法的空间复杂度
若排序算法所需的辅助空间并不依赖于问题的规模n,即辅助空间是O(1),则称之为就地排序(In-Place  Sort). 非就地排序一般要求的辅助空间为O(n).
3. 排序算法的时间开销
大多数排序算法的时间开销主要是关键字之间的比较和记录的移动.  有的排序算法其执行时间不仅依赖于问题的规模,还取决于输入实例中数据的状态.
1  插入排序
1.1  直接插入排序
定义: 直接插入排序(Straight Insertion Sort)是一种最简单的排序方法.  它的基本操作是将一个记录插入到一个长度为m(假设)的有序表中,使之仍保持有序,从而得到一个新的长度为m＋1的有序表.
算法思路: 设有一组关键字{K1,K2,…,Kn},排序开始就认为K1是一个有序序列,让K2 [...]]]></description>
			<content:encoded><![CDATA[<p><strong><span>一  排序的基本概念</span></strong></p>
<div>所谓排序,就是要整理文件中的记录,使之按关键字递增(或递减)次序排列起来.  其确切定义如下:</div>
<div>输入: n个记录R1,R2,…,Rn,其相应的关键字分别为K1,K2,…,Kn.</div>
<div>输出: Ril,Ri2,…,Rin,使得Ki1 ≤ Ki2 ≤ … ≤ Kin.(或Ki1 ≥  Ki2 ≥ … ≥ Kin.)</div>
<p><span id="more-929"></span></p>
<div><strong><span>二  排序的分类</span></strong></div>
<div>1. 按是否涉及数据的内、外存交换分为</div>
<div>内部排序: 内部排序(简称内排序),是带排序纪录存放在计算机内存中进行的排序过程.  细分又可为插入排序、选择排序、交换排序、归并排序和基数排序.</div>
<div>外部排序:  外部排序(简称外排序),是带排序纪录的数量很大,以至于内存一次不能容纳全部纪录,在排序过程中,只有部分数被调入内存,并借助内存调整数在外存中的存放顺序的排序方法.</div>
<div>2. 按策略划分内部排序方法</div>
<div>可以分为五类: 插入排序、选择排序、交换排序、归并排序和基数排序.</div>
<div><strong><span>三  排序算法的基本操作</span></strong></div>
<div>1. 比较两个关键字的大小</div>
<div>2. 改变指向记录的指针或移动记录本身</div>
<div><strong><span style="font-size: 9pt;">注意</span></strong><strong><span style="font-size: 9pt;">: </span></strong><span style="font-size: 9pt;">第</span><span style="font-size: 9pt;">2</span><span style="font-size: 9pt;">种基本操作的实现依赖于待排序记录的存储方式</span><span style="font-size: 9pt;">.</span></div>
<div><strong><span>四  排序算法的性能评价</span></strong></div>
<div><span style="color: blue;">1. </span><span style="color: blue;">评价排序算法好坏的标准</span></div>
<div>(1)执行时间和所需的辅助空间</div>
<div>(2)算法本身的复杂程度</div>
<div><span style="color: blue;">2. </span><span style="color: blue;">排序算法的空间复杂度</span></div>
<div>若排序算法所需的辅助空间并不依赖于问题的规模n,即辅助空间是O(1),则称之为就地排序(In-Place  Sort). 非就地排序一般要求的辅助空间为O(n).</div>
<div><span style="color: blue;">3. </span><span style="color: blue;">排序算法的时间开销</span></div>
<div>大多数排序算法的时间开销主要是关键字之间的比较和记录的移动.  有的排序算法其执行时间不仅依赖于问题的规模,还取决于输入实例中数据的状态.</div>
<div><strong><span>1  插入排序</span></strong></div>
<div><strong><span style="font-size: large;">1.1  直接插入排序</span></strong></div>
<div><strong>定义:</strong> 直接插入排序(Straight Insertion Sort)是一种最简单的排序方法.  它的基本操作是将一个记录插入到一个长度为m(假设)的有序表中,使之仍保持有序,从而得到一个新的长度为m＋1的有序表.</div>
<div><strong>算法思路:</strong> 设有一组关键字{K1,K2,…,Kn},排序开始就认为K1是一个有序序列,让K2  插入上述表长为1的有序序列,使之成为一个表长为2的有序序列,然后让K3插入上述表长为2的有序序列,使之成为一个表长为3的有序序列,依次类推,最后让Kn插入上述表长为  n-1的有序序列,得一个表长为n的有序序列.</div>
<div><strong>算法时间复杂度:</strong> 此算法外循环n-1次,在一般情况下内循环平均比较次数的数量级为Ｏ(n),所以算法总时间复杂度为Ｏ(n^2).</div>
<div><strong>直接插入排序的稳定性:</strong> 直接插入排序是<strong><span style="color: blue;">稳定</span>.</strong>的排序方法</div>
<div><strong>具体算法:</strong></div>
<div><span style="color: #009900;">/* </span><span style="color: #009900;">比较数据函数模板</span><span style="color: #009900;"> */</span></div>
<div><span style="color: black;">template&lt;class </span><span style="color: blue;">Type</span><span style="color: black;">&gt;</span></div>
<div><span style="color: black;">typedef </span><span style="color: #880000;">bool</span><span style="color: black;"> __stdcall  (*</span><span style="color: gray;">PFunCustomCompare</span><span style="color: black;">)(const </span><span style="color: blue;">Type</span><span style="color: black;"> *</span><span style="color: gray;">Data_1</span><span style="color: black;">, const </span><span style="color: blue;">Type</span><span style="color: black;"> *</span><span style="color: gray;">Data_2</span><span style="color: black;">) ;</span></div>
<div><span style="color: #009900;">// InsertSort</span></div>
<div><span style="color: black;">template&lt;class </span><span style="color: blue;">Type</span><span style="color: black;">&gt;</span></div>
<div><span style="color: black;">void InsertSort (</span><span style="color: blue;">Type</span><span style="color: gray;">Array</span><span style="color: black;">[], int </span><span style="color: gray;">n</span><span style="color: black;">, </span><span style="color: gray;">PFunCustomCompare</span><span style="color: gray;">pfCompare</span><span style="color: black;">)</span></div>
<div><span style="color: black;">{ </span></div>
<div><span style="color: black;"> int </span><span style="color: gray;">i</span><span style="color: black;"> , </span><span style="color: gray;">j</span><span style="color: black;"> ; </span></div>
<div><span style="color: black;"> for (</span><span style="color: gray;">i</span><span style="color: black;"> = 2 ; </span><span style="color: gray;">i</span><span style="color: black;"> &lt;= </span><span style="color: gray;">n</span><span style="color: black;"> ; </span><span style="color: gray;">i</span><span style="color: black;"> ++) </span><span style="color: #009900;">// </span><span style="color: #009900;">进行</span><span style="color: #009900;">n-1</span><span style="color: #009900;">趟插入</span></div>
<div><span style="color: black;"> {</span></div>
<div><span style="color: black;"> </span><span style="color: gray;">Array</span><span style="color: black;">[0] = </span><span style="color: gray;">Array</span><span style="color: black;">[</span><span style="color: gray;">i</span><span style="color: black;">] ; </span><span style="color: #009900;">// Array[0]</span><span style="color: #009900;">为监视哨</span><span style="color: #009900;">,</span><span style="color: #009900;">也可作下边循环结束标志</span></div>
<div><span style="color: black;"> </span><span style="color: gray;">j</span><span style="color: black;"> = </span><span style="color: gray;">i</span><span style="color: black;"> &#8211; 1 ;</span></div>
<div><span style="color: black;"> while ( </span><span style="color: #880000;">pfCompare</span><span style="color: black;">(</span><span style="color: gray;">Array</span><span style="color: black;">[</span><span style="color: gray;">j</span><span style="color: black;">], </span><span style="color: gray;">Array</span><span style="color: black;">[0]) )</span></div>
<div><span style="color: black;"> {</span></div>
<div><span style="color: black;"> </span><span style="color: gray;">Array</span><span style="color: black;">[</span><span style="color: gray;">j</span><span style="color: black;">+1] = </span><span style="color: gray;">Array</span><span style="color: black;">[</span><span style="color: gray;">j</span><span style="color: black;">] ;</span></div>
<div><span style="color: black;"> </span><span style="color: gray;">j</span><span style="color: black;"> &#8212; ;</span></div>
<div><span style="color: black;"> }</span></div>
<div><span style="color: black;"> </span><span style="color: gray;">Array</span><span style="color: black;">[</span><span style="color: gray;">j</span><span style="color: black;">+1] = </span><span style="color: gray;">Array</span><span style="color: black;">[0] ; </span><span style="color: #009900;">// </span><span style="color: #009900;">将</span><span style="color: #009900;">r[0]</span><span style="color: #009900;">即原</span><span style="color: #009900;">r[i]</span><span style="color: #009900;">记录内容</span><span style="color: #009900;">,</span><span style="color: #009900;">插到</span><span style="color: #009900;">r[j]</span><span style="color: #009900;">后一位置</span></div>
<div><span style="color: black;"> }</span></div>
<div><span style="color: black;">}</span></div>
<div><span style="color: #009900;">// </span><span style="color: #009900;">或者</span><span style="color: #009900;">:</span><span style="color: #009900;">不需要监视哨</span></div>
<div><span style="color: black;">template&lt;class </span><span style="color: blue;">Type</span><span style="color: black;">&gt;</span></div>
<div><span style="color: black;">void __stdcall  InsertSort(</span><span style="color: blue;">Type</span><span style="color: gray;">Array</span><span style="color: black;">[], int </span><span style="color: gray;">Num</span><span style="color: black;">, </span><span style="color: gray;">PFunCustomCompare</span><span style="color: gray;">pfCompare</span><span style="color: black;">)</span></div>
<div><span style="color: black;">{</span></div>
<div><span style="color: black;"> for (int </span><span style="color: gray;">i</span><span style="color: black;"> = 1 ; </span><span style="color: gray;">i</span><span style="color: black;"> &lt; </span><span style="color: gray;">Num</span><span style="color: black;"> ; </span><span style="color: gray;">i</span><span style="color: black;"> ++)</span></div>
<div><span style="color: black;"> {</span></div>
<div><span style="color: black;"> </span><span style="color: blue;">Type</span><span style="color: gray;">temp</span><span style="color: black;"> = </span><span style="color: gray;">Array</span><span style="color: black;">[</span><span style="color: gray;">i</span><span style="color: black;">] ;</span></div>
<div><span style="color: black;"> int </span><span style="color: gray;">j</span><span style="color: black;"> ;</span></div>
<div><span style="color: black;"> for (</span><span style="color: gray;">j</span><span style="color: black;"> = </span><span style="color: gray;">i</span><span style="color: black;">-1 ; </span><span style="color: gray;">j</span><span style="color: black;"> &gt;= 0 &amp;&amp; </span><span style="color: #880000;">pfCompare</span><span style="color: black;">(</span><span style="color: gray;">temp</span><span style="color: black;">, </span><span style="color: gray;">Array</span><span style="color: black;">[</span><span style="color: gray;">j</span><span style="color: black;">]) ; </span><span style="color: gray;">j</span><span style="color: black;"> &#8211;)</span></div>
<div><span style="color: black;"> </span><span style="color: gray;">Array</span><span style="color: black;">[</span><span style="color: gray;">j</span><span style="color: black;">+1] = </span><span style="color: gray;">Array</span><span style="color: black;">[</span><span style="color: gray;">j</span><span style="color: black;">] ;</span></div>
<div><span style="color: black;"> </span><span style="color: gray;">Array</span><span style="color: black;">[</span><span style="color: gray;">j</span><span style="color: black;">+1] = </span><span style="color: gray;">temp</span><span style="color: black;"> ;</span></div>
<div><span style="color: black;"> }</span></div>
<div><span style="color: black;">}</span></div>
<div><strong>例1</strong> 设有一组关键字序列{55,22,44,11,33},这里n = 5,即有5个记录.  请将其按由小到大的顺序排序. 排序过程如下所示:</div>
<div>第一趟:  [55]  22  44  11  33</div>
<div>第二趟:  [22 55] 44 11 33</div>
<div>第三趟:  [22 44 55] 11 33</div>
<div>第四趟:  [11 22 44 55] 33</div>
<div>第五趟: [11  22 33 44 55]</div>
<div><strong><span style="font-size: large;">1.2  折半插入排序</span></strong></div>
<div><strong>定义: </strong>当直接插入排序进行到某一趟时,对于r[i].key来讲,前边i-1个记录已经按关键字有序.此时不用直接插入排序的方法,而改为折半查找,找出r[i].key应插的位置,然后插入.  这种方法就是折半插入排序(Binary Insertion Sort).</div>
<div><strong>具体算法:</strong></div>
<div><span style="color: #009900;">// BinarySort</span></div>
<div><span style="color: black;">template&lt;class </span><span style="color: blue;">T</span><span style="color: black;">&gt;</span></div>
<div><span style="color: black;">void BinarySort(</span><span style="color: blue;">T</span><span style="color: gray;">a</span><span style="color: black;">[], int </span><span style="color: gray;">n</span><span style="color: black;">)</span></div>
<div><span style="color: black;">{</span></div>
<div><span style="color: black;"> int </span><span style="color: gray;">i</span><span style="color: black;"> , </span><span style="color: gray;">j</span><span style="color: black;"> , </span><span style="color: gray;">l</span><span style="color: black;"> , </span><span style="color: gray;">h</span><span style="color: black;"> , </span><span style="color: gray;">mid</span><span style="color: black;"> ;</span></div>
<div><span style="color: black;"> for (</span><span style="color: gray;">i</span><span style="color: black;"> = 2 ; </span><span style="color: gray;">i</span><span style="color: black;"> &lt;= </span><span style="color: gray;">n</span><span style="color: black;"> ; </span><span style="color: gray;">i</span><span style="color: black;"> ++)</span></div>
<div><span style="color: black;"> {</span></div>
<div><span style="color: black;"> </span><span style="color: gray;">a</span><span style="color: black;">[0] = </span><span style="color: gray;">a</span><span style="color: black;">[</span><span style="color: gray;">i</span><span style="color: black;">] ;</span></div>
<div><span style="color: black;"> </span><span style="color: gray;">l</span><span style="color: black;"> = 1 ; </span><span style="color: gray;">h</span><span style="color: black;"> = </span><span style="color: gray;">i</span><span style="color: black;">-1 ; </span><span style="color: #009900;">// </span><span style="color: #009900;">认为在</span><span style="color: #009900;">a[1]</span><span style="color: #009900;">和</span><span style="color: #009900;">a[i-1]</span><span style="color: #009900;">之间已经有序</span></div>
<div><span style="color: black;"> while (</span><span style="color: gray;">l</span><span style="color: black;"> &lt;= </span><span style="color: gray;">h</span><span style="color: black;">) </span><span style="color: #009900;">// </span><span style="color: #009900;">对有序表进行折半查找</span></div>
<div><span style="color: black;"> {</span></div>
<div><span style="color: black;"> </span><span style="color: gray;">mid</span><span style="color: black;"> = (</span><span style="color: gray;">l</span><span style="color: black;">+</span><span style="color: gray;">h</span><span style="color: black;">) / 2 ;</span></div>
<div><span style="color: black;"> if(</span><span style="color: gray;">a</span><span style="color: black;">[0].</span><span style="color: gray;">key</span><span style="color: black;"> &lt; </span><span style="color: gray;">a</span><span style="color: black;">[</span><span style="color: gray;">mid</span><span style="color: black;">].</span><span style="color: gray;">key</span><span style="color: black;">)</span></div>
<div><span style="color: black;"> </span><span style="color: gray;">h</span><span style="color: black;"> = </span><span style="color: gray;">mid</span><span style="color: black;">-1 ; </span></div>
<div><span style="color: black;"> else</span></div>
<div><span style="color: black;"> </span><span style="color: gray;">l</span><span style="color: black;"> = </span><span style="color: gray;">mid</span><span style="color: black;">+1  ;</span></div>
<div><span style="color: black;"> }</span></div>
<div><span style="color: black;"> </span><span style="color: #009900;">// </span><span style="color: #009900;">结果在</span><span style="color: #009900;">mid</span><span style="color: #009900;">位置</span></div>
<div><span style="color: black;"> for(</span><span style="color: gray;">j</span><span style="color: black;"> = </span><span style="color: gray;">i</span><span style="color: black;">-1 ; </span><span style="color: gray;">j</span><span style="color: black;"> &gt;= </span><span style="color: gray;">mid</span><span style="color: black;"> ; </span><span style="color: gray;">j</span><span style="color: black;"> &#8211;)</span></div>
<div><span style="color: black;"> </span><span style="color: gray;">a</span><span style="color: black;">[</span><span style="color: gray;">j</span><span style="color: black;">+1] = </span><span style="color: gray;">a</span><span style="color: black;">[</span><span style="color: gray;">j</span><span style="color: black;">] ;</span></div>
<div><span style="color: black;"> </span><span style="color: gray;">a</span><span style="color: black;">[</span><span style="color: gray;">mid</span><span style="color: black;">] = </span><span style="color: gray;">a</span><span style="color: black;">[0] ;</span></div>
<div><span style="color: black;"> }</span></div>
<div><span style="color: black;">}</span></div>
<div><strong>算法时间复杂度:</strong> 折半插入排序,关键字的比较次数由于采用了折半查找而减少,数量级为O  (n*log(n)),但是元素移动次数仍为Ｏ(n^2). 故折半插入排序时间复杂度仍为Ｏ(n^2).</div>
<div><strong>折半插入排序的稳定性: </strong>折半插入排序方法是<strong><span style="color: blue;">稳定</span>.</strong>的</div>
<div><strong><span style="font-size: large;">1.3  2路插入排序</span></strong></div>
<div><strong><span style="font-size: large;">1.4  表插入排序</span></strong></div>
<div><strong><span style="font-size: large;">1.5  希尔排序</span></strong></div>
<div><strong>定义: </strong>希尔排序(Shell Sort)是D.L.希尔(D.L.Shell)提出的“缩小增量”的排序方法.  它的作法不是每次一个元素挨一个元素的比较.  而是初期选用大跨步(增量较大)间隔比较,使记录跳跃式接近它的排序位置,然后增量缩小,最后增量为1,这样记录移动次数大大减少,提高了排序效率.  希尔排序对增量序列的选择没有严格规定.</div>
<div><strong>算法思路:</strong></div>
<div>① 先取一个正整数d1(d1&lt;n),把全部记录分成d1个组,所有距离为d1的倍数的记录看成一组,然后在各组内进行插入排序 ;</div>
<div>② 然后取 d2 (d2&lt;d1) ;</div>
<div>③ 重复上述分组和排序操作,直到取di=1 (i&gt;=1),即所有记录成为一个组为止.  一般选d1约为n/2,d2为d1/2,d3为d2/2,…,di=1.</div>
<div><strong>具体算法:</strong></div>
<div><span style="color: #009900;">/* </span><span style="color: #009900;">比较数据函数模板</span><span style="color: #009900;"> */</span><span style="color: black;"> </span></div>
<div><span style="color: black;">template&lt;class </span><span style="color: blue;">Type</span><span style="color: black;">&gt;</span></div>
<div><span style="color: black;">typedef </span><span style="color: #880000;">bool</span><span style="color: black;"> __stdcall  (*</span><span style="color: gray;">PFunCustomCompare</span><span style="color: black;">)(const </span><span style="color: blue;">Type</span><span style="color: black;"> *</span><span style="color: gray;">Data_1</span><span style="color: black;">, const </span><span style="color: blue;">Type</span><span style="color: black;"> *</span><span style="color: gray;">Data_2</span><span style="color: black;">) ;</span></div>
<div><span style="color: black;">template &lt;class </span><span style="color: blue;">Type</span><span style="color: black;">&gt; </span></div>
<div><span style="color: black;">void __stdcall ShellSort(</span><span style="color: blue;">Type</span><span style="color: gray;">Array</span><span style="color: black;">[], int </span><span style="color: gray;">Num</span><span style="color: black;">, PFunCusomCompare </span><span style="color: gray;">pfCompare</span><span style="color: black;">)</span></div>
<div><span style="color: black;">{</span></div>
<div><span style="color: black;"> d = </span><span style="color: gray;">Num</span><span style="color: black;"> ;</span></div>
<div><span style="color: black;"> do</span></div>
<div><span style="color: black;"> {</span></div>
<div><span style="color: black;"> d = d/2 ; </span><span style="color: #009900;">// </span><span style="color: #009900;">一般增量设置为数组元素个数</span><span style="color: #009900;">,</span><span style="color: #009900;">不断除以</span><span style="color: #009900;">2</span><span style="color: #009900;">以取小</span></div>
<div><span style="color: black;"> for (int </span><span style="color: gray;">i</span><span style="color: black;"> = d+1 ; </span><span style="color: gray;">i</span><span style="color: black;"> &lt;= </span><span style="color: gray;">Num</span><span style="color: black;"> ; ++ </span><span style="color: gray;">i</span><span style="color: black;">)</span></div>
<div><span style="color: black;"> {</span></div>
<div><span style="color: black;"> if (</span><span style="color: #880000;">pfCompare</span><span style="color: black;">(</span><span style="color: gray;">Array</span><span style="color: black;">[</span><span style="color: gray;">i</span><span style="color: black;">], </span><span style="color: gray;">Array</span><span style="color: black;">[</span><span style="color: gray;">i</span><span style="color: black;">-d]))</span></div>
<div><span style="color: black;"> {</span></div>
<div><span style="color: black;"> </span><span style="color: blue;">Type</span><span style="color: gray;">temp</span><span style="color: black;"> = </span><span style="color: gray;">Array</span><span style="color: black;">[</span><span style="color: gray;">i</span><span style="color: black;">] ;</span></div>
<div><span style="color: black;"> for (int </span><span style="color: gray;">j</span><span style="color: black;"> = </span><span style="color: gray;">i</span><span style="color: black;">-d ; </span><span style="color: gray;">j</span><span style="color: black;"> &gt; 0  &amp;&amp; fpCompare(</span><span style="color: gray;">temp</span><span style="color: black;">, </span><span style="color: gray;">Array</span><span style="color: black;">[</span><span style="color: gray;">j</span><span style="color: black;">]) ; </span><span style="color: gray;">j</span><span style="color: black;"> = </span><span style="color: gray;">j</span><span style="color: black;">-d)</span></div>
<div><span style="color: black;"> </span><span style="color: gray;">Array</span><span style="color: black;">[</span><span style="color: gray;">j</span><span style="color: black;">-d] = </span><span style="color: gray;">Array</span><span style="color: black;">[</span><span style="color: gray;">j</span><span style="color: black;">] ;</span></div>
<div><span style="color: black;"> </span><span style="color: gray;">Array</span><span style="color: black;">[</span><span style="color: gray;">j</span><span style="color: black;">+d] = </span><span style="color: gray;">temp</span><span style="color: black;"> ;</span></div>
<div><span style="color: black;"> }</span></div>
<div><span style="color: black;"> }</span></div>
<div><span style="color: black;"> }while (d &gt; 1)  ;</span></div>
<div><span style="color: black;">}</span></div>
<div><span style="color: green;">//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////</span></div>
<div><span style="color: green;">// Example two :</span></div>
<div><span style="color: black;">void ShellPass(SeqList </span><span style="color: gray;">R</span><span style="color: black;">, int </span><span style="color: gray;">d</span><span style="color: black;">)</span></div>
<div><span style="color: black;">{</span></div>
<div><span style="color: black;"> </span><span style="color: #009900;">//</span><span style="color: #009900;">希尔排序中的一趟排序</span><span style="color: #009900;">,d</span><span style="color: #009900;">为当前增量</span></div>
<div><span style="color: black;"> for(</span><span style="color: gray;">i</span><span style="color: black;"> = </span><span style="color: gray;">d</span><span style="color: black;">+1 ; </span><span style="color: gray;">i</span><span style="color: black;"> &lt;= </span><span style="color: gray;">n</span><span style="color: black;"> ; </span><span style="color: gray;">i</span><span style="color: black;"> ++) </span><span style="color: #009900;">// </span><span style="color: #009900;">将</span><span style="color: #009900;">R[d+1..n]</span><span style="color: #009900;">分别插入各组当前的有序区</span></div>
<div><span style="color: black;"> if(</span><span style="color: gray;">R</span><span style="color: black;">[</span><span style="color: gray;">i</span><span style="color: black;">].</span><span style="color: gray;">key</span><span style="color: black;"> &lt; </span><span style="color: gray;">R</span><span style="color: black;">[</span><span style="color: gray;">i</span><span style="color: black;">-</span><span style="color: gray;">d</span><span style="color: black;">].</span><span style="color: gray;">key</span><span style="color: black;">)</span></div>
<div><span style="color: black;"> {</span></div>
<div><span style="color: black;"> </span><span style="color: gray;">R</span><span style="color: black;">[0] = </span><span style="color: gray;">R</span><span style="color: black;">[</span><span style="color: gray;">i</span><span style="color: black;">] ;</span></div>
<div><span style="color: black;"> </span><span style="color: gray;">j</span><span style="color: black;"> = </span><span style="color: gray;">i</span><span style="color: black;">-</span><span style="color: gray;">d</span><span style="color: black;"> ; </span><span style="color: #009900;">//R[0]</span><span style="color: #009900;">只是暂存单元</span><span style="color: #009900;">,</span><span style="color: #009900;">不是哨兵</span></div>
<div><span style="color: black;"> do</span></div>
<div><span style="color: black;"> {</span></div>
<div><span style="color: black;"> </span><span style="color: #009900;">//</span><span style="color: #009900;">查找</span><span style="color: #009900;">R[i]</span><span style="color: #009900;">的插入位置</span></div>
<div><span style="color: black;"> </span><span style="color: gray;">R</span><span style="color: black;">[</span><span style="color: gray;">j</span><span style="color: black;">+</span><span style="color: gray;">d</span><span style="color: black;">] = </span><span style="color: gray;">R</span><span style="color: black;">[</span><span style="color: gray;">j</span><span style="color: black;">] ; </span><span style="color: #009900;">//</span><span style="color: #009900;">后移记录</span></div>
<div><span style="color: black;"> </span><span style="color: gray;">j</span><span style="color: black;"> = </span><span style="color: gray;">j</span><span style="color: black;">-</span><span style="color: gray;">d</span><span style="color: black;"> ; </span><span style="color: #009900;">//</span><span style="color: #009900;">查找前一记录</span></div>
<div><span style="color: black;"> }while  (</span><span style="color: gray;">j</span><span style="color: black;"> &gt; 0  &amp;&amp; </span><span style="color: gray;">R</span><span style="color: black;">[0].</span><span style="color: gray;">key</span><span style="color: black;"> &lt; </span><span style="color: gray;">R</span><span style="color: black;">[</span><span style="color: gray;">j</span><span style="color: black;">].</span><span style="color: gray;">key</span><span style="color: black;">) ;</span></div>
<div><span style="color: black;"> </span><span style="color: gray;">R</span><span style="color: black;">[</span><span style="color: gray;">j</span><span style="color: black;">+</span><span style="color: gray;">d</span><span style="color: black;">] = </span><span style="color: gray;">R</span><span style="color: black;">[0] ; </span><span style="color: #009900;">//</span><span style="color: #009900;">插入</span><span style="color: #009900;">R[i]</span><span style="color: #009900;">到正确的位置上</span></div>
<div><span style="color: black;"> } </span><span style="color: #009900;">// endif</span></div>
<div><span style="color: black;">} </span><span style="color: #009900;">// ShellPass</span></div>
<div><span style="color: black;">void ShellSort(SeqList </span><span style="color: gray;">R</span><span style="color: black;">)</span></div>
<div><span style="color: black;">{</span></div>
<div><span style="color: black;"> int </span><span style="color: gray;">increment</span><span style="color: black;"> = </span><span style="color: gray;">n</span><span style="color: black;"> ; </span><span style="color: #009900;">//</span><span style="color: #009900;">增量初值</span><span style="color: #009900;">,</span><span style="color: #009900;">不妨设</span><span style="color: #009900;">n&gt;0</span></div>
<div><span style="color: black;"> do</span></div>
<div><span style="color: black;"> {</span></div>
<div><span style="color: black;"> </span><span style="color: gray;">increment</span><span style="color: black;"> = </span><span style="color: gray;">increment</span><span style="color: black;">/3 + 1 ; </span><span style="color: #009900;">//</span><span style="color: #009900;">求下一增量</span></div>
<div><span style="color: black;"> ShellPass(</span><span style="color: gray;">R</span><span style="color: black;">, </span><span style="color: gray;">increment</span><span style="color: black;">) ; </span><span style="color: #009900;">//</span><span style="color: #009900;">一趟增量为</span><span style="color: #009900;">increment</span><span style="color: #009900;">的</span><span style="color: #009900;">Shell</span><span style="color: #009900;">插入排序</span></div>
<div><span style="color: black;"> }while (</span><span style="color: gray;">increment</span><span style="color: black;"> &gt; 1)  ;</span></div>
<div><span style="color: black;">} </span><span style="color: #009900;">//  ShellSort</span></div>
<div><span style="font-size: 9pt;">注意</span><span style="font-size: 9pt;">: </span><span style="font-size: 9pt;">当增量</span><span style="font-size: 9pt;">d=1</span><span style="font-size: 9pt;">时</span><span style="font-size: 9pt;">,ShellPass</span><span style="font-size: 9pt;">和</span><span style="font-size: 9pt;">InsertSort</span><span style="font-size: 9pt;">基本一致</span><span style="font-size: 9pt;">,</span><span style="font-size: 9pt;">只是由于没有哨兵而在内循环中增加了一个循环判定条件</span><span style="font-size: 9pt;">&#8220;j&gt;0&#8243;,</span><span style="font-size: 9pt;">以防下标越界</span><span style="font-size: 9pt;">.</span></div>
<div><strong>算法分析</strong><strong>:</strong></div>
<div style="margin: 0cm 0cm 0pt 18pt; text-indent: -18pt;"><span>①<span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none;"> </span></span>增量序列的选择</div>
<div style="margin: 0cm 0cm 0pt 18pt;">Shell排序的执行时间依赖于增量序列. 好的增量序列的共同特征:  最后一个增量必须为1 ; 应该尽量避免序列中的值(尤其是相邻的值)互为倍数的情况. 有人通过大量的实验,给出了目前比较好的结果:  当n较大时,比较和移动的次数在n<sup>1.25</sup>至1.6n<sup>1.25</sup>之间.</div>
<div style="margin: 0cm 0cm 0pt 18pt; text-indent: -18pt;"><span>②<span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none;"> </span></span>Shell排序的时间性能优于直接插入排序</div>
<div style="margin: 0cm 0cm 0pt 18pt;">希尔排序的时间性能优于直接插入排序的原因:  当文件初态基本有序时直接插入排序所需的比较和移动次数均较少 ;  当n值较小时,n和n2的差别也较小,即直接插入排序的最好时间复杂度O(n)和最坏时间复杂度O(n2)差别不大 ;  在希尔排序开始时增量较大,分组较多,每组的记录数目少,故各组内直接插入较快,后来增量di逐渐缩小,分组数逐渐减少,而各组的记录数目逐渐增多,但由于已经按di-1作为距离排过序,使文件较接近于有序状态,所以新的一趟排序过程也较快.  因此,希尔排序在效率上较直接插入排序有较大的改进.</div>
<div style="margin: 0cm 0cm 0pt 18pt; text-indent: -18pt;"><span>③<span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none;"> </span></span>稳定性</div>
<div style="margin: 0cm 0cm 0pt 18pt;">希尔排序是<strong><span style="color: blue;">不稳定</span>.</strong>的</div>
<div><strong><span>2  选择排序</span></strong></div>
<div>选择排序(Selection Sort)的基本思想是:  每一趟从待排序的记录中选出关键字最小的记录,顺序放在已排好序的子文件的最后,直到全部记录排序完毕.</div>
<div><strong><span style="font-size: large;">2.1  简单选择排序</span></strong></div>
<div><strong>定义: </strong>简单选择排序(Simple Selection Sort)也是直接选择排序.  此方法在一些高级语言课程中做过介绍,是一种较为容易理解的方法.</div>
<div><strong>算法思想: </strong>对于一组关键字{K1,K2,…,Kn},首先从K1,K2,…,Kn中选择最小值,假如它是Kz,则将Kz与K1对换,然后从K2,K3,…,Kn中选择最小值Kz,再将Kz与K2对换.  如此进行选择和调换n-2趟,第(n-1)趟,从Kn-1、Kn中选择最小值Kz将Kz与Kn-1对换,最后剩下的就是该序列中的最大值,一个由小到大的有序序列就这样形成.  即:  在要排序的一组数中,选出最小的一个数与第一个位置的数交换,然后在剩下的数当中再找最小的与第二个位置的数交换,如此循环到倒数第二个数和最后一个数比较为止.</div>
<div><strong>具体算法:</strong></div>
<div><span style="color: #009900;">/* </span><span style="color: #009900;">比较数据函数模板</span><span style="color: #009900;"> */</span></div>
<div><span style="color: black;">template&lt;class </span><span style="color: blue;">Type</span><span style="color: black;">&gt;</span></div>
<div><span style="color: black;">typedef </span><span style="color: #880000;">bool</span><span style="color: black;"> __stdcall  (*</span><span style="color: gray;">PFunCustomCompare</span><span style="color: black;">)(const </span><span style="color: blue;">Type</span><span style="color: black;"> *</span><span style="color: gray;">Data_1</span><span style="color: black;">,const </span><span style="color: blue;">Type</span><span style="color: black;"> *</span><span style="color: gray;">Data_2</span><span style="color: black;">) ;</span></div>
<div><span style="color: #009900;">/* </span><span style="color: #009900;">交换数据函数模板</span><span style="color: #009900;"> */</span></div>
<div><span style="color: black;">template&lt;class </span><span style="color: blue;">Type</span><span style="color: black;">&gt;</span></div>
<div><span style="color: black;">typedef void __stdcall (*</span><span style="color: gray;">PFunCusomSwap</span><span style="color: black;">)(const </span><span style="color: blue;">Type</span><span style="color: black;"> *</span><span style="color: gray;">Data_1</span><span style="color: black;">,const </span><span style="color: blue;">Type</span><span style="color: black;"> *</span><span style="color: gray;">Data_2</span><span style="color: black;">)  ;</span></div>
<div><span style="color: black;">template&lt;class </span><span style="color: blue;">Type</span><span style="color: black;">&gt;</span></div>
<div><span style="color: black;">void __stdcall  SelectSort(</span><span style="color: blue;">Type</span><span style="color: gray;">Array</span><span style="color: black;">[], int </span><span style="color: gray;">Num</span><span style="color: black;">, PFunCusomCompare </span><span style="color: gray;">pfCompare</span><span style="color: black;">,  PFunCusomSwap </span><span style="color: gray;">pfSwap</span><span style="color: black;">)</span></div>
<div><span style="color: black;">{</span></div>
<div><span style="color: black;"> for (int </span><span style="color: gray;">i</span><span style="color: black;"> = 0 ; </span><span style="color: gray;">i</span><span style="color: black;"> &lt; </span><span style="color: gray;">Num</span><span style="color: black;">-1 ; ++ </span><span style="color: gray;">i</span><span style="color: black;">)</span></div>
<div><span style="color: black;"> {</span></div>
<div><span style="color: black;"> </span><span style="color: #009900;">//</span><span style="color: #009900;">从</span><span style="color: #009900;">i~n-1</span><span style="color: #009900;">中选择要选的数据</span></div>
<div><span style="color: black;"> int </span><span style="color: gray;">min</span><span style="color: black;"> = </span><span style="color: gray;">i</span><span style="color: black;"> ;</span></div>
<div><span style="color: black;"> for (int </span><span style="color: gray;">j</span><span style="color: black;"> = </span><span style="color: gray;">i</span><span style="color: black;">+1 ; </span><span style="color: gray;">j</span><span style="color: black;"> &lt; </span><span style="color: gray;">Num</span><span style="color: black;"> ; ++ </span><span style="color: gray;">j</span><span style="color: black;">)</span></div>
<div><span style="color: black;"> if (</span><span style="color: #880000;">pfCompare</span><span style="color: black;"> (</span><span style="color: gray;">Array</span><span style="color: black;">[</span><span style="color: gray;">j</span><span style="color: black;">], </span><span style="color: gray;">Array</span><span style="color: black;">[</span><span style="color: gray;">min</span><span style="color: black;">]))</span></div>
<div><span style="color: black;"> </span><span style="color: gray;">min</span><span style="color: black;"> = </span><span style="color: gray;">j</span><span style="color: black;"> ;</span></div>
<div><span style="color: black;"> if(</span><span style="color: gray;">min</span><span style="color: black;"> != </span><span style="color: gray;">i</span><span style="color: black;">)</span></div>
<div><span style="color: black;"> </span><span style="color: #880000;">pfSwap</span><span style="color: black;">(</span><span style="color: gray;">Array</span><span style="color: black;">[</span><span style="color: gray;">j</span><span style="color: black;">],</span><span style="color: gray;">Array</span><span style="color: black;">[</span><span style="color: gray;">min</span><span style="color: black;">]) ;</span></div>
<div><span style="color: black;"> }</span></div>
<div><span style="color: black;">}</span></div>
<div><strong>算法分析</strong><strong>:</strong></div>
<div style="margin: 0cm 0cm 0pt 39pt; text-indent: -18pt;"><span>1.<span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none;"> </span></span>关键字比较次数</div>
<div style="margin: 0cm 0cm 0pt 39pt;">无论文件初始状态如何,在第i趟排序选出最小关键字的记录,需做n-i次比较,因此总的比较次数为:  n(n-1)/2 = O(n2).</div>
<div style="margin: 0cm 0cm 0pt 39pt; text-indent: -18pt;"><span>2.<span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none;"> </span></span>记录的移动次数</div>
<div style="margin: 0cm 0cm 0pt 39pt;">当初始文件为正序时,移动次数为0 ;</div>
<div style="margin: 0cm 0cm 0pt 39pt;">文件初态反序时,每趟排序均要执行交换操作,中的移动次数取最大值(n-1)  ;</div>
<div style="margin: 0cm 0cm 0pt 39pt;">直接选择排序的平均时间复杂度为O(n2) .</div>
<div style="margin: 0cm 0cm 0pt 39pt; text-indent: -18pt;"><span>3.<span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none;"> </span></span>直接选择排序是一个就地排序</div>
<div style="margin: 0cm 0cm 0pt 39pt; text-indent: -18pt;"><span>4.<span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none;"> </span></span>稳定性分析</div>
<div style="margin: 0cm 0cm 0pt 39pt;">直接选择排序是不稳定的.</div>
<div><strong><span style="font-size: large;">2.2 堆排序</span></strong></div>
<div><strong>定义: </strong>树形选择排序(锦标赛排序),1964年威洛姆斯(J.Willioms)提出了进一步改正的排序方法,即堆排序(Heap Sort).</div>
<div>堆是n个元素的有限序列{K1,K2,…,Kn},它当且仅当满足如下关系:</div>
<div>这是一个上小、底大的堆. 若是一个上大、底小的堆,只需把“&lt;=”改为“&gt;=”即可.  堆是一种数据元素之间的逻辑关系,常用向量做存储结构. 对于满二叉树,当对它的结点由上而下,自左至右编号之后,编号为i的结点是编号为2i和2i+1结点的双亲.  反过来讲,结点2i是结点i的左孩子,结点2i+1是结点i的右孩子. 图9.7表示完全二叉树和它在向量中的存储状态. 结点编号对应向量中的下标号.  用堆的概念分析向量中的数据,它显然满足(上小、底大)堆的关系. 不难看出满足堆的逻辑关系的一组数据,可画成二叉树的形状,并且它是一棵完全二叉树树形.  因此,也可借助完全二叉树来描述堆的概念.  若完全二叉树中任一非叶子结点的值小于等于(或大于等于)其左、右孩子结点的值,则从根结点开始按结点编号排列所得的结点序列就是一个小根(大根)堆.  在图9.8中(a)、(c)是堆, (b)、(d)不是堆.</div>
<div><strong>堆排序的算法思想: </strong>堆排序利用了大根堆(或小根堆)堆顶记录的关键字最大(或最小)这一特征,使得在当前无序区中选取最大(或最小)关键字的记录变得简单.</div>
<div>（1）用大根堆排序的基本思想</div>
<div>①. 先将初始文件R[1..n]建成一个大根堆,此堆为初始的无序区</div>
<div>②.  再将关键字最大的记录R[1](即堆顶)和无序区的最后一个记录R[n]交换,由此得到新的无序区R[1..n-1]和有序区R[n],且满足R[1..n-1].keys  ≤ R[n].key</div>
<div>③. 由于交换后新的根R[1]可能违反堆性质,故应将当前无序区R[1..n-1]调整为堆.  然后再次将R[1..n-1]中关键字最大的记录R[1]和该区间的最后一个记录R[n-1]交换,由此得到新的无序区R[1..n-2]和有序区R[n-1..n],且仍满足关系R[1..n-2].keys≤R[n-1..n].keys,同样要将R[1..n-2]调整为堆.</div>
<div>④. ……</div>
<div>⑤. 直到无序区只有一个元素为止.</div>
<div>（2）大根堆排序算法的基本操作:</div>
<div>①. 初始化操作: 将R[1..n]构造为初始堆 ;</div>
<div>②. 每一趟排序的基本操作: 将当前无序区的堆顶记录R[1]和该区间的最后一个记录交换,然后将新的无序区调整为堆(亦称重建堆).</div>
<div>注意:</div>
<div>① 只需做n-1趟排序,选出较大的n-1个关键字即可以使得文件递增有序.</div>
<div>② 用小根堆排序与利用大根堆类似,只不过其排序结果是递减有序的. 堆排序和直接选择排序相反:  在任何时刻,堆排序中无序区总是在有序区之前,且有序区是在原向量的尾部由后往前逐步扩大至整个向量为止.</div>
<div><strong>具体算法:</strong></div>
<div>建堆(BuildHeap)和堆化(Heapify)函数的实现:</div>
<div>因为构造初始堆必须使用到调整堆的操作,先讨论Heapify的实现.</div>
<div>以R[1]为根的堆,在R[1]与R[i]交换后,新的无序区R[1..i-1]中只有R[1]的值发生了变化,故除R[1]可能违反堆性质外,其余任何结点为根的子树均是堆.  因此,当被调整区间是R[low..high]时,只须调整以R[low]为根的树即可.  &#8220;筛选法&#8221;调整堆R[low]的左、右子树(若存在)均已是堆,这两棵子树的根R[2low]和R[2low+1]分别是各自子树中关键字最大的结点.  若R[low].key不小于这两个孩子结点的关键字,则R[low]未违反堆性质,以R[low]为根的树已是堆,无须调整;  否则必须将R[low]和它的两个孩子结点中关键字较大者进行交换,即R[low]与R[large](R[large].key=max(R[2low].key,R[2low+1].key))交换.  交换后又可能使结点R[large]违反堆性质,同样由于该结点的两棵子树(若存在)仍然是堆,故可重复上述的调整过程,对以R[large]为根的树进行调整.  此过程直至当前被调整的结点已满足堆性质,或者该结点已是叶子为止. 上述过程就象过筛子一样,把较小的关键字逐层筛下去,而将较大的关键字逐层选上来.  因此,有人将此方法称为&#8221;筛选法&#8221;.</div>
<div><strong>BuildHeap</strong><strong>的实现</strong></div>
<div>要将初始文件R[l..n]调整为一个大根堆,就必须将它所对应的完全二叉树中以每一结点为根的子树都调整为堆.  显然只有一个结点的树是堆,而在完全二叉树中,所有序号大于n/2的结点都是叶子,因此以这些结点为根的子树均已是堆.  这样,我们只需依次将以序号为n/2,…,1的结点作为根的子树都调整为堆即可.</div>
<div><span style="color: #009900;">//&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211; </span></div>
<div><span style="color: black;">template &lt;class </span><span style="color: blue;">type</span><span style="color: black;">&gt; static void </span><span style="color: #880000;">HeapIfy</span><span style="color: black;"> (</span><span style="color: blue;">type</span><span style="color: black;"> *</span><span style="color: gray;">arry</span><span style="color: black;">, int </span><span style="color: gray;">size</span><span style="color: black;">, int </span><span style="color: gray;">index</span><span style="color: black;">)  ;</span></div>
<div><span style="color: black;">template &lt;class </span><span style="color: blue;">type</span><span style="color: black;">&gt; inline static  void </span><span style="color: #880000;">BuildHeap</span><span style="color: black;"> (</span><span style="color: blue;">type</span><span style="color: black;"> *</span><span style="color: gray;">arry</span><span style="color: black;">, int </span><span style="color: gray;">size</span><span style="color: black;">) ;</span></div>
<div><span style="color: black;">template &lt;class </span><span style="color: blue;">type</span><span style="color: black;">&gt; static void </span><span style="color: #880000;">HeapSort</span><span style="color: black;"> (</span><span style="color: blue;">type</span><span style="color: black;"> *</span><span style="color: gray;">arry</span><span style="color: black;">, int </span><span style="color: gray;">size</span><span style="color: black;">)  ;</span></div>
<div><span style="color: #009900;">//&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211; </span></div>
<div><span style="color: black;">template &lt;class </span><span style="color: blue;">type</span><span style="color: black;">&gt;</span></div>
<div><span style="color: black;">static void </span><span style="color: #880000;">HeapSort</span><span style="color: black;"> (</span><span style="color: blue;">type</span><span style="color: black;"> *</span><span style="color: gray;">arry</span><span style="color: black;">, int </span><span style="color: gray;">size</span><span style="color: black;">)</span></div>
<div><span style="color: black;">{</span></div>
<div><span style="color: black;"> if (</span><span style="color: gray;">size</span><span style="color: black;"> &lt;= 1) return  ;</span></div>
<div><span style="color: black;"> </span><span style="color: #880000;">BuildHeap</span><span style="color: black;"> (</span><span style="color: gray;">arry</span><span style="color: black;">, </span><span style="color: gray;">size</span><span style="color: black;">) ;</span></div>
<div><span style="color: black;"> int </span><span style="color: gray;">count</span><span style="color: black;"> = </span><span style="color: gray;">size</span><span style="color: black;"> ;</span></div>
<div><span style="color: black;"> while (</span><span style="color: gray;">count</span><span style="color: black;"> &gt;=  2)</span></div>
<div><span style="color: black;"> {</span></div>
<div><span style="color: black;"> </span><span style="color: blue;">type</span><span style="color: gray;">temp</span><span style="color: black;"> = </span><span style="color: gray;">arry</span><span style="color: black;">[</span><span style="color: gray;">count</span><span style="color: black;">-1] ;</span></div>
<div><span style="color: black;"> </span><span style="color: gray;">arry</span><span style="color: black;">[</span><span style="color: gray;">count</span><span style="color: black;">-1] = </span><span style="color: gray;">arry</span><span style="color: black;">[0] ;</span></div>
<div><span style="color: black;"> </span><span style="color: gray;">arry</span><span style="color: black;">[0] = </span><span style="color: gray;">temp</span><span style="color: black;"> ;</span></div>
<div><span style="color: black;"> </span><span style="color: gray;">count</span><span style="color: black;"> &#8212; ;</span></div>
<div><span style="color: black;"> </span><span style="color: #880000;">BuildHeap</span><span style="color: black;"> (</span><span style="color: gray;">arry</span><span style="color: black;">, </span><span style="color: gray;">count</span><span style="color: black;">) ;</span></div>
<div><span style="color: black;"> }</span></div>
<div><span style="color: black;">}</span></div>
<div><span style="color: #009900;">//&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211; </span></div>
<div><span style="color: black;">template &lt;class </span><span style="color: blue;">type</span><span style="color: black;">&gt; </span></div>
<div><span style="color: black;">inline static void </span><span style="color: #880000;">BuildHeap</span><span style="color: black;"> (</span><span style="color: blue;">type</span><span style="color: black;"> *</span><span style="color: gray;">arry</span><span style="color: black;">, int </span><span style="color: gray;">size</span><span style="color: black;">)</span></div>
<div><span style="color: black;">{</span></div>
<div><span style="color: blue;">#if </span><span style="color: black;">_DEBUG</span></div>
<div><span style="color: black;"> </span><span style="color: #a000a0;">assert</span><span style="color: black;"> (</span><span style="color: gray;">arry</span><span style="color: black;"> &amp;&amp; </span><span style="color: gray;">size</span><span style="color: black;"> &gt; 0)  ; </span></div>
<div><span style="color: blue;">#endif</span></div>
<div><span style="color: black;"> int </span><span style="color: gray;">i</span><span style="color: black;"> = (</span><span style="color: gray;">size</span><span style="color: black;">-1)/2 ;</span></div>
<div><span style="color: black;"> for ( ; </span><span style="color: gray;">i</span><span style="color: black;"> &gt;= 0 ; </span><span style="color: gray;">i</span><span style="color: black;"> &#8211;)</span></div>
<div><span style="color: black;"> </span><span style="color: #880000;">HeapIfy</span><span style="color: black;"> (</span><span style="color: gray;">arry</span><span style="color: black;">, </span><span style="color: gray;">size</span><span style="color: black;">, </span><span style="color: gray;">i</span><span style="color: black;">) ;</span></div>
<div><span style="color: black;">} </span></div>
<div><span style="color: #009900;">//&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211; </span></div>
<div><span style="color: black;">static void </span><span style="color: #880000;">HeapIfy</span><span style="color: black;"> (</span><span style="color: blue;">type</span><span style="color: black;"> *</span><span style="color: gray;">arry</span><span style="color: black;">, int </span><span style="color: gray;">size</span><span style="color: black;">, int </span><span style="color: gray;">index</span><span style="color: black;">)</span></div>
<div><span style="color: black;">{</span></div>
<div><span style="color: black;"> </span><span style="color: #009900;">// </span><span style="color: #009900;">平衡堆</span><span style="color: #009900;">,</span><span style="color: #009900;">参数为数组</span><span style="color: #009900;">,</span><span style="color: #009900;">数组长度</span><span style="color: #009900;">,</span><span style="color: #009900;">加入的元素下标</span></div>
<div><span style="color: blue;">#if </span><span style="color: black;">_DEBUG</span></div>
<div><span style="color: black;"> </span><span style="color: #a000a0;">assert</span><span style="color: black;"> (</span><span style="color: gray;">arry</span><span style="color: black;"> &amp;&amp; </span><span style="color: gray;">size</span><span style="color: black;"> &gt; 0  &amp;&amp; </span><span style="color: gray;">index</span><span style="color: black;"> &gt;= 0 &amp;&amp; </span><span style="color: gray;">index</span><span style="color: black;"> &lt; </span><span style="color: gray;">size</span><span style="color: black;">) ;</span></div>
<div><span style="color: blue;">#endif</span></div>
<div><span style="color: black;"> int </span><span style="color: gray;">m</span><span style="color: black;"> = </span><span style="color: gray;">index</span><span style="color: black;"> ; </span><span style="color: #009900;">// </span><span style="color: #009900;">本身索引</span></div>
<div><span style="color: black;"> int </span><span style="color: gray;">l</span><span style="color: black;"> ;</span></div>
<div><span style="color: black;"> int </span><span style="color: gray;">r</span><span style="color: black;"> ;</span></div>
<div><span style="color: black;"> do</span></div>
<div><span style="color: black;"> {</span></div>
<div><span style="color: black;"> </span><span style="color: gray;">l</span><span style="color: black;"> = </span><span style="color: gray;">m</span><span style="color: black;">*2 + 1 ; </span><span style="color: #009900;">// </span><span style="color: #009900;">左儿子索引</span></div>
<div><span style="color: black;"> </span><span style="color: gray;">r</span><span style="color: black;"> = </span><span style="color: gray;">l</span><span style="color: black;"> + 1 ; </span><span style="color: #009900;">// </span><span style="color: #009900;">右儿子索引</span></div>
<div><span style="color: black;"> if (</span><span style="color: gray;">l</span><span style="color: black;"> &gt;= </span><span style="color: gray;">size</span><span style="color: black;">) </span><span style="color: #009900;">//</span><span style="color: #009900;">无儿子</span></div>
<div><span style="color: black;"> return  ;</span></div>
<div><span style="color: black;"> else if (</span><span style="color: gray;">r</span><span style="color: black;"> &gt;= </span><span style="color: gray;">size</span><span style="color: black;">)</span></div>
<div><span style="color: black;"> {</span></div>
<div><span style="color: black;"> </span><span style="color: #009900;">// </span><span style="color: #009900;">无右儿子</span></div>
<div><span style="color: black;"> if (</span><span style="color: gray;">arry</span><span style="color: black;">[</span><span style="color: gray;">m</span><span style="color: black;">] &gt;= </span><span style="color: gray;">arry</span><span style="color: black;">[</span><span style="color: gray;">l</span><span style="color: black;">]) </span></div>
<div><span style="color: black;"> return  ;</span></div>
<div><span style="color: black;"> else</span></div>
<div><span style="color: black;"> {</span></div>
<div><span style="color: black;"> </span><span style="color: blue;">type</span><span style="color: gray;">temp</span><span style="color: black;"> = </span><span style="color: gray;">arry</span><span style="color: black;">[</span><span style="color: gray;">m</span><span style="color: black;">] ;</span></div>
<div><span style="color: black;"> </span><span style="color: gray;">arry</span><span style="color: black;">[</span><span style="color: gray;">m</span><span style="color: black;">] = </span><span style="color: gray;">arry</span><span style="color: black;">[</span><span style="color: gray;">l</span><span style="color: black;">] ;</span></div>
<div><span style="color: black;"> </span><span style="color: gray;">arry</span><span style="color: black;">[</span><span style="color: gray;">l</span><span style="color: black;">] = </span><span style="color: gray;">temp</span><span style="color: black;"> ;</span></div>
<div><span style="color: black;"> return  ;</span></div>
<div><span style="color: black;"> }</span></div>
<div><span style="color: black;"> if (</span><span style="color: gray;">arry</span><span style="color: black;">[</span><span style="color: gray;">l</span><span style="color: black;">] &gt;= </span><span style="color: gray;">arry</span><span style="color: black;">[</span><span style="color: gray;">r</span><span style="color: black;">])</span></div>
<div><span style="color: black;"> { </span></div>
<div><span style="color: black;"> if  (</span><span style="color: gray;">arry</span><span style="color: black;">[</span><span style="color: gray;">m</span><span style="color: black;">] &gt;= </span><span style="color: gray;">arry</span><span style="color: black;">[</span><span style="color: gray;">l</span><span style="color: black;">])</span></div>
<div><span style="color: black;"> return ;</span></div>
<div><span style="color: black;"> </span><span style="color: blue;">type</span><span style="color: gray;">temp</span><span style="color: black;"> = </span><span style="color: gray;">arry</span><span style="color: black;">[</span><span style="color: gray;">m</span><span style="color: black;">] ;</span></div>
<div><span style="color: black;"> </span><span style="color: gray;">arry</span><span style="color: black;">[</span><span style="color: gray;">m</span><span style="color: black;">] = </span><span style="color: gray;">arry</span><span style="color: black;">[</span><span style="color: gray;">l</span><span style="color: black;">] ;</span></div>
<div><span style="color: black;"> </span><span style="color: gray;">arry</span><span style="color: black;">[</span><span style="color: gray;">l</span><span style="color: black;">] = </span><span style="color: gray;">temp</span><span style="color: black;"> ;</span></div>
<div><span style="color: black;"> </span><span style="color: gray;">m</span><span style="color: black;"> = </span><span style="color: gray;">l</span><span style="color: black;"> ;</span></div>
<div><span style="color: black;"> continue  ;</span></div>
<div><span style="color: black;"> } </span></div>
<div><span style="color: black;"> }</span></div>
<div><span style="color: black;"> else</span></div>
<div><span style="color: black;"> { </span></div>
<div><span style="color: black;"> if (</span><span style="color: gray;">arry</span><span style="color: black;">[</span><span style="color: gray;">m</span><span style="color: black;">] &gt;= </span><span style="color: gray;">arry</span><span style="color: black;">[</span><span style="color: gray;">r</span><span style="color: black;">])</span></div>
<div><span style="color: black;"> return  ;</span></div>
<div><span style="color: black;"> </span><span style="color: blue;">type</span><span style="color: gray;">temp</span><span style="color: black;"> = </span><span style="color: gray;">arry</span><span style="color: black;">[</span><span style="color: gray;">m</span><span style="color: black;">] ;</span></div>
<div><span style="color: black;"> </span><span style="color: gray;">arry</span><span style="color: black;">[</span><span style="color: gray;">m</span><span style="color: black;">] = </span><span style="color: gray;">arry</span><span style="color: black;">[</span><span style="color: gray;">r</span><span style="color: black;">] ;</span></div>
<div><span style="color: black;"> </span><span style="color: gray;">arry</span><span style="color: black;">[</span><span style="color: gray;">r</span><span style="color: black;">] = </span><span style="color: gray;">temp</span><span style="color: black;"> ;</span></div>
<div><span style="color: black;"> </span><span style="color: gray;">m</span><span style="color: black;"> = </span><span style="color: gray;">r</span><span style="color: black;"> ;</span></div>
<div><span style="color: black;"> continue  ;</span></div>
<div><span style="color: black;"> }</span></div>
<div><span style="color: black;"> }while (true) ;</span></div>
<div><span style="color: black;">}</span></div>
<div><strong>算法时间复杂度:</strong></div>
<div>堆排序中heap算法的时间复杂度与堆所对应的完全二叉树的树高度log<sub>2</sub>n相关. 而  heapsort中对heap的调用数量级为n,所以堆排序的整个时间复杂度为O(nlog<sub>2</sub>n). 并且堆排序是不稳定的.</div>
<div>堆排序的时间,主要由建立初始堆和反复重建堆这两部分的时间开销构成,它们均是通过调用Heapify实现的.</div>
<div>堆排序的最坏时间复杂度为O(nlog(n)),堆排序的平均性能较接近于最坏性能.</div>
<div>由于建初始堆所需的比较次数较多,所以堆排序不适于记录数较少的文件.</div>
<div>堆排序是就地排序,辅助空间为O(1).</div>
<div>堆排序是不稳定的.</div>
<div><strong><span>3  交换排序</span></strong></div>
<div>交换排序主要是根据记录的关键字的大小,将记录交换来进行排序的. 交换排序的特点是:  将关键字值较大的记录向序列的后部移动,关键字较小的记录向前移动. 这里介绍两种交换排序方法,它们是冒泡排序和快速排序.</div>
<div><strong><span style="font-size: large;">3.1  冒泡排序</span></strong></div>
<div><strong>定义: </strong>将被排序的记录数组R[1...n]垂直排列,每个记录R[i]看作是重量为R[i].key的气泡.  根据轻气泡不能在重气泡之下的原则,从下往上扫描数组R: 凡扫描到违反本原则的轻气泡,就使其向上&#8221;飘浮&#8221;.  如此反复进行,直到最后任何两个气泡都是轻者在上,重者在下为止.</div>
<div><strong>算法思路:</strong></div>
<div>(1) 让j取n至2,将r[j].key与r[j-1].key比较,如果r[j].key &lt;  r[j-1].key,则把记录r[j]与r[j-1]交换位置,否则不进行交换.  最后是r[2].key与r[1].key对比,关键字较小的记录就换到r[1]的位置上,到此第一趟结束.  最小关键字的记录就象最轻的气泡冒到顶部一样换到了文件的前边.</div>
<div>(2) 让j取n至3,重复上述的比较对换操作,最终r[2]之中存放的是剩余n-1个记录(r[1]除外)中关键字最小的记录.</div>
<div>(3) 让j取n至i+1,经过一系列对联对比交换之后,r[i]之中是剩余若干记录中关键字最小的记录.</div>
<div>(4) 让j取n至n-1,将r[n].key与r[n-1].key对比,把关键字较小的记录交换到r[n-1]之中.</div>
<div><strong>例 </strong>设有一组关键字序列{55,22,44,11,33},这里n=5,即有5个记录.  请将其按由小到大的顺序排序.</div>
<div><strong>具体算法:</strong></div>
<div><span style="color: black;">template&lt;class </span><span style="color: blue;">Type</span><span style="color: black;">&gt; </span></div>
<div><span style="color: black;">BubbleSort(</span><span style="color: blue;">Type</span><span style="color: gray;">Array</span><span style="color: black;">[], int </span><span style="color: gray;">n</span><span style="color: black;">)</span></div>
<div><span style="color: black;">{</span></div>
<div><span style="color: black;"> int </span><span style="color: gray;">t</span><span style="color: black;"> = 1, </span><span style="color: gray;">tag</span><span style="color: black;">, </span><span style="color: gray;">j</span><span style="color: black;"> ;</span></div>
<div><span style="color: black;"> </span><span style="color: blue;">T</span><span style="color: gray;">x</span><span style="color: black;"> ; </span></div>
<div><span style="color: black;"> do</span></div>
<div><span style="color: black;"> {</span></div>
<div><span style="color: black;"> </span><span style="color: gray;">tag</span><span style="color: black;"> = 0 ;</span></div>
<div><span style="color: black;"> for(</span><span style="color: gray;">j</span><span style="color: black;"> = </span><span style="color: gray;">n</span><span style="color: black;"> ; </span><span style="color: gray;">j</span><span style="color: black;"> &gt;= </span><span style="color: gray;">i</span><span style="color: black;"> ; </span><span style="color: gray;">j</span><span style="color: black;"> &#8211;)</span></div>
<div><span style="color: black;"> if(r[</span><span style="color: gray;">j</span><span style="color: black;">].</span><span style="color: gray;">key</span><span style="color: black;"> &lt; r[</span><span style="color: gray;">j</span><span style="color: black;">-1].</span><span style="color: gray;">key</span><span style="color: black;">)</span></div>
<div><span style="color: black;"> {</span></div>
<div><span style="color: black;"> </span><span style="color: gray;">x</span><span style="color: black;"> =  r[</span><span style="color: gray;">j</span><span style="color: black;">]  ;</span></div>
<div><span style="color: black;"> r[</span><span style="color: gray;">j</span><span style="color: black;">] =  r[</span><span style="color: gray;">j</span><span style="color: black;">-1]  ;</span></div>
<div><span style="color: black;"> r[</span><span style="color: gray;">j</span><span style="color: black;">-1] = </span><span style="color: gray;">x</span><span style="color: black;"> ;</span></div>
<div><span style="color: black;"> </span><span style="color: gray;">tag</span><span style="color: black;"> = 1  ;</span></div>
<div><span style="color: black;"> } </span></div>
<div><span style="color: black;"> </span><span style="color: gray;">i</span><span style="color: black;"> ++ ;</span></div>
<div><span style="color: black;"> }while (</span><span style="color: gray;">tag</span><span style="color: black;"> == 1 &amp;&amp; </span><span style="color: gray;">i</span><span style="color: black;"> &lt;= </span><span style="color: gray;">n</span><span style="color: black;">)  ;</span></div>
<div><span style="color: black;">} </span><span style="color: #009900;">//  BubbleSort</span></div>
<div><strong>算法时间复杂度:</strong> 该算法的时间复杂度为O(n2).  但是,当原始关键字序列已有序时,只进行一趟比较就结束,此时时间复杂度为O(n).</div>
<div><strong><span style="font-size: large;">3.2  鸡尾酒排序(冒泡排序变形)</span></strong></div>
<div><strong><span style="font-size: large;">3.3  快速排序</span></strong></div>
<div><strong>定义:</strong> 快速排序由霍尔(Hoare)提出,它是一种对冒泡排序的改正. 由于其排序速度快,故称快速排序(Quick  Sort). 快速排序方法的实质是将一组关键字[K1,K2,…,Kn]进行分区交换排序.</div>
<div><strong>算法思路:</strong></div>
<div style="margin: 0cm 0cm 0pt 18pt; text-indent: -18pt;"><span>①<span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none;"> </span></span>以第一个关键字K1为控制字,将[K1,K2,…,Kn]分成两个子区,使左区所有关键字小于等于K1,右区所有关键字大于等于K1,最后控制字居两个子区中间的适当位置.  在子区内数据尚处于无序状态.</div>
<div style="margin: 0cm 0cm 0pt 18pt; text-indent: -18pt;"><span>②<span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none;"> </span></span>将右区首、尾指针(记录的下标号)保存入栈,对左区进行与第①步相类似的处理,又得到它的左子区和右子区,控制字居中.</div>
<div style="margin: 0cm 0cm 0pt 18pt; text-indent: -18pt;"><span>③<span style="font-family: 'Times New Roman'; font-style: normal; font-variant: normal; font-weight: normal; font-size: 7pt; line-height: normal; font-size-adjust: none; font-stretch: normal; -x-system-font: none;"> </span></span>后退栈对一个个右子区进行相类似的处理,直到栈空.</div>
<div>由以上三步可以看出:  快速排序算法总框架是进行多趟的分区处理,而对某一特定子区,则应把它看成又是一个待排序的文件,控制字总是取子区中第一个记录的关键字.  现在设计一个函数hoare,它仅对某一待排序文件进行左、右子区的划分,使控制字居中,再设计一个主体框架函数quicksort,在这里多次调用hoare函数以实现对整个文件的排序.</div>
<div><strong>快速排序算法分析:</strong></div>
<div>快速排序的非递归算法引用了辅助栈,它的深度为log(n).  假设每一次分区处理所得的两个子区长度相近,那么可入栈的子区长度分别为:  n/(2*1),n/(2*2),n/(2*3),n/(2*4),…,n/(2*k).又因为n/2k=1,所以 k= log<sub>2</sub>(n).  分母中2的指数恰好反映出需要入栈的子区个数,它就是 log<sub>2</sub>n,也即栈的深度.  在最坏情况下,比如原文件关键字已经有序,每次分区处理仅能得到一个子区. 可入的子区个数接近n,此时栈的最大深度为n.</div>
<div>快速排序主体算法时间运算量约O(log<sub>2</sub>n),划分子区函数运算量约O(n),所以总的时间复杂度为O(nlog<sub>2</sub>n),它显然优于冒泡排序O(n2).  可是算法的优势并不是绝对的. 试分析,当原文件关键字有序时,快速排序时间复杂度是O(n2),这种情况下快速排序不快. 而这种情况的冒泡排序是O(n),反而很快.  在原文件记录关键字无序时的多种排序方法中,快速排序被认为是最好的一种排序方法.</div>
<div><strong>例</strong> 试用[6,7,5(1),2,5(2),8]进行快速排序.</div>
<div>排序过程简述如下</div>
<div>6<span> 7     5(1) 2     5(2) 8 </span>初始状态</div>
<div>[5(2)<span> 7     5(1)]       6     [7    8]</span></div>
<div>[2]<span> 5(2) [5(1)]      6     7     [8]</span></div>
<div>[2<span> 5(2) 5(1) 6   7   8] </span>最后状态</div>
<div>从这个例子可以分析出快速排序法的稳定性问题,其中51和52表示两个关键字的值相同,都是5.  5(1)表示排序之前它位于5(2)的前面. 从结果中可以看出原先位于5(1)之后的5(2)在排序之后移到了5(1)的前面,所以说快速排序是不稳定的.</div>
<div><strong>具体算法:</strong></div>
<div><span style="color: black;">template &lt;class </span><span style="color: blue;">Type</span><span style="color: black;">&gt; </span></div>
<div><span style="color: black;">void __stdcall QuickSort(</span><span style="color: blue;">Type</span><span style="color: gray;">Array</span><span style="color: black;">[], int </span><span style="color: gray;">Num</span><span style="color: black;">, PFunCusomCompare </span><span style="color: gray;">pfCompare</span><span style="color: black;">, PFunCusomSwap </span><span style="color: gray;">pfSwap</span><span style="color: black;">)</span></div>
<div><span style="color: black;">{</span></div>
<div><span style="color: black;"> int </span><span style="color: gray;">left</span><span style="color: black;"> = 0 ;</span></div>
<div><span style="color: black;"> int </span><span style="color: gray;">right</span><span style="color: black;"> = </span><span style="color: gray;">Num</span><span style="color: black;">-1 ;</span></div>
<div><span style="color: black;"> do</span></div>
<div><span style="color: black;"> {</span></div>
<div><span style="color: black;"> int </span><span style="color: gray;">i</span><span style="color: black;"> = </span><span style="color: gray;">left</span><span style="color: black;"> , </span><span style="color: gray;">j</span><span style="color: black;"> = </span><span style="color: gray;">right</span><span style="color: black;"> ;</span></div>
<div><span style="color: black;"> </span><span style="color: blue;">Type</span><span style="color: gray;">MidData</span><span style="color: black;"> = </span><span style="color: gray;">Array</span><span style="color: black;">[(</span><span style="color: gray;">left</span><span style="color: black;">+</span><span style="color: gray;">right</span><span style="color: black;">)/2] ;</span></div>
<div><span style="color: black;"> do</span></div>
<div><span style="color: black;"> {</span></div>
<div><span style="color: black;"> while (fpCompare  (</span><span style="color: gray;">MidData</span><span style="color: black;">, </span><span style="color: gray;">Array</span><span style="color: black;">[</span><span style="color: gray;">i</span><span style="color: black;">]) &amp;&amp; </span><span style="color: gray;">i</span><span style="color: black;"> &lt; </span><span style="color: gray;">right</span><span style="color: black;">)</span></div>
<div><span style="color: black;"> {</span></div>
<div><span style="color: black;"> </span><span style="color: #009900;">// </span><span style="color: #009900;">从左扫描大于中值的数</span></div>
<div><span style="color: black;"> ++ </span><span style="color: gray;">i</span><span style="color: black;"> ;</span></div>
<div><span style="color: black;"> }</span></div>
<div><span style="color: black;"> while (fpCompare  (</span><span style="color: gray;">Array</span><span style="color: black;">[</span><span style="color: gray;">j</span><span style="color: black;">], </span><span style="color: gray;">MidData</span><span style="color: black;">) &amp;&amp; </span><span style="color: gray;">j</span><span style="color: black;"> &gt; </span><span style="color: gray;">left</span><span style="color: black;">)</span></div>
<div><span style="color: black;"> {</span></div>
<div><span style="color: black;"> </span><span style="color: #009900;">// </span><span style="color: #009900;">从右扫描大于中值的数</span></div>
<div><span style="color: black;"> &#8212; </span><span style="color: gray;">j</span><span style="color: black;"> ;</span></div>
<div><span style="color: black;"> }</span></div>
<div><span style="color: black;"> if (</span><span style="color: gray;">i</span><span style="color: black;"> &lt;= </span><span style="color: gray;">j</span><span style="color: black;">)</span></div>
<div><span style="color: black;"> { </span></div>
<div><span style="color: black;"> </span><span style="color: #880000;">pfSwap</span><span style="color: black;">(</span><span style="color: gray;">Array</span><span style="color: black;">[</span><span style="color: gray;">i</span><span style="color: black;">], </span><span style="color: gray;">Array</span><span style="color: black;">[</span><span style="color: gray;">j</span><span style="color: black;">]) ; </span><span style="color: #009900;">// </span><span style="color: #009900;">交换数据</span></div>
<div><span style="color: black;"> ++ </span><span style="color: gray;">i</span><span style="color: black;"> ;</span></div>
<div><span style="color: black;"> &#8212; </span><span style="color: gray;">j</span><span style="color: black;"> ;</span></div>
<div><span style="color: black;"> } </span></div>
<div><span style="color: black;"> }while (</span><span style="color: gray;">i</span><span style="color: black;"> &lt;= </span><span style="color: gray;">j</span><span style="color: black;">) ;</span><span style="color: #009900;">// </span><span style="color: #009900;">如果两边扫描的下标交错</span><span style="color: #009900;">,</span><span style="color: #009900;">就停止</span><span style="color: #009900;">(</span><span style="color: #009900;">完成一次</span><span style="color: #009900;">)</span></div>
<div><span style="color: black;"> if (</span><span style="color: gray;">left</span><span style="color: black;"> &lt; </span><span style="color: gray;">j</span><span style="color: black;">)</span></div>
<div><span style="color: black;"> {</span></div>
<div><span style="color: black;"> </span><span style="color: #009900;">// </span><span style="color: #009900;">当左边部分有值</span><span style="color: #009900;">(left&lt;j),</span><span style="color: #009900;">递归左半边</span></div>
<div><span style="color: black;"> </span><span style="color: gray;">left</span><span style="color: black;"> = </span><span style="color: gray;">left</span><span style="color: black;"> ;</span></div>
<div><span style="color: black;"> </span></div>
<div><span style="color: black;"> }</span></div>
<div><span style="color: black;"> if (</span><span style="color: gray;">right</span><span style="color: black;"> &gt; </span><span style="color: gray;">i</span><span style="color: black;">)</span></div>
<div><span style="color: black;"> {</span></div>
<div><span style="color: black;"> </span><span style="color: #009900;">//</span><span style="color: #009900;">当右边部分有值</span><span style="color: #009900;">(right&gt;i),</span><span style="color: #009900;">递归右半边</span></div>
<div><span style="color: black;"> </span><span style="color: gray;">left</span><span style="color: black;"> = </span><span style="color: gray;">i</span><span style="color: black;"> ;</span></div>
<div><span style="color: black;"> </span><span style="color: gray;">right</span><span style="color: black;"> = </span><span style="color: gray;">right</span><span style="color: black;"> ;</span></div>
<div><span style="color: black;"> }</span></div>
<div><span style="color: black;"> }while (</span><span style="color: gray;">left</span><span style="color: black;"> &lt;= </span><span style="color: gray;">right</span><span style="color: black;">) ;</span></div>
<div><span style="color: black;">}</span></div>
<div><strong><span>4  归并排序</span></strong></div>
<div><strong>定义: </strong>归并排序(Merge  Sort)是一类与插入排序、交换排序、选择排序不同的另一种排序方法.归并的含义是将两个或两个以上的有序表合并成一个新的有序表.  归并排序有多路归并排序、两路归并排序,可用于内排序,也可以用于外排序. 这里仅对内排序的两路归并方法进行讨论.</div>
<div><strong>两路归并排序算法思路:</strong></div>
<div>①. 把n个记录看成n个长度为l的有序子表 ;</div>
<div>②. 进行两两归并使记录关键字有序,得到n/2个长度为2的有序子表 ;</div>
<div>③. 重复第②步直到所有记录归并成一个长度为n的有序表为止 ;</div>
<div><strong>算法实现:</strong></div>
<div>此算法的实现不像图示那样简单,现分三步来讨论.  首先从宏观上分析,首先让子表表长L=1进行处理,不断地使L=2*L,进行子表处理,直到L&gt;=n为止,把这一过程写成一个主体框架函数mergesort.  然后对于某确定的子表表长L,将n个记录分成若干组子表,两两归并,这里显然要循环若干次,把这一步写成一个函数mergepass,可由mergesort调用.  最后再看每一组(一对)子表的归并,其原理是相同的,只是子表表长不同,换句话说,是子表的首记录号与尾记录号不同,把这个归并操作作为核心算法写成函数merge,由mergepass来调用.</div>
<div><strong>具体算法:</strong></div>
<div><span style="color: #009900;">// </span><span style="color: #009900;">归并操作</span></div>
<div><span style="color: black;">template &lt;class </span><span style="color: blue;">type</span><span style="color: black;">&gt; </span></div>
<div><span style="color: black;">static void Merge (</span><span style="color: blue;">type</span><span style="color: gray;">array</span><span style="color: black;">[], int </span><span style="color: gray;">p</span><span style="color: black;">, int </span><span style="color: gray;">q</span><span style="color: black;">, int </span><span style="color: gray;">r</span><span style="color: black;">)</span></div>
<div><span style="color: black;">{ </span></div>
<div><span style="color: black;"> int </span><span style="color: gray;">i</span><span style="color: black;"> , </span><span style="color: gray;">k</span><span style="color: black;"> ;</span></div>
<div><span style="color: black;"> int </span><span style="color: gray;">begin1</span><span style="color: black;"> , </span><span style="color: gray;">end1</span><span style="color: black;"> , </span><span style="color: gray;">begin2</span><span style="color: black;"> , </span><span style="color: gray;">end2</span><span style="color: black;"> ;</span></div>
<div><span style="color: black;"> int* </span><span style="color: gray;">temp</span><span style="color: black;"> = (int*)</span><span style="color: #880000;">malloc</span><span style="color: black;">((</span><span style="color: gray;">r</span><span style="color: black;">-</span><span style="color: gray;">p</span><span style="color: black;">)*sizeof(int))  ;</span></div>
<div><span style="color: black;"> </span><span style="color: gray;">begin1</span><span style="color: black;"> = </span><span style="color: gray;">p</span><span style="color: black;"> ;</span></div>
<div><span style="color: black;"> </span><span style="color: gray;">end1</span><span style="color: black;"> = </span><span style="color: gray;">q</span><span style="color: black;"> ;</span></div>
<div><span style="color: black;"> </span><span style="color: gray;">begin2</span><span style="color: black;"> = </span><span style="color: gray;">q</span><span style="color: black;">+1 ;</span></div>
<div><span style="color: black;"> </span><span style="color: gray;">end2</span><span style="color: black;"> = </span><span style="color: gray;">r</span><span style="color: black;"> ;</span></div>
<div><span style="color: black;"> </span><span style="color: gray;">k</span><span style="color: black;"> = 0 ;</span></div>
<div><span style="color: black;"> while (</span><span style="color: gray;">begin1</span><span style="color: black;"> &lt;= </span><span style="color: gray;">end1</span><span style="color: black;"> &amp;&amp; </span><span style="color: gray;">begin2</span><span style="color: black;"> &lt;= </span><span style="color: gray;">end2</span><span style="color: black;">)</span></div>
<div><span style="color: black;"> {</span></div>
<div><span style="color: black;"> if (</span><span style="color: gray;">array</span><span style="color: black;">[</span><span style="color: gray;">begin1</span><span style="color: black;">] &lt; </span><span style="color: gray;">array</span><span style="color: black;">[</span><span style="color: gray;">begin2</span><span style="color: black;">])</span></div>
<div><span style="color: black;"> {</span></div>
<div><span style="color: black;"> </span><span style="color: gray;">temp</span><span style="color: black;">[</span><span style="color: gray;">k</span><span style="color: black;">] = </span><span style="color: gray;">array</span><span style="color: black;">[</span><span style="color: gray;">begin1</span><span style="color: black;">] ;</span></div>
<div><span style="color: black;"> </span><span style="color: gray;">begin1</span><span style="color: black;"> ++ ;</span></div>
<div><span style="color: black;"> }</span></div>
<div><span style="color: black;"> else</span></div>
<div><span style="color: black;"> {</span></div>
<div><span style="color: black;"> </span><span style="color: gray;">temp</span><span style="color: black;">[</span><span style="color: gray;">k</span><span style="color: black;">] = </span><span style="color: gray;">array</span><span style="color: black;">[</span><span style="color: gray;">begin2</span><span style="color: black;">] ;</span></div>
<div><span style="color: black;"> </span><span style="color: gray;">begin2</span><span style="color: black;"> ++ ;</span></div>
<div><span style="color: black;"> }</span></div>
<div><span style="color: black;"> </span><span style="color: gray;">k</span><span style="color: black;"> ++ ;</span></div>
<div><span style="color: black;"> }</span></div>
<div><span style="color: black;"> while (</span><span style="color: gray;">begin1</span><span style="color: black;"> &lt; </span><span style="color: gray;">end1</span><span style="color: black;">)</span></div>
<div><span style="color: black;"> {</span></div>
<div><span style="color: black;"> </span><span style="color: gray;">temp</span><span style="color: black;">[</span><span style="color: gray;">k</span><span style="color: black;">++] = </span><span style="color: gray;">array</span><span style="color: black;">[</span><span style="color: gray;">begin1</span><span style="color: black;">++] ;</span></div>
<div><span style="color: black;"> }</span></div>
<div><span style="color: black;"> while (</span><span style="color: gray;">begin2</span><span style="color: black;"> &lt; </span><span style="color: gray;">end2</span><span style="color: black;">)</span></div>
<div><span style="color: black;"> {</span></div>
<div><span style="color: black;"> </span><span style="color: gray;">temp</span><span style="color: black;">[</span><span style="color: gray;">k</span><span style="color: black;">++] = </span><span style="color: gray;">array</span><span style="color: black;">[</span><span style="color: gray;">begin2</span><span style="color: black;">++] ;</span></div>
<div><span style="color: black;"> }</span></div>
<div><span style="color: black;"> for (</span><span style="color: gray;">i</span><span style="color: black;"> = 0 ; </span><span style="color: gray;">i</span><span style="color: black;"> &lt; (</span><span style="color: gray;">r</span><span style="color: black;">-</span><span style="color: gray;">p</span><span style="color: black;">) ; </span><span style="color: gray;">i</span><span style="color: black;"> ++)</span></div>
<div><span style="color: black;"> {</span></div>
<div><span style="color: black;"> </span><span style="color: gray;">array</span><span style="color: black;">[</span><span style="color: gray;">p</span><span style="color: black;">+</span><span style="color: gray;">i</span><span style="color: black;">] = </span><span style="color: gray;">temp</span><span style="color: black;"> ;</span></div>
<div><span style="color: black;"> }</span></div>
<div><span style="color: black;"> </span><span style="color: #880000;">free</span><span style="color: black;">(</span><span style="color: gray;">temp</span><span style="color: black;">) ;</span></div>
<div><span style="color: black;">}</span></div>
<div><span style="color: #009900;">//&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8212;&#8211; </span></div>
<div><span style="color: black;">template &lt;class </span><span style="color: blue;">type</span><span style="color: black;">&gt;</span></div>
<div><span style="color: black;">void MergeSort(</span><span style="color: blue;">type</span><span style="color: gray;">array</span><span style="color: black;">[], unsigned int </span><span style="color: gray;">first</span><span style="color: black;">, unsigned int </span><span style="color: gray;">last</span><span style="color: black;">)</span></div>
<div><span style="color: black;">{</span></div>
<div><span style="color: black;"> int </span><span style="color: gray;">mid</span><span style="color: black;"> = 0 ;</span></div>
<div><span style="color: black;"> if (</span><span style="color: gray;">first</span><span style="color: black;"> &lt; </span><span style="color: gray;">last</span><span style="color: black;">)</span></div>
<div><span style="color: black;"> {</span></div>
<div><span style="color: black;"> </span><span style="color: gray;">mid</span><span style="color: black;"> = (</span><span style="color: gray;">first</span><span style="color: black;">+</span><span style="color: gray;">last</span><span style="color: black;">)/2 ;</span></div>
<div><span style="color: black;"> MergeSort (</span><span style="color: gray;">array</span><span style="color: black;">, </span><span style="color: gray;">first</span><span style="color: black;">, </span><span style="color: gray;">mid</span><span style="color: black;">) ;</span></div>
<div><span style="color: black;"> MergeSort (</span><span style="color: gray;">array</span><span style="color: black;">, </span><span style="color: gray;">mid</span><span style="color: black;">+1, </span><span style="color: gray;">last</span><span style="color: black;">) ;</span></div>
<div><span style="color: black;"> Merge (</span><span style="color: gray;">array</span><span style="color: black;">, </span><span style="color: gray;">first</span><span style="color: black;">, </span><span style="color: gray;">mid</span><span style="color: black;">, </span><span style="color: gray;">last</span><span style="color: black;">) ;</span></div>
<div><span style="color: black;"> }</span></div>
<div><span style="color: black;">}</span></div>
<div><strong>算法分析:</strong></div>
<div>1. 稳定性,归并排序是一种稳定的排序.</div>
<div>2. 存储结构要求,可用顺序存储结构,也易于在链表上实现.</div>
<div>3.  时间复杂度,对长度为n的文件,需进行log(n)趟二路归并,每趟归并的时间为O(n),故其时间复杂度无论是在最好情况下还是在最坏情况下均是O(nlog(n)).</div>
<div>4.  空间复杂度,需要一个辅助向量来暂存两有序子文件归并的结果,故其辅助空间复杂度为O(n),显然它不是就地排序.</div>
<div>注意: 若用单链表做存储结构,很容易给出就地的归并排序.</div>
<div><strong><span>5  分配排序</span></strong></div>
<div>分配排序的基本思想: 排序过程无须比较关键字,而是通过&#8221;分配&#8221;和&#8221;收集&#8221;过程来实现排序.  它们的时间复杂度可达到线性阶: O(n).</div>
<div><strong><span style="font-size: large;">5.1桶排序</span></strong></div>
<div><span> </span>这里先介绍箱排序.</div>
<div><strong>箱排序的基本思想</strong><strong>:</strong></div>
<div>箱排序也称桶排序(Bucket Sort),其基本思想是:  设置若干个箱子,依次扫描待排序的记录R[0],R[1],…,R[n-1],把关键字等于k的记录全都装入到第k个箱子里(分配),然后按序号依次将各非空的箱子首尾连接起来(收集).</div>
<div><strong>例</strong>要将一副混洗的52张扑克牌按点数A&lt;2&lt;…&lt;J&lt;Q&lt;K排序,需设置13个&#8221;箱子&#8221;,排序时依次将每张牌按点数放入相应的箱子里,然后依次将这些箱子首尾相接,就得到了按点数递增序排列的一副牌.</div>
<div><strong>箱排序中</strong><strong>,</strong><strong>箱子的个数取决于关键字的取值范围</strong></div>
<div>若R[0..n-1]中关键字的取值范围是0到m-1的整数,则必须设置m个箱子.  因此箱排序要求关键字的类型是有限类型,否则可能要无限个箱子.</div>
<div><strong>箱子的类型应设计成链表为宜</strong></div>
<div>一般情况下每个箱子中存放多少个关键字相同的记录是无法预料的,故箱子的类型应设计成链表为宜.</div>
<div><strong>为保证排序是稳定的</strong><strong>,</strong><strong>分配过程中装箱及收集过程中的连接必须按先进先出原则进行</strong><strong>.</strong></div>
<div><span style="color: blue;">实现方法一</span></div>
<div>每个箱子设为一个链队列.  当一记录装入某箱子时,应做入队操作将其插入该箱子尾部,而收集过程则是对箱子做出队操作,依次将出队的记录放到输出序列中.</div>
<div><span style="color: blue;">实现方法二</span></div>
<div>若输入的待排序记录是以链表形式给出时,出队操作可简化为是将整个箱子链表链接到输出链表的尾部.  这只需要修改输出链表的尾结点中的指针域,令其指向箱子链表的头,然后修改输出链表的尾指针,令其指向箱子链表的尾即可.</div>
<div><strong>算法简析</strong></div>
<div>分配过程的时间是O(n),收集过程的时间为O(m),(采用链表来存储输入的待排序记录)或O(m+n).  因此,箱排序的时间为O(m+n). 若箱子个数m的数量级为O(n),则箱排序的时间是线性的,即O(n).</div>
<div>注意: 箱排序实用价值不大,仅适用于作为基数排序(下节介绍)的一个中间步骤.</div>
<div>箱排序的变种.  为了区别于上述的箱排序,姑且称它为桶排序(实际上箱排序和桶排序是同义词).</div>
<div><strong>桶排序基本思想</strong></div>
<div>桶排序的思想是把[0,1)划分为n个大小相同的子区间,每一子区间是一个桶.  然后将n个记录分配到各个桶中. 因为关键字序列是均匀分布在[0,1)上的,所以一般不会有很多个记录落入同一个桶中.  由于同一桶中的记录其关键字不尽相同,所以必须采用关键字比较的排序方法(通常用插入排序)对各个桶进行排序,然后依次将各非空桶中的记录连接(收集)起来即可.</div>
<div>注意: 这种排序思想基于以下假设:  假设输入的n个关键字序列是随机分布在区间[0,1)之上.若关键字序列的取值范围不是该区间,只要其取值均非负,我们总能将所有关键字除以某一合适的数,将关键字映射到该区间上.  但要保证映射后的关键字是均匀分布在[0,1)上的.</div>
<div><strong>桶排序算法</strong></div>
<div>伪代码算法为:</div>
<div>void BucketSon(R)</div>
<div>{</div>
<div>//对R[0..n-1]做桶排序,其中0 ≤ R[i].key &lt; 1 (0 ≤ i  &lt; n)</div>
<div>for(i = 0 ; i &lt; n ; i ++) // 分配过程</div>
<div style="margin: 0cm 0cm 0pt 21pt; text-indent: 21pt;">将R[i]插入到桶B[「<a href="http://fifid.com/search/n%28R%5Bi%5D.key%29?src=yb_qsal&amp;utm_source=yb_qsal&amp;utm_medium=link" target="_blank">n(R[i].key)</a>」]中 ; // 可插入表头上</div>
<div style="margin: 0cm 0cm 0pt 21pt;">for(i = 0 ; i &lt; n ; i ++) // 排序过程</div>
<div style="margin: 0cm 0cm 0pt 21pt; text-indent: 21pt;">当B[i]非空时用插人排序将B[i]中的记录排序  ;</div>
<div style="margin: 0cm 0cm 0pt 21pt;">for(i = 0 ; i &lt; n ; i ++) // 收集过程</div>
<div style="margin: 0cm 0cm 0pt 21pt; text-indent: 21pt;">若B[i]非空,则将B[i]中的记录依次输出到R中  ;</div>
<div>}</div>
<div><span style="color: red;">注意</span><span style="color: red;">: </span>实现时需设置一个指针向量B[0..n-1]来表示n个桶. 但因为任一记录R[i]的关键字满足:  0≤R[i].key&lt;1(0≤i≤n-1),所以必须将R[i].key映射到B的下标区间[0,n-1)上才能使R[i]装入某个桶中,这可通过「<a href="http://fifid.com/search/n%2A%28R%5Bi%5D.key%29?src=yb_qsal&amp;utm_source=yb_qsal&amp;utm_medium=link" target="_blank">n*(R[i].key)</a>」来实现.</div>
<div><strong>桶排序算法分析</strong></div>
<div>桶排序的平均时间复杂度是线性的,即O(n).  但最坏情况仍有可能是O(n<sup>2</sup>).</div>
<div>箱排序只适用于关键字取值范围较小的情况,否则所需箱子的数目m太多导致浪费存储空间和计算时间.</div>
<div><strong>例</strong>n=10,被排序的记录关键字k<sub>i</sub>取值范围是0到99之间的整数(36,5,16,98,95,47,32,36,48)时,要用100个箱子来做一趟箱排序.  (即若m=n<sup>2</sup>时,箱排序的时间O(m+n)=O(n<sup>2</sup>)).</div>
<div><strong><span style="font-size: large;">5.2  基数排序</span></strong></div>
<div>基数排序(Radix Sort)是对箱排序的改进和推广.</div>
<div><strong>单关键字和多关键字</strong></div>
<div>文件中任一记录R[i]的关键字均由d个分量构成.</div>
<div>若这d个分量中每个分量都是一个独立的关键字,则文件是多关键字的(如扑克牌有两个关键字:  点数和花色),否则文件是单关键字的,<span style="position: relative; top: 6pt;"> (0≤j&lt;d)</span>只不过是关键字中其中的一位(如字符串、十进制整数等).</div>
<div>多关键字中的每个关键字的取值范围一般不同. 如扑克牌的花色取值只有4种,而点数则有13种.  单关键字中的每位一般取值范围相同.</div>
<div><strong>基数</strong></div>
<div>设单关键字的每个分量的取值范围均是:  C<sub>0</sub>≤k<sub>j</sub>≤C<sub>rd-1</sub>(0≤j&lt;d), 可能的取值个数rd称为基数.</div>
<div>基数的选择和关键字的分解因关键字的类型而异:</div>
<div>(1)  若关键字是十进制整数,则按个、十等位进行分解,基数rd=10,C<sub>0</sub>=0,C<sub>9</sub>=9,d为最长整数的位数;</div>
<div>(2)  若关键字是小写的英文字符串,则rd=26,C<sub>o</sub>=&#8217;a',C<sub>25</sub>=&#8217;z',d为字符串的最大长度.</div>
<div><strong>基数排序的基本思想</strong></div>
<div>基数排序的基本思想是:  从低位到高位依次对K<sup>j</sup>(j=d-1,d-2,…,0)进行箱排序.  在d趟箱排序中,所需的箱子数就是基数rd,这就是&#8221;基数排序&#8221;名称的由来.</div>
<div><strong>算法分析</strong></div>
<div>若排序文件不是以数组R形式给出,而是以单链表形式给出(此时称为链式的基数排序),则可通过修改出队和人队函数使表示箱子的链队列无须分配结点空间,而使用原链表的结点空间.  入队出队操作亦无需移动记录而仅需修改指针. 虽然这样一来节省了一定的时间和空间,但算法要复杂得多,且时空复杂度就其数量级而言并未得到改观.</div>
<div>基数排序的时间是线性的(即O(n)).</div>
<div>基数排序所需的辅助存储空间为O(n+rd).</div>
<div>基数排序是稳定的.</div>
<div><strong><span style="font-size: large;">5.3  鸽巢排序</span></strong></div>
<div><strong><span>6  并行排序</span></strong></p>
<hr />
<p>© <a href="http://www.iwanna.cn">我想网</a> Akon 所有 , 2009. |
<a href="http://www.iwanna.cn/archives/2009/05/03/929/">永久链接</a> |
<a href="http://www.iwanna.cn/archives/2009/05/03/929/#comments">没有评论</a> |
提交到
<a rel="nofollow" target="_blank" href="http://www.google.com/reader/view/feed/http://www.iwanna.cn/archives/2009/05/03/929/">Google Reader</a>
<a rel="nofollow" target="_blank" href="http://www.xianguo.com/subscribe.php?url=http://www.iwanna.cn/archives/2009/05/03/929/">鲜果</a>
<a rel="nofollow" target="_blank" href="http://www.zhuaxia.com/add_channel.php?url=http://www.iwanna.cn/archives/2009/05/03/929/">抓虾</a>
<hr />
</p>
	标签：<a href="http://www.iwanna.cn/topics/develope/algorithm/" title="Algorithm" rel="tag nofollow">Algorithm</a>, <a href="http://www.iwanna.cn/tags/algorithm/" title="Algorithm" rel="tag nofollow">Algorithm</a><br />

	<h2 class="related_post">您可能会感兴趣的其他文章</h2>
	<ul class="st-related-posts">
	<li><a href="http://www.iwanna.cn/archives/2009/03/31/71/" title="递归－三角数字 (2009年03月31日)">递归－三角数字</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/06/08/3769/" title="用PHP数组对百万数据进行排重 (2010年06月8日)">用PHP数组对百万数据进行排重</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/07/21/4661/" title="浅谈递归过程以及递归的优化 (2010年07月21日)">浅谈递归过程以及递归的优化</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/07/23/4680/" title="检查素数的正则表达式 (2010年07月23日)">检查素数的正则表达式</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/03/31/69/" title="排序－选择 (2009年03月31日)">排序－选择</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/03/31/75/" title="排序－插入 (2009年03月31日)">排序－插入</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/03/31/73/" title="排序－冒泡 (2009年03月31日)">排序－冒泡</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/04/09/323/" title="全文检索中近义词、关联词的解决方案 (2009年04月9日)">全文检索中近义词、关联词的解决方案</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/07/23/4695/" title="一些重要的算法 (2010年07月23日)">一些重要的算法</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/07/13/4513/" title="一个显示排序过程的Python脚本 (2010年07月13日)">一个显示排序过程的Python脚本</a> </li>
</ul>


<p><small>Feed enhanced by <a href='http://planetozh.com/blog/my-projects/wordpress-plugin-better-feed-rss/'>Better Feed</a> from  <a href='http://planetozh.com/blog/'>Ozh</a></small></p>
]]></content:encoded>
			<wfw:commentRss>http://www.iwanna.cn/archives/2009/05/03/929/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>全文检索中近义词、关联词的解决方案</title>
		<link>http://www.iwanna.cn/archives/2009/04/09/323/</link>
		<comments>http://www.iwanna.cn/archives/2009/04/09/323/#comments</comments>
		<pubDate>Thu, 09 Apr 2009 04:22:41 +0000</pubDate>
		<dc:creator>seasun</dc:creator>
				<category><![CDATA[Algorithm]]></category>

		<guid isPermaLink="false">http://www.iwanna.cn/?p=323</guid>
		<description><![CDATA[一直想找到一个好的同义词解决方案，在百度和google查找，大家对于这个问题都只是寥寥数语，不愿讲清，我在javaeye搜此类信息也求不到,后来发了个提问贴也只有浏览数而无回复，不知道这是什么原因，无奈之下我只有自己研究。
因为没有其它的解决方案可以借鉴，以下纯为我个人的见解。
我认为所谓近义词、关联词检索不外乎以下三种形式：
1.类似google suggest,用户输入关键字后自动提示功能。
2.假如“奥运会”的关联词是“北京”，用户输入“奥运会”搜索时，将“奥运会”的搜索结果以及“北京”的搜索结果都搜出来。
3.用户输入“奥运会”搜索，只显示“奥运会”的结果，它的关联词在结果集的底端用“相关搜索”的形式提示给用户。
这三种方式中看似2和3是类似的，其实还是有些很大区别的,我个人认为在实际的应用中，第3种方式是最多见的。
先说说第1种方式
google suggest的在网上可以搜到完整的解决方案，跟我此前想的一样。
建一个用来存储关键字的表
例如：


Sql代码 


create table KEYS( 
 ITEM_ID varcha2(50) not null, 
 SEARCH_KEY varchar2(100), 
); 


create table  KEYS(
   ITEM_ID varcha2(50) not null,
   SEARCH_KEY varchar2(100),
);
SEARCH_KEY里存储一些检索的关键字，如“奥运”，“奥运会”，“北京奥运会”等.
当用户在文本框敲入时，使用AJAX将当前文本框的内容发到Action，进行下面类似的操作


Java代码 


String key = request.getParameter(&#8220;inputValue&#8221;); 
String sql = &#8220;select * from KEYS as k where k.SEARCH_KEY like &#8217;%key%&#8217;&#8221;; 


String key = request.getParameter("inputValue");
String sql = "select * from KEYS as k where k.SEARCH_KEY like '%key%'";
这个办法也就是把当前文本框中的字放到数据库中做模糊查询，比如用户输入“奥”这个字，会从搜出所有包含“奥”字的词，然后将这些词包装好，发回至页面，页面上用JS画出下拉框，将这些包含“奥”字的词填入就可以了。
google做的是右边匹配，即是用的 like &#8217;key%&#8217; ,输入“奥”字，会出现所有以“奥”字开头的词的提示。
大家应该注意到google suggest的提示词的最后面都写有“约XXXXX条记录”，我现在唯一能想到的解决方案是，当我们在Action中拿到匹配的词之后，将匹配的词搜索一次即可得出具体记录的条数，其实这样也不耗多少资源。
第2种方式
将关键词和关键词所联的词的结果都搜出来
我个人认为这个功能在实际的应用中只需用到其5%就可以了，因为在用户体验方面考虑，我们必须保障搜索结果的质量。关键词的近义词可以在结果页的底端提示给用户，也就是我上边说到的第3种方式。
我所说的只需用到5%的意思是只需为少数的、必须转义的词实现这样的功能
比如搜索“China”,那么“中国”这个词的结果肯定得出现在结果集里，还有比如搜索“08”，那么“2008”的结果也得出现在结果集里，这些都是一些特定情况，其它的词没必要做成这样，只需做提示即可。
现在中文检索一般都是基于词库的检索，实现第2种方式这个功能必须将之前的词库以及分词算法进行修改。
一般的方法是在词库中把同义词写成一行，如将“中国 China”写在同一行，然后修改Token算法（这个大家可以去研究一下，我现在使用的Analyzer包是公司商业上的伙伴提供的测试包，这个测试包已经可以满足很大一部分需求了，我还不知道能不能共享）
其实原理是在索引时将原词和原词的近义词一起索引
具体给大家个例子
有这样一句话  &#8212;- “中国是世界上人口最多的国家”
如果没有为其做同义词，大家可能会索引成这样
[中国][世界][人口][最多][国家]
如果做了同义词，会索引成
[中国][China][世界][人口][最多][国家]
即是说在索引时就已经将“中国”这个词存成[中国][China]了，搜索时无论搜“中国”或是“China”都可以搜到这句话。
其实这个功能相当大一部分是依赖第三方的jar包，说来说去也没多大意思，并且大多数情况下我们需要的并不同这种功能，而是更人性化的查询提示的功能，也就是第3种方式。
第3种方式
这种方式是我在原有的系统上改进完成的
原有的系统是 compass + paoding + lucene
由于我不太熟compass的搜索，所以我还是采用的lucene搜索。相信大家对这种搭配的全文检索已经非常熟悉了，paoding的词库是可以自己配置的。
那么怎样在原有的基础实现关键词提示功能呢？？？
我的做法是这样的，我按照paoding词库的特点新建了一个mydictionary.dic文件放在classpath下，里面的内容大致如下。
第1行：奥运会  [...]]]></description>
			<content:encoded><![CDATA[<p>一直想找到一个好的同义词解决方案，在百度和google查找，大家对于这个问题都只是寥寥数语，不愿讲清，我在javaeye搜此类信息也求不到,后来发了个提问贴也只有浏览数而无回复，不知道这是什么原因，无奈之下我只有自己研究。</p>
<p>因为没有其它的解决方案可以借鉴，以下纯为我个人的见解。<span id="more-323"></span></p>
<p><span><strong>我认为所谓近义词、关联词检索不外乎以下三种形式：</strong></span></p>
<p><span><strong>1.类似google suggest,用户输入关键字后自动提示功能。</strong></span></p>
<p><span><strong>2.假如“奥运会”的关联词是“北京”，用户输入“奥运会”搜索时，将“奥运会”的搜索结果以及“北京”的搜索结果都搜出来。</strong></span></p>
<p><span><strong>3.用户输入“奥运会”搜索，只显示“奥运会”的结果，它的关联词在结果集的底端用“相关搜索”的形式提示给用户。</strong></span></p>
<p>这三种方式中看似2和3是类似的，其实还是有些很大区别的,我个人认为在实际的应用中，第3种方式是最多见的。</p>
<p>先说说第1种方式</p>
<p>google suggest的在网上可以搜到完整的解决方案，跟我此前想的一样。</p>
<p>建一个用来存储关键字的表</p>
<p>例如：</p>
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Sql代码 <object width="14" height="15" data="http://www.javaeye.com/javascripts/syntaxhighlighter/clipboard_new.swf" type="application/x-shockwave-flash"><param name="flashvars" value="clipboard=create%20table%20%20KEYS(%20%20%20%20%0A%20%20%20ITEM_ID%20varcha2(50)%20not%20null%2C%20%20%20%20%0A%20%20%20SEARCH_KEY%20varchar2(100)%2C%20%20%20%20%20%20%20%20%0A)%3B%20%20" /><param name="src" value="http://www.javaeye.com/javascripts/syntaxhighlighter/clipboard_new.swf" /><param name="quality" value="high" /></object></div>
</div>
<ol class="dp-sql">
<li><span><span class="keyword">create</span><span> </span><span class="keyword">table</span><span> KEYS( </span></span></li>
<li><span> ITEM_ID varcha2(50) <span class="op">not</span><span> </span><span class="op">null</span><span>, </span></span></li>
<li><span> SEARCH_KEY varchar2(100), </span></li>
<li><span>); </span></li>
</ol>
</div>
<pre class="sql" style="display: none;">create table  KEYS(
   ITEM_ID varcha2(50) not null,
   SEARCH_KEY varchar2(100),
);</pre>
<p>SEARCH_KEY里存储一些检索的关键字，如“奥运”，“奥运会”，“北京奥运会”等.</p>
<p>当用户在文本框敲入时，使用AJAX将当前文本框的内容发到Action，进行下面类似的操作</p>
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <object width="14" height="15" data="http://www.javaeye.com/javascripts/syntaxhighlighter/clipboard_new.swf" type="application/x-shockwave-flash"><param name="flashvars" value="clipboard=String%20key%20%3D%20request.getParameter(%22inputValue%22)%3B%0AString%20sql%20%3D%20%22select%20*%20from%20KEYS%20as%20k%20where%20k.SEARCH_KEY%20like%20'%25key%25'%22%3B" /><param name="src" value="http://www.javaeye.com/javascripts/syntaxhighlighter/clipboard_new.swf" /><param name="quality" value="high" /></object></div>
</div>
<ol class="dp-j">
<li><span><span>String key = request.getParameter(</span><span class="string">&#8220;inputValue&#8221;</span><span>); </span></span></li>
<li><span>String sql = <span class="string">&#8220;select * from KEYS as k where k.SEARCH_KEY like &#8217;%key%&#8217;&#8221;</span><span>; </span></span></li>
</ol>
</div>
<pre class="java" style="display: none;">String key = request.getParameter("inputValue");
String sql = "select * from KEYS as k where k.SEARCH_KEY like '%key%'";</pre>
<p>这个办法也就是把当前文本框中的字放到数据库中做模糊查询，比如用户输入“奥”这个字，会从搜出所有包含“奥”字的词，然后将这些词包装好，发回至页面，页面上用JS画出下拉框，将这些包含“奥”字的词填入就可以了。</p>
<p>google做的是右边匹配，即是用的 like &#8217;key%&#8217; ,输入“奥”字，会出现所有以“奥”字开头的词的提示。</p>
<p>大家应该注意到google suggest的提示词的最后面都写有“约XXXXX条记录”，我现在唯一能想到的解决方案是，当我们在Action中拿到匹配的词之后，将匹配的词搜索一次即可得出具体记录的条数，其实这样也不耗多少资源。</p>
<p>第2种方式</p>
<p>将关键词和关键词所联的词的结果都搜出来</p>
<p>我个人认为这个功能在实际的应用中只需用到其5%就可以了，因为在用户体验方面考虑，我们必须保障搜索结果的质量。关键词的近义词可以在结果页的底端提示给用户，也就是我上边说到的第3种方式。</p>
<p>我所说的只需用到5%的意思是只需为少数的、必须转义的词实现这样的功能</p>
<p>比如搜索“China”,那么“中国”这个词的结果肯定得出现在结果集里，还有比如搜索“08”，那么“2008”的结果也得出现在结果集里，这些都是一些特定情况，其它的词没必要做成这样，只需做提示即可。</p>
<p>现在中文检索一般都是基于词库的检索，实现第2种方式这个功能必须将之前的词库以及分词算法进行修改。</p>
<p>一般的方法是在词库中把同义词写成一行，如将“中国 China”写在同一行，然后修改Token算法（这个大家可以去研究一下，我现在使用的Analyzer包是公司商业上的伙伴提供的测试包，这个测试包已经可以满足很大一部分需求了，我还不知道能不能共享）</p>
<p>其实原理是在索引时将原词和原词的近义词一起索引</p>
<p>具体给大家个例子</p>
<p>有这样一句话  &#8212;- “中国是世界上人口最多的国家”</p>
<p>如果没有为其做同义词，大家可能会索引成这样</p>
<p>[中国][世界][人口][最多][国家]</p>
<p>如果做了同义词，会索引成</p>
<p>[中国][China][世界][人口][最多][国家]</p>
<p>即是说在索引时就已经将“中国”这个词存成[中国][China]了，搜索时无论搜“中国”或是“China”都可以搜到这句话。</p>
<p>其实这个功能相当大一部分是依赖第三方的jar包，说来说去也没多大意思，并且大多数情况下我们需要的并不同这种功能，而是更人性化的查询提示的功能，也就是第3种方式。</p>
<p>第3种方式</p>
<p>这种方式是我在原有的系统上改进完成的</p>
<p>原有的系统是 compass + paoding + lucene</p>
<p>由于我不太熟compass的搜索，所以我还是采用的lucene搜索。相信大家对这种搭配的全文检索已经非常熟悉了，paoding的词库是可以自己配置的。</p>
<p>那么怎样在原有的基础实现关键词提示功能呢？？？</p>
<p>我的做法是这样的，我按照paoding词库的特点新建了一个mydictionary.dic文件放在classpath下，里面的内容大致如下。</p>
<p>第1行：奥运会  北京  2008  第29届奥运会</p>
<p>第2行：中国 China 中华人民共和国 中国电信 中国人民银行</p>
<p>&#8230;&#8230;..</p>
<p>然后在服务器启动时，将mydictionary.dic这个文件中的文字一行行读入，分别做索引</p>
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <object width="14" height="15" data="http://www.javaeye.com/javascripts/syntaxhighlighter/clipboard_new.swf" type="application/x-shockwave-flash"><param name="flashvars" value="clipboard=%20%20%20%20%09InputStream%20fi%20%3D%20this.getClass().getClassLoader().getResourceAsStream(%22mydictionary.dic%22)%3B%20%20%20%20%09%0A%20%20%20%20%09File%20indexDir%20%3D%20new%20File(%22d%3A%5C%5Ctong%22)%3B%0A%20%20%20%20%09Analyzer%20luceneAnalyzer%20%3D%20new%20StandardAnalyzer()%3B%20%20%20%20%0A%20%20%20%20%20%20%20%20%09IndexWriter%20indexWriter%20%3D%20new%20IndexWriter(indexDir%2C%20luceneAnalyzer%2Ctrue)%3B%20%20%20%20%09%0A%09BufferedReader%20reader%20%3D%20new%20BufferedReader(new%20InputStreamReader(fi%2C%20%22UTF-8%22))%3B%20%20%20%0A%09String%20line%20%3D%20new%20String()%3B%20%20%20%20%09%20%20%20%0A%09while%20((line%20%3D%20reader.readLine())%20!%3D%20null)%20%0A%09%7B%20%20%20%0A%09%09Document%20document%20%3D%20new%20Document()%3B%0A%09%09Field%20FieldName%20%3D%20new%20Field(%22line%22%2C%20line%2CField.Store.YES%2C%20Field.Index.TOKENIZED)%3B%0A%09%09document.add(FieldName)%3B%0A%09%09indexWriter.addDocument(document)%3B%0A%09%7D%20%20%20%0A%09indexWriter.optimize()%3B%0A%20%20%20%20%20%20%20%20%09indexWriter.close()%3B%0A%09reader.close()%3B%20%20%20%20" /><param name="src" value="http://www.javaeye.com/javascripts/syntaxhighlighter/clipboard_new.swf" /><param name="quality" value="high" /></object></div>
</div>
<ol class="dp-j">
<li><span><span> InputStream fi = </span><span class="keyword">this</span><span>.getClass().getClassLoader().getResourceAsStream(</span><span class="string">&#8220;mydictionary.dic&#8221;</span><span>); </span></span></li>
<li><span> File indexDir = <span class="keyword">new</span><span> File(</span><span class="string">&#8220;d:\\tong&#8221;</span><span>); </span></span></li>
<li><span> Analyzer luceneAnalyzer = <span class="keyword">new</span><span> StandardAnalyzer(); </span></span></li>
<li><span> IndexWriter indexWriter = <span class="keyword">new</span><span> IndexWriter(indexDir, luceneAnalyzer,</span><span class="keyword">true</span><span>); </span></span></li>
<li><span>BufferedReader reader = <span class="keyword">new</span><span> BufferedReader(</span><span class="keyword">new</span><span> InputStreamReader(fi, </span><span class="string">&#8220;UTF-8&#8243;</span><span>)); </span></span></li>
<li><span>String line = <span class="keyword">new</span><span> String(); </span></span></li>
<li><span><span class="keyword">while</span><span> ((line = reader.readLine()) != </span><span class="keyword">null</span><span>) </span></span></li>
<li><span>{ </span></li>
<li><span> Document document = <span class="keyword">new</span><span> Document(); </span></span></li>
<li><span> Field FieldName = <span class="keyword">new</span><span> Field(</span><span class="string">&#8220;line&#8221;</span><span>, line,Field.Store.YES, Field.Index.TOKENIZED); </span></span></li>
<li><span> document.add(FieldName); </span></li>
<li><span> indexWriter.addDocument(document); </span></li>
<li><span>} </span></li>
<li><span>indexWriter.optimize(); </span></li>
<li><span> indexWriter.close(); </span></li>
<li><span>reader.close(); </span></li>
</ol>
</div>
<pre class="java" style="display: none;">    	InputStream fi = this.getClass().getClassLoader().getResourceAsStream("mydictionary.dic");
    	File indexDir = new File("d:\\tong");
    	Analyzer luceneAnalyzer = new StandardAnalyzer();
        	IndexWriter indexWriter = new IndexWriter(indexDir, luceneAnalyzer,true);
	BufferedReader reader = new BufferedReader(new InputStreamReader(fi, "UTF-8"));
	String line = new String();
	while ((line = reader.readLine()) != null)
	{
		Document document = new Document();
		Field FieldName = new Field("line", line,Field.Store.YES, Field.Index.TOKENIZED);
		document.add(FieldName);
		indexWriter.addDocument(document);
	}
	indexWriter.optimize();
        	indexWriter.close();
	reader.close();</pre>
<p>在搜索时，对用户输入的关键字正常搜索出结果后，对关键字进行第二次搜索，搜的是同义词的索引，得到的结果按空格分开，即可得到所有同义词，然后将同义词发送至页面即可。</p>
<div class="dp-highlighter">
<div class="bar">
<div class="tools">Java代码 <object width="14" height="15" data="http://www.javaeye.com/javascripts/syntaxhighlighter/clipboard_new.swf" type="application/x-shockwave-flash"><param name="flashvars" value="clipboard=%09public%20List%20getTongYi(String%20searchword)%20throws%20Exception%0A%09%7B%0A%09%09List%20list%20%3D%20new%20ArrayList()%3B%0A%09%09Hits%20hits%20%3D%20null%3B%20%20%20%20%0A%09%09String%20queryString%20%3D%20searchword%3B%20%20%20%20%0A%09%09Query%20query%20%3D%20null%3B%20%20%20%20%0A%09%09String%20result%20%3D%20%22%22%3B%0A%09%09IndexSearcher%20searcher%20%3D%20new%20IndexSearcher(%22d%3A%5C%5Ctong%22)%3B%20%20%20%20%09%09%20%20%20%0A%09%09Analyzer%20analyzer%20%3D%20new%20StandardAnalyzer()%3B%20%20%20%20%0A%09%09QueryParser%20qp%20%3D%20new%20QueryParser(%22line%22%2C%20analyzer)%3B%20%20%20%20%0A%09%09query%20%3D%20qp.parse(queryString)%3B%20%20%20%20%09%20%20%20%20%20%20%20%20%0A%09%09if%20(searcher%20!%3D%20null)%0A%09%09%7B%20%20%20%20%0A%09%09%20%20%20%20hits%20%3D%20searcher.search(query)%3B%20%20%20%20%20%20%0A%09%09%20%20%20%20for(int%20i%3D0%3Bi%3Chits.length()%3Bi%2B%2B)%0A%09%09%20%20%20%20%7B%0A%09%09%20%20%20%20%09Document%20doc%20%3D%20hits.doc(i)%3B%0A%09%09%20%20%20%20%09System.out.println((i%2B1)%2B%22.%22%2Bdoc.get(%22line%22))%3B%0A%09%09%20%20%20%20%09result%20%3D%20doc.get(%22line%22)%3B%0A%09%09%20%20%20%20%7D%20%20%20%20%20%20%20%20%20%20%0A%09%09%7D%0A%09%09if(result!%3Dnull%20%26%26%20!result.equals(%22%22))%0A%09%09%7B%0A%09%09%09String%20%5B%5D%20manyresult%20%3D%20result.split(%22%20%22)%3B%0A%09%09%09for(int%20i%3D0%3Bi%3Cmanyresult.length%3Bi%2B%2B)%0A%09%09%09%7B%0A%09%09%09%09if(manyresult%5Bi%5D!%3Dnull%20%26%26%20!manyresult%5Bi%5D.trim().equals(%22%22))%0A%09%09%09%09%7B%0A%09%09%09%09%09list.add(manyresult%5Bi%5D)%3B%0A%09%09%09%09%7D%0A%09%09%09%7D%0A%09%09%7D%0A%09%09return%20list%3B%20%20%20%20%0A%09%7D%09" /><param name="src" value="http://www.javaeye.com/javascripts/syntaxhighlighter/clipboard_new.swf" /><param name="quality" value="high" /></object></div>
</div>
<ol class="dp-j">
<li><span><span class="keyword">public</span><span> List getTongYi(String searchword) </span><span class="keyword">throws</span><span> Exception </span></span></li>
<li><span>{ </span></li>
<li><span> List list = <span class="keyword">new</span><span> ArrayList(); </span></span></li>
<li><span> Hits hits = <span class="keyword">null</span><span>; </span></span></li>
<li><span> String queryString = searchword; </span></li>
<li><span> Query query = <span class="keyword">null</span><span>; </span></span></li>
<li><span> String result = <span class="string">&#8220;&#8221;</span><span>; </span></span></li>
<li><span> IndexSearcher searcher = <span class="keyword">new</span><span> IndexSearcher(</span><span class="string">&#8220;d:\\tong&#8221;</span><span>); </span></span></li>
<li><span> Analyzer analyzer = <span class="keyword">new</span><span> StandardAnalyzer(); </span></span></li>
<li><span> QueryParser qp = <span class="keyword">new</span><span> QueryParser(</span><span class="string">&#8220;line&#8221;</span><span>, analyzer); </span></span></li>
<li><span> query = qp.parse(queryString); </span></li>
<li><span> <span class="keyword">if</span><span> (searcher != </span><span class="keyword">null</span><span>) </span></span></li>
<li><span> { </span></li>
<li><span> hits = searcher.search(query); </span></li>
<li><span> <span class="keyword">for</span><span>(</span><span class="keyword">int</span><span> i=</span><span class="number">0</span><span>;i&lt;hits.length();i++) </span></span></li>
<li><span> { </span></li>
<li><span> Document doc = hits.doc(i); </span></li>
<li><span> System.out.println((i+<span class="number">1</span><span>)+</span><span class="string">&#8220;.&#8221;</span><span>+doc.get(</span><span class="string">&#8220;line&#8221;</span><span>)); </span></span></li>
<li><span> result = doc.get(<span class="string">&#8220;line&#8221;</span><span>); </span></span></li>
<li><span> } </span></li>
<li><span> } </span></li>
<li><span> <span class="keyword">if</span><span>(result!=</span><span class="keyword">null</span><span> &amp;&amp; !result.equals(</span><span class="string">&#8220;&#8221;</span><span>)) </span></span></li>
<li><span> { </span></li>
<li><span> String [] manyresult = result.split(<span class="string">&#8220; &#8221;</span><span>); </span></span></li>
<li><span> <span class="keyword">for</span><span>(</span><span class="keyword">int</span><span> i=</span><span class="number">0</span><span>;i&lt;manyresult.length;i++) </span></span></li>
<li><span> { </span></li>
<li><span> <span class="keyword">if</span><span>(manyresult[i]!=</span><span class="keyword">null</span><span> &amp;&amp; !manyresult[i].trim().equals(</span><span class="string">&#8220;&#8221;</span><span>)) </span></span></li>
<li><span> { </span></li>
<li><span> list.add(manyresult[i]); </span></li>
<li><span> } </span></li>
<li><span> } </span></li>
<li><span> } </span></li>
<li><span> <span class="keyword">return</span><span> list; </span></span></li>
<li><span>} </span></li>
</ol>
</div>
<pre class="java" style="display: none;">	public List getTongYi(String searchword) throws Exception
	{
		List list = new ArrayList();
		Hits hits = null;
		String queryString = searchword;
		Query query = null;
		String result = "";
		IndexSearcher searcher = new IndexSearcher("d:\\tong");
		Analyzer analyzer = new StandardAnalyzer();
		QueryParser qp = new QueryParser("line", analyzer);
		query = qp.parse(queryString);
		if (searcher != null)
		{
		    hits = searcher.search(query);
		    for(int i=0;i&lt;hits.length();i++)
		    {
		    	Document doc = hits.doc(i);
		    	System.out.println((i+1)+"."+doc.get("line"));
		    	result = doc.get("line");
		    }
		}
		if(result!=null &amp;&amp; !result.equals(""))
		{
			String [] manyresult = result.split(" ");
			for(int i=0;i&lt;manyresult.length;i++)
			{
				if(manyresult[i]!=null &amp;&amp; !manyresult[i].trim().equals(""))
				{
					list.add(manyresult[i]);
				}
			}
		}
		return list;
	}</pre>
<p>我觉得做同义词索引和搜索的时候最好用StandardAnalyzer，切成单字是最符合的。</p>
<hr />
<p>© <a href="http://www.iwanna.cn">我想网</a> Akon 所有 , 2009. |
<a href="http://www.iwanna.cn/archives/2009/04/09/323/">永久链接</a> |
<a href="http://www.iwanna.cn/archives/2009/04/09/323/#comments">没有评论</a> |
提交到
<a rel="nofollow" target="_blank" href="http://www.google.com/reader/view/feed/http://www.iwanna.cn/archives/2009/04/09/323/">Google Reader</a>
<a rel="nofollow" target="_blank" href="http://www.xianguo.com/subscribe.php?url=http://www.iwanna.cn/archives/2009/04/09/323/">鲜果</a>
<a rel="nofollow" target="_blank" href="http://www.zhuaxia.com/add_channel.php?url=http://www.iwanna.cn/archives/2009/04/09/323/">抓虾</a>
<hr />
</p>
	标签：<a href="http://www.iwanna.cn/topics/develope/algorithm/" title="Algorithm" rel="tag nofollow">Algorithm</a>, <a href="http://www.iwanna.cn/tags/algorithm/" title="Algorithm" rel="tag nofollow">Algorithm</a><br />

	<h2 class="related_post">您可能会感兴趣的其他文章</h2>
	<ul class="st-related-posts">
	<li><a href="http://www.iwanna.cn/archives/2009/03/31/71/" title="递归－三角数字 (2009年03月31日)">递归－三角数字</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/06/08/3769/" title="用PHP数组对百万数据进行排重 (2010年06月8日)">用PHP数组对百万数据进行排重</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/07/21/4661/" title="浅谈递归过程以及递归的优化 (2010年07月21日)">浅谈递归过程以及递归的优化</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/07/23/4680/" title="检查素数的正则表达式 (2010年07月23日)">检查素数的正则表达式</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/03/31/69/" title="排序－选择 (2009年03月31日)">排序－选择</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/03/31/75/" title="排序－插入 (2009年03月31日)">排序－插入</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/03/31/73/" title="排序－冒泡 (2009年03月31日)">排序－冒泡</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/05/03/929/" title="排序算法汇总 (2009年05月3日)">排序算法汇总</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/07/23/4695/" title="一些重要的算法 (2010年07月23日)">一些重要的算法</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/07/13/4513/" title="一个显示排序过程的Python脚本 (2010年07月13日)">一个显示排序过程的Python脚本</a> </li>
</ul>


<p><small>Feed enhanced by <a href='http://planetozh.com/blog/my-projects/wordpress-plugin-better-feed-rss/'>Better Feed</a> from  <a href='http://planetozh.com/blog/'>Ozh</a></small></p>
]]></content:encoded>
			<wfw:commentRss>http://www.iwanna.cn/archives/2009/04/09/323/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>排序－插入</title>
		<link>http://www.iwanna.cn/archives/2009/03/31/75/</link>
		<comments>http://www.iwanna.cn/archives/2009/03/31/75/#comments</comments>
		<pubDate>Tue, 31 Mar 2009 14:49:59 +0000</pubDate>
		<dc:creator>seasun</dc:creator>
				<category><![CDATA[Algorithm]]></category>

		<guid isPermaLink="false">http://www.iwanna.cn/?p=75</guid>
		<description><![CDATA[插入排序算法比冒泡 和选择 略微复杂些，但效率好些。
插入排序总是假设指定位置的左边的数组是有序的，而后将指定位置的值插入左边的有序数组。
指定的位置从下标1开始，每次循环递增1，直到数组结束。
插入排序的比较次数与交换次数的时间效率均为O(n^2)，确切的说是O(n^2 / 4)，比冒泡排序快一倍。
对于一个基本有序数组，由于内循环基本都是空循环，插入排序的效率接近O(n)，但对于完全逆序数组，插入排序的效率与冒泡相同。因此插入排序对于 基本有序，或反复排序的数组比较有利，实是上插入排序常常用于其他排序的首尾工作，其他排序只要排到基本有序即可，比如快速排序。
下面是代码。
class Insert {
public static void main(String[] args) {
int[] a = {1,5,3,8,4,3,8};
sort(a);
print(a);
}
private static void sort(int[] a) {
int temp;
for(int i=1; i&#60;a.length; i++) {
int pos = i;        //确定位置，在此位置左边的数组是有序的。
temp = a[i];         //根据位置确定要插入的数值。
while(pos&#62;0 &#38;&#38; a[pos-1]&#62;temp) {   //选择第一个不大于要插入数值的的位置
a[pos] = a[pos - 1];   //将数据以此向后移动
pos&#8211;;
}
a[pos] = temp;   //将指定数值插入恰当位置
}
}
private static void print(int[] a) {
for(int i: a) System.out.print(i + &#8221; [...]]]></description>
			<content:encoded><![CDATA[<p>插入排序算法比<a href="http://shenyu.javaeye.com/blog/187776">冒泡</a> 和<a href="http://shenyu.javaeye.com/blog/187305">选择</a> 略微复杂些，但效率好些。</p>
<p>插入排序总是假设指定位置的左边的数组是有序的，而后将指定位置的值插入左边的有序数组。</p>
<p>指定的位置从下标1开始，每次循环递增1，直到数组结束。</p>
<p>插入排序的比较次数与交换次数的时间效率均为O(n^2)，确切的说是O(n^2 / 4)，比冒泡排序快一倍。</p>
<p>对于一个基本有序数组，由于内循环基本都是空循环，插入排序的效率接近O(n)，但对于完全逆序数组，插入排序的效率与冒泡相同。因此插入排序对于 基本有序，或反复排序的数组比较有利，实是上插入排序常常用于其他排序的首尾工作，其他排序只要排到基本有序即可，比如快速排序。</p>
<p>下面是代码。</p>
<p>class Insert {<br />
public static void main(String[] args) {<br />
int[] a = {1,5,3,8,4,3,8};<br />
sort(a);<br />
print(a);<br />
}</p>
<p>private static void sort(int[] a) {<br />
int temp;<br />
for(int i=1; i&lt;a.length; i++) {<br />
int pos = i;        //确定位置，在此位置左边的数组是有序的。<br />
temp = a[i];         //根据位置确定要插入的数值。<br />
while(pos&gt;0 &amp;&amp; a[pos-1]&gt;temp) {   //选择第一个不大于要插入数值的的位置<br />
a[pos] = a[pos - 1];   //将数据以此向后移动<br />
pos&#8211;;<br />
}<br />
a[pos] = temp;   //将指定数值插入恰当位置<br />
}<br />
}</p>
<p>private static void print(int[] a) {<br />
for(int i: a) System.out.print(i + &#8221; &#8220;);<br />
System.out.println();<br />
}<br />
}</p>
<hr />
<p>© <a href="http://www.iwanna.cn">我想网</a> Akon 所有 , 2009. |
<a href="http://www.iwanna.cn/archives/2009/03/31/75/">永久链接</a> |
<a href="http://www.iwanna.cn/archives/2009/03/31/75/#comments">没有评论</a> |
提交到
<a rel="nofollow" target="_blank" href="http://www.google.com/reader/view/feed/http://www.iwanna.cn/archives/2009/03/31/75/">Google Reader</a>
<a rel="nofollow" target="_blank" href="http://www.xianguo.com/subscribe.php?url=http://www.iwanna.cn/archives/2009/03/31/75/">鲜果</a>
<a rel="nofollow" target="_blank" href="http://www.zhuaxia.com/add_channel.php?url=http://www.iwanna.cn/archives/2009/03/31/75/">抓虾</a>
<hr />
</p>
	标签：<a href="http://www.iwanna.cn/topics/develope/algorithm/" title="Algorithm" rel="tag nofollow">Algorithm</a>, <a href="http://www.iwanna.cn/tags/algorithm/" title="Algorithm" rel="tag nofollow">Algorithm</a><br />

	<h2 class="related_post">您可能会感兴趣的其他文章</h2>
	<ul class="st-related-posts">
	<li><a href="http://www.iwanna.cn/archives/2009/03/31/71/" title="递归－三角数字 (2009年03月31日)">递归－三角数字</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/06/08/3769/" title="用PHP数组对百万数据进行排重 (2010年06月8日)">用PHP数组对百万数据进行排重</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/07/21/4661/" title="浅谈递归过程以及递归的优化 (2010年07月21日)">浅谈递归过程以及递归的优化</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/07/23/4680/" title="检查素数的正则表达式 (2010年07月23日)">检查素数的正则表达式</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/03/31/69/" title="排序－选择 (2009年03月31日)">排序－选择</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/03/31/73/" title="排序－冒泡 (2009年03月31日)">排序－冒泡</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/05/03/929/" title="排序算法汇总 (2009年05月3日)">排序算法汇总</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/04/09/323/" title="全文检索中近义词、关联词的解决方案 (2009年04月9日)">全文检索中近义词、关联词的解决方案</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/07/23/4695/" title="一些重要的算法 (2010年07月23日)">一些重要的算法</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/07/13/4513/" title="一个显示排序过程的Python脚本 (2010年07月13日)">一个显示排序过程的Python脚本</a> </li>
</ul>


<p><small>Feed enhanced by <a href='http://planetozh.com/blog/my-projects/wordpress-plugin-better-feed-rss/'>Better Feed</a> from  <a href='http://planetozh.com/blog/'>Ozh</a></small></p>
]]></content:encoded>
			<wfw:commentRss>http://www.iwanna.cn/archives/2009/03/31/75/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>排序－冒泡</title>
		<link>http://www.iwanna.cn/archives/2009/03/31/73/</link>
		<comments>http://www.iwanna.cn/archives/2009/03/31/73/#comments</comments>
		<pubDate>Tue, 31 Mar 2009 14:49:18 +0000</pubDate>
		<dc:creator>seasun</dc:creator>
				<category><![CDATA[Algorithm]]></category>

		<guid isPermaLink="false">http://www.iwanna.cn/?p=73</guid>
		<description><![CDATA[冒泡排序的算法此处不在叙述。冒泡排序比较与交换的时间效率都是O(n^2)。
下面提供冒泡排序的Java代码。代码足够简单，没有加注释。
class Bubble {
public static void main(String[] args) {
int[] a = {6,3,2,6,3,2,9,7};
sort(a);
print(a);
}
private static void print(int [] a) {
for(int i: a) System.out.print(i + &#8221; &#8220;);
System.out.println();
}
private static void sort(int[] a) {
int temp;
for(int i=a.length-1; i&#62;0; i&#8211;) {
for(int j=0; j&#60;i; j++) {
if(a[j] &#62; a[j+1]) {
temp = a[j];
a[j] = a[j+1];
a[j+1] = temp;
}
}
}
}
}

© 我想网 Akon 所有 , 2009. &#124;
永久链接 &#124;
没有评论 &#124;
提交到
Google Reader
鲜果
抓虾


	标签：Algorithm, [...]]]></description>
			<content:encoded><![CDATA[<p>冒泡排序的算法此处不在叙述。冒泡排序比较与交换的时间效率都是O(n^2)。</p>
<p>下面提供冒泡排序的Java代码。代码足够简单，没有加注释。</p>
<p>class Bubble {<br />
public static void main(String[] args) {<br />
int[] a = {6,3,2,6,3,2,9,7};<br />
sort(a);<br />
print(a);<br />
}</p>
<p>private static void print(int [] a) {<br />
for(int i: a) System.out.print(i + &#8221; &#8220;);<br />
System.out.println();<br />
}</p>
<p>private static void sort(int[] a) {<br />
int temp;<br />
for(int i=a.length-1; i&gt;0; i&#8211;) {<br />
for(int j=0; j&lt;i; j++) {<br />
if(a[j] &gt; a[j+1]) {<br />
temp = a[j];<br />
a[j] = a[j+1];<br />
a[j+1] = temp;<br />
}<br />
}<br />
}<br />
}<br />
}</p>
<hr />
<p>© <a href="http://www.iwanna.cn">我想网</a> Akon 所有 , 2009. |
<a href="http://www.iwanna.cn/archives/2009/03/31/73/">永久链接</a> |
<a href="http://www.iwanna.cn/archives/2009/03/31/73/#comments">没有评论</a> |
提交到
<a rel="nofollow" target="_blank" href="http://www.google.com/reader/view/feed/http://www.iwanna.cn/archives/2009/03/31/73/">Google Reader</a>
<a rel="nofollow" target="_blank" href="http://www.xianguo.com/subscribe.php?url=http://www.iwanna.cn/archives/2009/03/31/73/">鲜果</a>
<a rel="nofollow" target="_blank" href="http://www.zhuaxia.com/add_channel.php?url=http://www.iwanna.cn/archives/2009/03/31/73/">抓虾</a>
<hr />
</p>
	标签：<a href="http://www.iwanna.cn/topics/develope/algorithm/" title="Algorithm" rel="tag nofollow">Algorithm</a>, <a href="http://www.iwanna.cn/tags/algorithm/" title="Algorithm" rel="tag nofollow">Algorithm</a><br />

	<h2 class="related_post">您可能会感兴趣的其他文章</h2>
	<ul class="st-related-posts">
	<li><a href="http://www.iwanna.cn/archives/2009/03/31/71/" title="递归－三角数字 (2009年03月31日)">递归－三角数字</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/06/08/3769/" title="用PHP数组对百万数据进行排重 (2010年06月8日)">用PHP数组对百万数据进行排重</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/07/21/4661/" title="浅谈递归过程以及递归的优化 (2010年07月21日)">浅谈递归过程以及递归的优化</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/07/23/4680/" title="检查素数的正则表达式 (2010年07月23日)">检查素数的正则表达式</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/03/31/69/" title="排序－选择 (2009年03月31日)">排序－选择</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/03/31/75/" title="排序－插入 (2009年03月31日)">排序－插入</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/05/03/929/" title="排序算法汇总 (2009年05月3日)">排序算法汇总</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/04/09/323/" title="全文检索中近义词、关联词的解决方案 (2009年04月9日)">全文检索中近义词、关联词的解决方案</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/07/23/4695/" title="一些重要的算法 (2010年07月23日)">一些重要的算法</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/07/13/4513/" title="一个显示排序过程的Python脚本 (2010年07月13日)">一个显示排序过程的Python脚本</a> </li>
</ul>


<p><small>Feed enhanced by <a href='http://planetozh.com/blog/my-projects/wordpress-plugin-better-feed-rss/'>Better Feed</a> from  <a href='http://planetozh.com/blog/'>Ozh</a></small></p>
]]></content:encoded>
			<wfw:commentRss>http://www.iwanna.cn/archives/2009/03/31/73/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>递归－三角数字</title>
		<link>http://www.iwanna.cn/archives/2009/03/31/71/</link>
		<comments>http://www.iwanna.cn/archives/2009/03/31/71/#comments</comments>
		<pubDate>Tue, 31 Mar 2009 14:48:45 +0000</pubDate>
		<dc:creator>seasun</dc:creator>
				<category><![CDATA[Algorithm]]></category>

		<guid isPermaLink="false">http://www.iwanna.cn/?p=71</guid>
		<description><![CDATA[
三角数字是这样一组数字：1 3 6 10 15 21 28 36 45&#8230;&#8230;
其中第n个数字等于n-1个数字的值加上n。
此处用递归算法求三角数字。（要求得该数字不一定要使用递归，迭代来的效率更高一些）
下面是代码：
class Triangle {
public static void main(String[] args) {
for(int i=1; i&#60;10; i++) System.out.print(getNext(i) + &#8221; &#8220;);
System.out.println();
}
private static int getNext(int n) {
if(n == 1) return 1;
return n + getNext(n-1);
}
}

© 我想网 Akon 所有 , 2009. &#124;
永久链接 &#124;
没有评论 &#124;
提交到
Google Reader
鲜果
抓虾


	标签：Algorithm, Algorithm

	您可能会感兴趣的其他文章
	
	用PHP数组对百万数据进行排重 
	浅谈递归过程以及递归的优化 
	检查素数的正则表达式 
	排序－选择 
	排序－插入 
	排序－冒泡 
	排序算法汇总 
	全文检索中近义词、关联词的解决方案 
	一些重要的算法 
	一个显示排序过程的Python脚本 



Feed [...]]]></description>
			<content:encoded><![CDATA[<div class="blog_content">
<p>三角数字是这样一组数字：1 3 6 10 15 21 28 36 45&#8230;&#8230;</p>
<p>其中第n个数字等于n-1个数字的值加上n。</p>
<p>此处用递归算法求三角数字。（要求得该数字不一定要使用递归，迭代来的效率更高一些）</p>
<p>下面是代码：</p>
<p>class Triangle {<br />
public static void main(String[] args) {<br />
for(int i=1; i&lt;10; i++) System.out.print(getNext(i) + &#8221; &#8220;);<br />
System.out.println();<br />
}</p>
<p>private static int getNext(int n) {<br />
if(n == 1) return 1;<br />
return n + getNext(n-1);<br />
}<br />
}</p></div>
<hr />
<p>© <a href="http://www.iwanna.cn">我想网</a> Akon 所有 , 2009. |
<a href="http://www.iwanna.cn/archives/2009/03/31/71/">永久链接</a> |
<a href="http://www.iwanna.cn/archives/2009/03/31/71/#comments">没有评论</a> |
提交到
<a rel="nofollow" target="_blank" href="http://www.google.com/reader/view/feed/http://www.iwanna.cn/archives/2009/03/31/71/">Google Reader</a>
<a rel="nofollow" target="_blank" href="http://www.xianguo.com/subscribe.php?url=http://www.iwanna.cn/archives/2009/03/31/71/">鲜果</a>
<a rel="nofollow" target="_blank" href="http://www.zhuaxia.com/add_channel.php?url=http://www.iwanna.cn/archives/2009/03/31/71/">抓虾</a>
<hr />
</p>
	标签：<a href="http://www.iwanna.cn/topics/develope/algorithm/" title="Algorithm" rel="tag nofollow">Algorithm</a>, <a href="http://www.iwanna.cn/tags/algorithm/" title="Algorithm" rel="tag nofollow">Algorithm</a><br />

	<h2 class="related_post">您可能会感兴趣的其他文章</h2>
	<ul class="st-related-posts">
	<li><a href="http://www.iwanna.cn/archives/2010/06/08/3769/" title="用PHP数组对百万数据进行排重 (2010年06月8日)">用PHP数组对百万数据进行排重</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/07/21/4661/" title="浅谈递归过程以及递归的优化 (2010年07月21日)">浅谈递归过程以及递归的优化</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/07/23/4680/" title="检查素数的正则表达式 (2010年07月23日)">检查素数的正则表达式</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/03/31/69/" title="排序－选择 (2009年03月31日)">排序－选择</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/03/31/75/" title="排序－插入 (2009年03月31日)">排序－插入</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/03/31/73/" title="排序－冒泡 (2009年03月31日)">排序－冒泡</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/05/03/929/" title="排序算法汇总 (2009年05月3日)">排序算法汇总</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/04/09/323/" title="全文检索中近义词、关联词的解决方案 (2009年04月9日)">全文检索中近义词、关联词的解决方案</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/07/23/4695/" title="一些重要的算法 (2010年07月23日)">一些重要的算法</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/07/13/4513/" title="一个显示排序过程的Python脚本 (2010年07月13日)">一个显示排序过程的Python脚本</a> </li>
</ul>


<p><small>Feed enhanced by <a href='http://planetozh.com/blog/my-projects/wordpress-plugin-better-feed-rss/'>Better Feed</a> from  <a href='http://planetozh.com/blog/'>Ozh</a></small></p>
]]></content:encoded>
			<wfw:commentRss>http://www.iwanna.cn/archives/2009/03/31/71/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>排序－选择</title>
		<link>http://www.iwanna.cn/archives/2009/03/31/69/</link>
		<comments>http://www.iwanna.cn/archives/2009/03/31/69/#comments</comments>
		<pubDate>Tue, 31 Mar 2009 14:48:04 +0000</pubDate>
		<dc:creator>seasun</dc:creator>
				<category><![CDATA[Algorithm]]></category>

		<guid isPermaLink="false">http://www.iwanna.cn/?p=69</guid>
		<description><![CDATA[选择排序 ，原理与冒泡 类似，相比之下，交换的时间效率为O(n)，比较的时间效率依然为O(n^2)
代码如下，程序简单，没有提供注释。
class Select {
public static void main(String[] args) {
int[] a = {2,4,6,3,6,2,6,4,9};
sort(a);
print(a);
}
private static void sort(int[] a) {
int temp;
for(int i=0; i&#60;a.length-1; i++) {
int min = i;
for(int j=i+1; j&#60;a.length; j++) {
if(a[j] &#60; a[min]) min = j;
}
if(min != i) {
temp = a[min];
a[min] = a[i];
a[i] = temp;
}
}
}
private static void print(int[] a) {
for(int i: a) System.out.print(i + &#8221; &#8220;);
System.out.println();
}
}

© [...]]]></description>
			<content:encoded><![CDATA[<p>选择排序 ，原理与<a href="http://shenyu.javaeye.com/blog/187776">冒泡</a> 类似，相比之下，交换的时间效率为O(n)，比较的时间效率依然为O(n^2)</p>
<p>代码如下，程序简单，没有提供注释。</p>
<p>class Select {<br />
public static void main(String[] args) {<br />
int[] a = {2,4,6,3,6,2,6,4,9};<br />
sort(a);<br />
print(a);<br />
}</p>
<p>private static void sort(int[] a) {<br />
int temp;<br />
for(int i=0; i&lt;a.length-1; i++) {<br />
int min = i;<br />
for(int j=i+1; j&lt;a.length; j++) {<br />
if(a[j] &lt; a[min]) min = j;<br />
}<br />
if(min != i) {<br />
temp = a[min];<br />
a[min] = a[i];<br />
a[i] = temp;<br />
}<br />
}<br />
}</p>
<p>private static void print(int[] a) {<br />
for(int i: a) System.out.print(i + &#8221; &#8220;);<br />
System.out.println();<br />
}<br />
}</p>
<hr />
<p>© <a href="http://www.iwanna.cn">我想网</a> Akon 所有 , 2009. |
<a href="http://www.iwanna.cn/archives/2009/03/31/69/">永久链接</a> |
<a href="http://www.iwanna.cn/archives/2009/03/31/69/#comments">没有评论</a> |
提交到
<a rel="nofollow" target="_blank" href="http://www.google.com/reader/view/feed/http://www.iwanna.cn/archives/2009/03/31/69/">Google Reader</a>
<a rel="nofollow" target="_blank" href="http://www.xianguo.com/subscribe.php?url=http://www.iwanna.cn/archives/2009/03/31/69/">鲜果</a>
<a rel="nofollow" target="_blank" href="http://www.zhuaxia.com/add_channel.php?url=http://www.iwanna.cn/archives/2009/03/31/69/">抓虾</a>
<hr />
</p>
	标签：<a href="http://www.iwanna.cn/topics/develope/algorithm/" title="Algorithm" rel="tag nofollow">Algorithm</a>, <a href="http://www.iwanna.cn/tags/algorithm/" title="Algorithm" rel="tag nofollow">Algorithm</a><br />

	<h2 class="related_post">您可能会感兴趣的其他文章</h2>
	<ul class="st-related-posts">
	<li><a href="http://www.iwanna.cn/archives/2009/03/31/71/" title="递归－三角数字 (2009年03月31日)">递归－三角数字</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/06/08/3769/" title="用PHP数组对百万数据进行排重 (2010年06月8日)">用PHP数组对百万数据进行排重</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/07/21/4661/" title="浅谈递归过程以及递归的优化 (2010年07月21日)">浅谈递归过程以及递归的优化</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/07/23/4680/" title="检查素数的正则表达式 (2010年07月23日)">检查素数的正则表达式</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/03/31/75/" title="排序－插入 (2009年03月31日)">排序－插入</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/03/31/73/" title="排序－冒泡 (2009年03月31日)">排序－冒泡</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/05/03/929/" title="排序算法汇总 (2009年05月3日)">排序算法汇总</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/04/09/323/" title="全文检索中近义词、关联词的解决方案 (2009年04月9日)">全文检索中近义词、关联词的解决方案</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/07/23/4695/" title="一些重要的算法 (2010年07月23日)">一些重要的算法</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/07/13/4513/" title="一个显示排序过程的Python脚本 (2010年07月13日)">一个显示排序过程的Python脚本</a> </li>
</ul>


<p><small>Feed enhanced by <a href='http://planetozh.com/blog/my-projects/wordpress-plugin-better-feed-rss/'>Better Feed</a> from  <a href='http://planetozh.com/blog/'>Ozh</a></small></p>
]]></content:encoded>
			<wfw:commentRss>http://www.iwanna.cn/archives/2009/03/31/69/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>Tree 二叉搜索树</title>
		<link>http://www.iwanna.cn/archives/2009/03/31/67/</link>
		<comments>http://www.iwanna.cn/archives/2009/03/31/67/#comments</comments>
		<pubDate>Tue, 31 Mar 2009 14:44:55 +0000</pubDate>
		<dc:creator>seasun</dc:creator>
				<category><![CDATA[Algorithm]]></category>

		<guid isPermaLink="false">http://www.iwanna.cn/?p=67</guid>
		<description><![CDATA[每个节点最多两个子节点，其中左边节点的值小于该节点的值，右边节点的值大于该节点的值。为了简便起见，该二叉树装入的数据为整数，且不允许有重复的关键字值。
编程中为了简便，采用了递归算法，运算时会带来额外的开销，如果能将相应的算法替换为迭代，则更为有效。删除的算法相应复杂一些，但也可以承受。

API
add：将数加入树
remove：从树中删除指定的节点
contains：树中是否包含指定的数
ordinal：从小到大遍历打印数（测试只用）
max：查找最大值
min：查找最小值
其中Node类是辅助类，为了简单没有写标准的 get，set方法。
因为该树没有自我保持平衡的能力，因此对于随机插入的数据，效果较好，对于有局部生降序特征的插入序列，则会失去平衡，极端状况下，树退化成链表。关于平衡树请参见（Tree2-3-4 ，红黑树 ,Tree-2-3 )
Tree的main函数仅为测试之用。
class Node {
private int value;
private Node left;
private Node right;
Node(int value) {
this.value = value;
}
int value() {
return value;
}
void left(Node left) {
this.left = left;
}
void right(Node right) {
this.right = right;
}
Node left() {
return left;
}
Node right() {
return right;
}
}
class Tree {
private Node root;
void add(int value) {
Node node = new Node(value);
if(root == null) root = node;
else add(root,node);
}
private void add(Node [...]]]></description>
			<content:encoded><![CDATA[<p>每个节点最多两个子节点，其中左边节点的值小于该节点的值，右边节点的值大于该节点的值。为了简便起见，该二叉树装入的数据为整数，且不允许有重复的关键字值。</p>
<p>编程中为了简便，采用了递归算法，运算时会带来额外的开销，如果能将相应的算法替换为迭代，则更为有效。删除的算法相应复杂一些，但也可以承受。</p>
<p style="padding-left: 30px;">
API<br />
add：将数加入树<br />
remove：从树中删除指定的节点<br />
contains：树中是否包含指定的数<br />
ordinal：从小到大遍历打印数（测试只用）<br />
max：查找最大值<br />
min：查找最小值<br />
其中Node类是辅助类，为了简单没有写标准的 get，set方法。</p>
<p>因为该树没有自我保持平衡的能力，因此对于随机插入的数据，效果较好，对于有局部生降序特征的插入序列，则会失去平衡，极端状况下，树退化成链表。关于平衡树请参见（<a href="http://shenyu.javaeye.com/blog/188650">Tree2-3-4</a> ，红黑树 ,<a href="http://shenyu.javaeye.com/blog/186572">Tree-2-3</a> )<br />
Tree的main函数仅为测试之用。</p>
<p>class Node {</p>
<p>private int value;</p>
<p>private Node left;</p>
<p>private Node right;</p>
<p>Node(int value) {</p>
<p>this.value = value;</p>
<p>}</p>
<p>int value() {</p>
<p>return value;</p>
<p>}</p>
<p>void left(Node left) {</p>
<p>this.left = left;</p>
<p>}</p>
<p>void right(Node right) {</p>
<p>this.right = right;</p>
<p>}</p>
<p>Node left() {</p>
<p>return left;</p>
<p>}</p>
<p>Node right() {</p>
<p>return right;</p>
<p>}</p>
<p>}</p>
<p>class Tree {</p>
<p>private Node root;</p>
<p>void add(int value) {</p>
<p>Node node = new Node(value);</p>
<p>if(root == null) root = node;</p>
<p>else add(root,node);</p>
<p>}</p>
<p>private void add(Node current, Node node) {</p>
<p>if(node.value() &lt; current.value()) {</p>
<p>if(current.left() == null) current.left(node);</p>
<p>else add(current.left(), node);</p>
<p>} else if(node.value() &gt; current.value()) {</p>
<p>if(current.right() == null) current.right(node);</p>
<p>else add(current.right(), node);</p>
<p>}</p>
<p>}</p>
<p>boolean contains(int value) {</p>
<p>if(root == null) return false;</p>
<p>else return contains(root,value);</p>
<p>}</p>
<p>private boolean contains(Node current, int value) {</p>
<p>if(current == null) return false;</p>
<p>if(current.value() == value) return true;</p>
<p>if(value &lt; current.value()) return contains(current.left(),value);</p>
<p>else return contains(current.right(),value);</p>
<p>}</p>
<p>void remove(int value) {</p>
<p>remove(null,root,value);</p>
<p>}</p>
<p>private void remove(Node parent, Node current, int value) {</p>
<p>if(current == null) return;</p>
<p>if(current.value() == value) {</p>
<p>Node node;</p>
<p>if(current.left() == null &amp;&amp; current.right() ==  null) node = null;</p>
<p>else if (current.left() != null &amp;&amp; current.right() == null) node = current.left();</p>
<p>else if (current.right() != null &amp;&amp; current.left() == null) node = current.right();</p>
<p>else {</p>
<p>node = removeMin(current,current.right());</p>
<p>node.left(current.left());</p>
<p>node.right(current.right());</p>
<p>}</p>
<p>if(parent == null) root = node;</p>
<p>else if(parent.left() == current) parent.left(node);</p>
<p>else parent.right(node);</p>
<p>} else if(value &lt; current.value()) remove(current,current.left(),value);</p>
<p>else remove(current,current.right(),value);</p>
<p>}</p>
<p>private Node removeMin(Node parent, Node current) {</p>
<p>if(current.left() != null) return removeMin(current,current.left());</p>
<p>else {</p>
<p>if(parent.left() == current) parent.left(current.right());</p>
<p>else parent.right(current.right());</p>
<p>return current;</p>
<p>}</p>
<p>}</p>
<p>int max() {</p>
<p>if(root == null) return -1;</p>
<p>else return max(root);</p>
<p>}</p>
<p>private int max(Node current) {</p>
<p>if(current.right() == null) return current.value();</p>
<p>else return max(current.right());</p>
<p>}</p>
<p>int min() {</p>
<p>if(root == null) return -1;</p>
<p>else return min(root);</p>
<p>}</p>
<p>private int min(Node current) {</p>
<p>if(current.left() == null) return current.value();</p>
<p>else return min(current.left());</p>
<p>}</p>
<p>void ordinal() {</p>
<p>if (root == null) return;</p>
<p>else ordinal(root);</p>
<p>}</p>
<p>void ordinal(Node current) {</p>
<p>if(current.left() != null) ordinal(current.left());</p>
<p>System.out.println(current.value() + &#8221; &#8220;);</p>
<p>if(current.right() != null) ordinal(current.right());</p>
<p>}</p>
<p>public static void main(String[] args) {</p>
<p>Tree t = new Tree();</p>
<p>t.add(50);</p>
<p>t.add(6);</p>
<p>t.add(29);</p>
<p>t.add(100);</p>
<p>t.add(34);</p>
<p>t.add(45);</p>
<p>t.add(4);</p>
<p>t.add(68);</p>
<p>t.ordinal();</p>
<p>System.out.println(t.contains(34));</p>
<p>assert t.contains(34);</p>
<p>assert t.contains(6);</p>
<p>assert !t.contains(110);</p>
<p>assert t.max() == 100;</p>
<p>assert t.min() == 4;</p>
<p>t.remove(50);</p>
<p>t.remove(45);</p>
<p>t.remove(6);</p>
<p>t.ordinal();</p>
<p>}</p>
<p>}</p>
<hr />
<p>© <a href="http://www.iwanna.cn">我想网</a> Akon 所有 , 2009. |
<a href="http://www.iwanna.cn/archives/2009/03/31/67/">永久链接</a> |
<a href="http://www.iwanna.cn/archives/2009/03/31/67/#comments">没有评论</a> |
提交到
<a rel="nofollow" target="_blank" href="http://www.google.com/reader/view/feed/http://www.iwanna.cn/archives/2009/03/31/67/">Google Reader</a>
<a rel="nofollow" target="_blank" href="http://www.xianguo.com/subscribe.php?url=http://www.iwanna.cn/archives/2009/03/31/67/">鲜果</a>
<a rel="nofollow" target="_blank" href="http://www.zhuaxia.com/add_channel.php?url=http://www.iwanna.cn/archives/2009/03/31/67/">抓虾</a>
<hr />
</p>
	标签：<a href="http://www.iwanna.cn/topics/develope/algorithm/" title="Algorithm" rel="tag nofollow">Algorithm</a>, <a href="http://www.iwanna.cn/tags/algorithm/" title="Algorithm" rel="tag nofollow">Algorithm</a><br />

	<h2 class="related_post">您可能会感兴趣的其他文章</h2>
	<ul class="st-related-posts">
	<li><a href="http://www.iwanna.cn/archives/2009/03/31/71/" title="递归－三角数字 (2009年03月31日)">递归－三角数字</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/06/08/3769/" title="用PHP数组对百万数据进行排重 (2010年06月8日)">用PHP数组对百万数据进行排重</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/07/21/4661/" title="浅谈递归过程以及递归的优化 (2010年07月21日)">浅谈递归过程以及递归的优化</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/07/23/4680/" title="检查素数的正则表达式 (2010年07月23日)">检查素数的正则表达式</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/03/31/69/" title="排序－选择 (2009年03月31日)">排序－选择</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/03/31/75/" title="排序－插入 (2009年03月31日)">排序－插入</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/03/31/73/" title="排序－冒泡 (2009年03月31日)">排序－冒泡</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/05/03/929/" title="排序算法汇总 (2009年05月3日)">排序算法汇总</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2009/04/09/323/" title="全文检索中近义词、关联词的解决方案 (2009年04月9日)">全文检索中近义词、关联词的解决方案</a> </li>
	<li><a href="http://www.iwanna.cn/archives/2010/07/23/4695/" title="一些重要的算法 (2010年07月23日)">一些重要的算法</a> </li>
</ul>


<p><small>Feed enhanced by <a href='http://planetozh.com/blog/my-projects/wordpress-plugin-better-feed-rss/'>Better Feed</a> from  <a href='http://planetozh.com/blog/'>Ozh</a></small></p>
]]></content:encoded>
			<wfw:commentRss>http://www.iwanna.cn/archives/2009/03/31/67/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
