<?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; Category &#187; 算法</title>
	<atom:link href="http://shiyanjun.cn/archives/category/algorithm/feed" rel="self" type="application/rss+xml" />
	<link>http://shiyanjun.cn</link>
	<description>简单之美，难得简单，享受简单的唯美。</description>
	<lastBuildDate>Wed, 04 Mar 2026 07:04:53 +0000</lastBuildDate>
	<language>zh-CN</language>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.9.2</generator>
	<item>
		<title>内部排序算法：基数排序</title>
		<link>http://shiyanjun.cn/archives/823.html</link>
		<comments>http://shiyanjun.cn/archives/823.html#comments</comments>
		<pubDate>Tue, 01 Apr 2014 13:06:35 +0000</pubDate>
		<dc:creator><![CDATA[Yanjun]]></dc:creator>
				<category><![CDATA[算法]]></category>

		<guid isPermaLink="false">http://shiyanjun.cn/?p=823</guid>
		<description><![CDATA[<p>基本思想
基数排序是一种非比较型整数排序算法，其原理是将整数按位数切割成不同的数字，然后按每个位数分别比较。由于整数也可以表达字符串（比如名字或日期）和特定格式的浮点数，所以基数排序也不是只能使用于整数。
基数排序可以采用两种方式：

LSD（Least Significant Digital）：从待排序元素的最右边开始计算（如果是数字类型，即从最低位个位开始）。
MSD（Most Significant Digital）：从待排序元素的最左边开始计算（如果是数字类型，即从最高位开始）。

我们以LSD方式为例，从数组R[1..n]中每个元素的最低位开始处理，假设基数为radix，如果是十进制，则radix=10。基本过程如下所示：

计算R中最大的元素，求得位数最大的元素，最大位数记为distance；
对每一位round&lt;=distance，计算R[i] % radix即可得到；
将上面计算得到的余数作为bucket编号，每个bucket中可能存放多个数组R的元素；
按照bucket编号的顺序，收集bucket中元素，就地替换数组R中元素；
重复2~4，最终数组R中的元素为有序。

算法实现
基数排序算法，Java实现，代码如下所示：
基数</p>]]></description>
	<p>基本思想
基数排序是一种非比较型整数排序算法，其原理是将整数按位数切割成不同的数字，然后按每个位数分别比较。由于整数也可以表达字符串（比如名字或日期）和特定格式的浮点数，所以基数排序也不是只能使用于整数。
基数排序可以采用两种方式：

LSD（Least Significant Digital）：从待排序元素的最右边开始计算（如果是数字类型，即从最低位个位开始）。
MSD（Most Significant Digital）：从待排序元素的最左边开始计算（如果是数字类型，即从最高位开始）。

我们以LSD方式为例，从数组R[1..n]中每个元素的最低位开始处理，假设基数为radix，如果是十进制，则radix=10。基本过程如下所示：

计算R中最大的元素，求得位数最大的元素，最大位数记为distance；
对每一位round&lt;=distance，计算R[i] % radix即可得到；
将上面计算得到的余数作为bucket编号，每个bucket中可能存放多个数组R的元素；
按照bucket编号的顺序，收集bucket中元素，就地替换数组R中元素；
重复2~4，最终数组R中的元素为有序。

算法实现
基数排序算法，Java实现，代码如下所示：

p</p>			<content:encoded><![CDATA[<p>基本思想
基数排序是一种非比较型整数排序算法，其原理是将整数按位数切割成不同的数字，然后按每个位数分别比较。由于整数也可以表达字符串（比如名字或日期）和特定格式的浮点数，所以基数排序也不是只能使用于整数。
基数排序可以采用两种方式：

LSD（Least Significant Digital）：从待排序元素的最右边开始计算（如果是数字类型，即从最低位个位开始）。
MSD（Most Significant Digital）：从待排序元素的最左边开始计算（如果是数字类型，即从最高位开始）。

我们以LSD方式为例，从数组R[1..n]中每个元素的最低位开始处理，假设基数为radix，如果是十进制，则radix=10。基本过程如下所示：

计算R中最大的元素，求得位数最大的元素，最大位数记为distance；
对每一位round&lt;=distance，计算R[i] % radix即可得到；
将上面计算得到的余数作为bucket编号，每个bucket中可能存放多个数组R的元素；
按照bucket编号的顺序，收集bucket中元素，就地替换数组R中元素；
重复2~4，最终数组R中的元素为有序。

算法实现
基数排序算法，Java实现，代码如下所示：
基数</p>]]></content:encoded>
			<wfw:commentRss>http://shiyanjun.cn/archives/823.html/feed</wfw:commentRss>
		<slash:comments>3</slash:comments>
		</item>
		<item>
		<title>内部排序算法：归并排序</title>
		<link>http://shiyanjun.cn/archives/820.html</link>
		<comments>http://shiyanjun.cn/archives/820.html#comments</comments>
		<pubDate>Mon, 31 Mar 2014 14:14:46 +0000</pubDate>
		<dc:creator><![CDATA[Yanjun]]></dc:creator>
				<category><![CDATA[算法]]></category>

		<guid isPermaLink="false">http://shiyanjun.cn/?p=820</guid>
		<description><![CDATA[<p>基本思想
n个记录的文件的直接选择排序可经过n-1趟直接选择排序得到有序结果：

初始状态：无序区为R[1..n]，有序区为空。
第1趟排序: 在无序区R[1..n]中选出关键字最小的记录R[k]，将它与无序区的第1个记录R[1] 交换，使R[1..1]和R[2..n]分别变为记录个数增加1个的新有序区和记录个数减少1个的新无序区。
……
第i趟排序: 第i趟排序开始时，当前有序区和无序区分别为R[1..i-1]和R[i..n](1≤i≤n-1)。 该趟排序从当前无序区中选出关键字最小的记录R[k]，将它与无序区的第1个记录R[i]交换，使R[1..i] 和R[i+1..n]分别变为记录个数增加1个的新有序区和记录个数减少1个的新无序区。

这样，n个记录的文件的直接选择排序可经过n-1趟直接选择排序得到有序结果。 
算法实现
归并排序算法，Java实现，代码如下所示：
归并排序算法，Python实现，代码如下所示：
排序过程
假设待排序数组为array = {94,12,34,76,26,9,0,37,55,76,37,5,68,83,90,37,12,65,76,49}，数组大小为20，我们以该数组为例，执行归并排序的具体过程，如下所示：
上面示例的排序过程中，方括号表示“分解</p>]]></description>
	<p>基本思想
n个记录的文件的直接选择排序可经过n-1趟直接选择排序得到有序结果：

初始状态：无序区为R[1..n]，有序区为空。
第1趟排序: 在无序区R[1..n]中选出关键字最小的记录R[k]，将它与无序区的第1个记录R[1] 交换，使R[1..1]和R[2..n]分别变为记录个数增加1个的新有序区和记录个数减少1个的新无序区。
……
第i趟排序: 第i趟排序开始时，当前有序区和无序区分别为R[1..i-1]和R[i..n](1≤i≤n-1)。 该趟排序从当前无序区中选出关键字最小的记录R[k]，将它与无序区的第1个记录R[i]交换，使R[1..i] 和R[i+1..n]分别变为记录个数增加1个的新有序区和记录个数减少1个的新无序区。

这样，n个记录的文件的直接选择排序可经过n-1趟直接选择排序得到有序结果。 
算法实现
归并排序算法，Java实现，代码如下所示：

public abstract class Sorter {
     public abstract void sort(int[] array);
}

public class MergeSorter extends Sorter {

     @Override
     public void sort(int[] array) {
          int[] auxArray = new int[array.length];
   </p>			<content:encoded><![CDATA[<p>基本思想
n个记录的文件的直接选择排序可经过n-1趟直接选择排序得到有序结果：

初始状态：无序区为R[1..n]，有序区为空。
第1趟排序: 在无序区R[1..n]中选出关键字最小的记录R[k]，将它与无序区的第1个记录R[1] 交换，使R[1..1]和R[2..n]分别变为记录个数增加1个的新有序区和记录个数减少1个的新无序区。
……
第i趟排序: 第i趟排序开始时，当前有序区和无序区分别为R[1..i-1]和R[i..n](1≤i≤n-1)。 该趟排序从当前无序区中选出关键字最小的记录R[k]，将它与无序区的第1个记录R[i]交换，使R[1..i] 和R[i+1..n]分别变为记录个数增加1个的新有序区和记录个数减少1个的新无序区。

这样，n个记录的文件的直接选择排序可经过n-1趟直接选择排序得到有序结果。 
算法实现
归并排序算法，Java实现，代码如下所示：
归并排序算法，Python实现，代码如下所示：
排序过程
假设待排序数组为array = {94,12,34,76,26,9,0,37,55,76,37,5,68,83,90,37,12,65,76,49}，数组大小为20，我们以该数组为例，执行归并排序的具体过程，如下所示：
上面示例的排序过程中，方括号表示“分解</p>]]></content:encoded>
			<wfw:commentRss>http://shiyanjun.cn/archives/820.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>内部排序算法：堆排序</title>
		<link>http://shiyanjun.cn/archives/802.html</link>
		<comments>http://shiyanjun.cn/archives/802.html#comments</comments>
		<pubDate>Mon, 31 Mar 2014 08:16:33 +0000</pubDate>
		<dc:creator><![CDATA[Yanjun]]></dc:creator>
				<category><![CDATA[算法]]></category>

		<guid isPermaLink="false">http://shiyanjun.cn/?p=802</guid>
		<description><![CDATA[<p>基本思想

堆的定义

n个关键字序列kl，k2，…，kn称为堆，当且仅当该序列满足如下性质之一（简称堆性质）：

ki≤k2i且ki≤k2i+1 或
ki≥k2i且ki≥k2i+1（1≤i≤FLOOR(n/2)）

若将此序列所存储的向量R[1..n]看做是一棵完全二叉树的存储结构，则堆实质上是满足如下性质的完全二叉树：树中任一非叶结点的关键字均不大于（或不小于）其左右孩子（若 存在）结点的关键字。

小根堆：根结点（亦称为堆顶）的关键字是堆里所有结点关键字中最小的。
大根堆：根结点（亦称为堆顶）的关键字是堆里所有结点关键字中最大的。

我们可以选择大根堆或者小根堆中的任意一个来进行排序。

排序思想

用大根堆排序的基本思想：

先将初始文件R[1..n]建成一个大根堆，此堆为初始的无序区。
再将关键字最大的记录R[1]（即堆顶）和无序区的最后一个记录R[n]交换，由此得 到新的无序区R[1..n-1]和有序区R[n]，且满足R[1..n-1].keys≤R[n].key。
由于交换后新的根R[1]可能违反堆性质，故应将当前无序区R[1..n-1]调整为堆。 然后再次将R[1..n-1]中关键字最大的记录R[1]和该区间的最后一个</p>]]></description>
	<p>基本思想

堆的定义

n个关键字序列kl，k2，…，kn称为堆，当且仅当该序列满足如下性质之一（简称堆性质）：

ki≤k2i且ki≤k2i+1 或
ki≥k2i且ki≥k2i+1（1≤i≤FLOOR(n/2)）

若将此序列所存储的向量R[1..n]看做是一棵完全二叉树的存储结构，则堆实质上是满足如下性质的完全二叉树：树中任一非叶结点的关键字均不大于（或不小于）其左右孩子（若 存在）结点的关键字。

小根堆：根结点（亦称为堆顶）的关键字是堆里所有结点关键字中最小的。
大根堆：根结点（亦称为堆顶）的关键字是堆里所有结点关键字中最大的。

我们可以选择大根堆或者小根堆中的任意一个来进行排序。

排序思想

用大根堆排序的基本思想：

先将初始文件R[1..n]建成一个大根堆，此堆为初始的无序区。
再将关键字最大的记录R[1]（即堆顶）和无序区的最后一个记录R[n]交换，由此得 到新的无序区R[1..n-1]和有序区R[n]，且满足R[1..n-1].keys≤R[n].key。
由于交换后新的根R[1]可能违反堆性质，故应将当前无序区R[1..n-1]调整为堆。 然后再次将R[1..n-1]中关键字最大的记录R[1]和该区间的最后一个</p>			<content:encoded><![CDATA[<p>基本思想

堆的定义

n个关键字序列kl，k2，…，kn称为堆，当且仅当该序列满足如下性质之一（简称堆性质）：

ki≤k2i且ki≤k2i+1 或
ki≥k2i且ki≥k2i+1（1≤i≤FLOOR(n/2)）

若将此序列所存储的向量R[1..n]看做是一棵完全二叉树的存储结构，则堆实质上是满足如下性质的完全二叉树：树中任一非叶结点的关键字均不大于（或不小于）其左右孩子（若 存在）结点的关键字。

小根堆：根结点（亦称为堆顶）的关键字是堆里所有结点关键字中最小的。
大根堆：根结点（亦称为堆顶）的关键字是堆里所有结点关键字中最大的。

我们可以选择大根堆或者小根堆中的任意一个来进行排序。

排序思想

用大根堆排序的基本思想：

先将初始文件R[1..n]建成一个大根堆，此堆为初始的无序区。
再将关键字最大的记录R[1]（即堆顶）和无序区的最后一个记录R[n]交换，由此得 到新的无序区R[1..n-1]和有序区R[n]，且满足R[1..n-1].keys≤R[n].key。
由于交换后新的根R[1]可能违反堆性质，故应将当前无序区R[1..n-1]调整为堆。 然后再次将R[1..n-1]中关键字最大的记录R[1]和该区间的最后一个</p>]]></content:encoded>
			<wfw:commentRss>http://shiyanjun.cn/archives/802.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>内部排序算法：快速排序</title>
		<link>http://shiyanjun.cn/archives/800.html</link>
		<comments>http://shiyanjun.cn/archives/800.html#comments</comments>
		<pubDate>Mon, 31 Mar 2014 06:35:22 +0000</pubDate>
		<dc:creator><![CDATA[Yanjun]]></dc:creator>
				<category><![CDATA[算法]]></category>

		<guid isPermaLink="false">http://shiyanjun.cn/?p=800</guid>
		<description><![CDATA[<p>基本思想
设当前待排序的数组无序区为R[low..high]，利用分治法可将快速排序的基本思想描述为：

分解：

在R[low..high]中任选一个记录作为基准（Pivot），以此基准将当前无序区划分为左、右两个较小的子区间R[low..pivotpos-1)和R[pivotpos+1..high]，并使左边子区间中所有记录的关键字均小于等于基准记录（不妨记为pivot）的关键字pivot.key，右边的子区间中所有记录的关键字均大于等于pivot.key，而基准记录pivot则位于正确的位置（pivotpos）上，它无需参加后续的排序。
注意：划分的关键是要求出基准记录所在的位置pivotpos，划分的结果可以简单地表示为（注意pivot=R[pivotpos]）：
R[low..pivotpos-1].keys ≤ R[pivotpos].key ≤ R[pivotpos+1..high].keys
其中low≤pivotpos≤high。

求解：

通过递归调用快速排序对左、右子区间R[low..pivotpos-1]和R[pivotpos+1..high] 快速排序。

组合：

因为当“求解”步骤中的两个递归调用结束时，其左、右两个子区间已有序。对快速排序而言， “组合”步骤不需要做什么，可看作是空操作。
算法实现
快速排序算法</p>]]></description>
	<p>基本思想
设当前待排序的数组无序区为R[low..high]，利用分治法可将快速排序的基本思想描述为：

分解：

在R[low..high]中任选一个记录作为基准（Pivot），以此基准将当前无序区划分为左、右两个较小的子区间R[low..pivotpos-1)和R[pivotpos+1..high]，并使左边子区间中所有记录的关键字均小于等于基准记录（不妨记为pivot）的关键字pivot.key，右边的子区间中所有记录的关键字均大于等于pivot.key，而基准记录pivot则位于正确的位置（pivotpos）上，它无需参加后续的排序。
注意：划分的关键是要求出基准记录所在的位置pivotpos，划分的结果可以简单地表示为（注意pivot=R[pivotpos]）：
R[low..pivotpos-1].keys ≤ R[pivotpos].key ≤ R[pivotpos+1..high].keys
其中low≤pivotpos≤high。

求解：

通过递归调用快速排序对左、右子区间R[low..pivotpos-1]和R[pivotpos+1..high] 快速排序。

组合：

因为当“求解”步骤中的两个递归调用结束时，其左、右两个子区间已有序。对快速排序而言， “组合”步骤不需要做什么，可看作是空操作。
算法实现
快速排序算法</p>			<content:encoded><![CDATA[<p>基本思想
设当前待排序的数组无序区为R[low..high]，利用分治法可将快速排序的基本思想描述为：

分解：

在R[low..high]中任选一个记录作为基准（Pivot），以此基准将当前无序区划分为左、右两个较小的子区间R[low..pivotpos-1)和R[pivotpos+1..high]，并使左边子区间中所有记录的关键字均小于等于基准记录（不妨记为pivot）的关键字pivot.key，右边的子区间中所有记录的关键字均大于等于pivot.key，而基准记录pivot则位于正确的位置（pivotpos）上，它无需参加后续的排序。
注意：划分的关键是要求出基准记录所在的位置pivotpos，划分的结果可以简单地表示为（注意pivot=R[pivotpos]）：
R[low..pivotpos-1].keys ≤ R[pivotpos].key ≤ R[pivotpos+1..high].keys
其中low≤pivotpos≤high。

求解：

通过递归调用快速排序对左、右子区间R[low..pivotpos-1]和R[pivotpos+1..high] 快速排序。

组合：

因为当“求解”步骤中的两个递归调用结束时，其左、右两个子区间已有序。对快速排序而言， “组合”步骤不需要做什么，可看作是空操作。
算法实现
快速排序算法</p>]]></content:encoded>
			<wfw:commentRss>http://shiyanjun.cn/archives/800.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>内部排序算法：希尔排序</title>
		<link>http://shiyanjun.cn/archives/798.html</link>
		<comments>http://shiyanjun.cn/archives/798.html#comments</comments>
		<pubDate>Mon, 31 Mar 2014 05:27:46 +0000</pubDate>
		<dc:creator><![CDATA[Yanjun]]></dc:creator>
				<category><![CDATA[算法]]></category>

		<guid isPermaLink="false">http://shiyanjun.cn/?p=798</guid>
		<description><![CDATA[<p>基本思想

先取一个小于n的整数d1作为第一个增量，把待排序的全部记录分成dx个组。所有距离为d1的倍数的记录放在同一个组中。
先在各组内进行直接插人排序。
然后，取第二个增量d2&lt;d1重复上述的分组和排序。
直至所取的增量dt=1(dt&lt;dt-x&lt;&#8230;&lt;d2&lt;d1)，即所有记录放在同一组中进行直接插入排序为止。

算法实现
希尔排序算法，Java实现，代码如下所示：
希尔排序算法，Python实现，代码如下所示：
排序过程
希尔排序的过程如下：

首先初始化间隔d为待排序数组的长度，无需排序。减小d，对于每次得到的间隔d，执行多组排序，使得原始数组间隔为d的一个子数组为有序，该数组通过类似直接插入排序的算法来执行排序。
直到，d减小为1的时候，整个数组为有序。这里，采用二分的策略来得到间隔d。

下面通过例子来说明，执行希尔排序的过程，如下所示：
假设待排序数组为array = {94,12,34,76,26,9,0,37,55,76,37,5,68,83,90,37,12,65,76,49}，数组大小为20。整个排序过程的分组情况，如下所示：
下面说明详细过程：
首先，初始化d = 20。在循环中反复得</p>]]></description>
	<p>基本思想

先取一个小于n的整数d1作为第一个增量，把待排序的全部记录分成dx个组。所有距离为d1的倍数的记录放在同一个组中。
先在各组内进行直接插人排序。
然后，取第二个增量d2&lt;d1重复上述的分组和排序。
直至所取的增量dt=1(dt&lt;dt-x&lt;&#8230;&lt;d2&lt;d1)，即所有记录放在同一组中进行直接插入排序为止。

算法实现
希尔排序算法，Java实现，代码如下所示：

public abstract class Sorter {
     public abstract void sort(int[] array);
}

public class ShellSorter extends Sorter {

     @Override
     public void sort(int[] array) {
          int d = array.length;
          do {
               d /= 2;
               shellPass(array, d); // 根据逐渐减小的间隔增量，循环调用一趟排序
          } while (d &gt; 1);
     }

     /**
     * 希尔一趟排序
     * @param d 间隔增量
     */
     private void shellPass(int[] array, int d) {
          Integer tmp;
          for (int i = d; i &lt;</p>			<content:encoded><![CDATA[<p>基本思想

先取一个小于n的整数d1作为第一个增量，把待排序的全部记录分成dx个组。所有距离为d1的倍数的记录放在同一个组中。
先在各组内进行直接插人排序。
然后，取第二个增量d2&lt;d1重复上述的分组和排序。
直至所取的增量dt=1(dt&lt;dt-x&lt;&#8230;&lt;d2&lt;d1)，即所有记录放在同一组中进行直接插入排序为止。

算法实现
希尔排序算法，Java实现，代码如下所示：
希尔排序算法，Python实现，代码如下所示：
排序过程
希尔排序的过程如下：

首先初始化间隔d为待排序数组的长度，无需排序。减小d，对于每次得到的间隔d，执行多组排序，使得原始数组间隔为d的一个子数组为有序，该数组通过类似直接插入排序的算法来执行排序。
直到，d减小为1的时候，整个数组为有序。这里，采用二分的策略来得到间隔d。

下面通过例子来说明，执行希尔排序的过程，如下所示：
假设待排序数组为array = {94,12,34,76,26,9,0,37,55,76,37,5,68,83,90,37,12,65,76,49}，数组大小为20。整个排序过程的分组情况，如下所示：
下面说明详细过程：
首先，初始化d = 20。在循环中反复得</p>]]></content:encoded>
			<wfw:commentRss>http://shiyanjun.cn/archives/798.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>内部排序算法：冒泡排序</title>
		<link>http://shiyanjun.cn/archives/795.html</link>
		<comments>http://shiyanjun.cn/archives/795.html#comments</comments>
		<pubDate>Fri, 28 Mar 2014 13:33:26 +0000</pubDate>
		<dc:creator><![CDATA[Yanjun]]></dc:creator>
				<category><![CDATA[算法]]></category>

		<guid isPermaLink="false">http://shiyanjun.cn/?p=795</guid>
		<description><![CDATA[<p>基本思想
将被排序的记录数组R[0..n-1]垂直排列，每个记录R[i]看作是重量为R[i].key的气泡。根据轻气泡不能在重气泡之下的原则，从下往上扫描数组R：凡扫描到违反本原则的轻气泡，就使其 向上&#8221;飘浮&#8221;。如此反复进行，直到最后任何两个气泡都是轻者在上，重者在下为止。
具体过程，如下所示：

初始状态：R[0..n-1]为无序区。
第一趟扫描：从无序区底部向上依次比较相邻的两个气泡的重量，若发现轻者在下、重者 在上，则交换二者的位置，即依次比较(R[n-1], R[n-2])、(R[n-2], R[n-3])、…、(R[1],  R[0])；对于每对气泡(R[j+1], R[j])，若R[j+1].key第一趟扫描完毕时，&#8221;最轻&#8221;的气泡就飘浮到该区间的顶部，即关键字最小的记录被放在最高位置R[0]上。
第二趟扫描：扫描R[1..n-1]。扫描完毕时，&#8221;次轻&#8221;的气泡飘浮到R[1]的位置上……最后，经过n-1趟扫描可得到有序区R[0..n-1]。

注意：
第i趟扫描时，R[0..i-1]和R[i..n-1]分别为当前的有序区和无序区。扫描仍是从无序区底 部向上直至该区顶部。扫描完毕时，该区中最轻气泡飘浮到顶部</p>]]></description>
	<p>基本思想
将被排序的记录数组R[0..n-1]垂直排列，每个记录R[i]看作是重量为R[i].key的气泡。根据轻气泡不能在重气泡之下的原则，从下往上扫描数组R：凡扫描到违反本原则的轻气泡，就使其 向上&#8221;飘浮&#8221;。如此反复进行，直到最后任何两个气泡都是轻者在上，重者在下为止。
具体过程，如下所示：

初始状态：R[0..n-1]为无序区。
第一趟扫描：从无序区底部向上依次比较相邻的两个气泡的重量，若发现轻者在下、重者 在上，则交换二者的位置，即依次比较(R[n-1], R[n-2])、(R[n-2], R[n-3])、…、(R[1],  R[0])；对于每对气泡(R[j+1], R[j])，若R[j+1].key第一趟扫描完毕时，&#8221;最轻&#8221;的气泡就飘浮到该区间的顶部，即关键字最小的记录被放在最高位置R[0]上。
第二趟扫描：扫描R[1..n-1]。扫描完毕时，&#8221;次轻&#8221;的气泡飘浮到R[1]的位置上……最后，经过n-1趟扫描可得到有序区R[0..n-1]。

注意：
第i趟扫描时，R[0..i-1]和R[i..n-1]分别为当前的有序区和无序区。扫描仍是从无序区底 部向上直至该区顶部。扫描完毕时，该区中最轻气泡飘浮到顶部</p>			<content:encoded><![CDATA[<p>基本思想
将被排序的记录数组R[0..n-1]垂直排列，每个记录R[i]看作是重量为R[i].key的气泡。根据轻气泡不能在重气泡之下的原则，从下往上扫描数组R：凡扫描到违反本原则的轻气泡，就使其 向上&#8221;飘浮&#8221;。如此反复进行，直到最后任何两个气泡都是轻者在上，重者在下为止。
具体过程，如下所示：

初始状态：R[0..n-1]为无序区。
第一趟扫描：从无序区底部向上依次比较相邻的两个气泡的重量，若发现轻者在下、重者 在上，则交换二者的位置，即依次比较(R[n-1], R[n-2])、(R[n-2], R[n-3])、…、(R[1],  R[0])；对于每对气泡(R[j+1], R[j])，若R[j+1].key第一趟扫描完毕时，&#8221;最轻&#8221;的气泡就飘浮到该区间的顶部，即关键字最小的记录被放在最高位置R[0]上。
第二趟扫描：扫描R[1..n-1]。扫描完毕时，&#8221;次轻&#8221;的气泡飘浮到R[1]的位置上……最后，经过n-1趟扫描可得到有序区R[0..n-1]。

注意：
第i趟扫描时，R[0..i-1]和R[i..n-1]分别为当前的有序区和无序区。扫描仍是从无序区底 部向上直至该区顶部。扫描完毕时，该区中最轻气泡飘浮到顶部</p>]]></content:encoded>
			<wfw:commentRss>http://shiyanjun.cn/archives/795.html/feed</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>内部排序算法：直接选择排序</title>
		<link>http://shiyanjun.cn/archives/793.html</link>
		<comments>http://shiyanjun.cn/archives/793.html#comments</comments>
		<pubDate>Fri, 28 Mar 2014 09:42:37 +0000</pubDate>
		<dc:creator><![CDATA[Yanjun]]></dc:creator>
				<category><![CDATA[算法]]></category>

		<guid isPermaLink="false">http://shiyanjun.cn/?p=793</guid>
		<description><![CDATA[<p>基本思想
n个记录的文件的直接选择排序可经过n-1趟直接选择排序得到有序结果：

初始状态：无序区为R[1..n]，有序区为空。
第1趟排序：在无序区R[1..n]中选出关键字最小的记录R[k]，将它与无序区的第1个记录R[1] 交换，使R[1..1]和R[2..n]分别变为记录个数增加1个的新有序区和记录个数减少1个的新无序区。
……
第i趟排序：第i趟排序开始时，当前有序区和无序区分别为R[1..i-1]和R[i..n](1≤i≤n-1)。 该趟排序从当前无序区中选出关键字最小的记录R[k]，将它与无序区的第1个记录R[i]交换，使R[1..i] 和R[i+1..n]分别变为记录个数增加1个的新有序区和记录个数减少1个的新无序区。

这样，n个记录的文件的直接选择排序可经过n-1趟直接选择排序得到有序结果。
算法实现
直接选择排序算法，Java实现，代码如下所示：
直接选择排序算法，Python实现，代码如下所示：
排序过程
首先，从0~n-1个元素中找到最小的元素，交换到0位置上；
其次，再从1~n-1中找到次最小的元素，交换到1位置上；
……；
最后从n-2~n-1中找到最小的元素，交换到n-2位置上。n-1位置上一定是最大的元</p>]]></description>
	<p>基本思想
n个记录的文件的直接选择排序可经过n-1趟直接选择排序得到有序结果：

初始状态：无序区为R[1..n]，有序区为空。
第1趟排序：在无序区R[1..n]中选出关键字最小的记录R[k]，将它与无序区的第1个记录R[1] 交换，使R[1..1]和R[2..n]分别变为记录个数增加1个的新有序区和记录个数减少1个的新无序区。
……
第i趟排序：第i趟排序开始时，当前有序区和无序区分别为R[1..i-1]和R[i..n](1≤i≤n-1)。 该趟排序从当前无序区中选出关键字最小的记录R[k]，将它与无序区的第1个记录R[i]交换，使R[1..i] 和R[i+1..n]分别变为记录个数增加1个的新有序区和记录个数减少1个的新无序区。

这样，n个记录的文件的直接选择排序可经过n-1趟直接选择排序得到有序结果。
算法实现
直接选择排序算法，Java实现，代码如下所示：

public abstract class Sorter {
     public abstract void sort(int[] array);
}

public class StraightSelectionSorter extends Sorter {

     @Override
     public void sort(int[] array) {
          int tmp; // 用于交换数据的暂存</p>			<content:encoded><![CDATA[<p>基本思想
n个记录的文件的直接选择排序可经过n-1趟直接选择排序得到有序结果：

初始状态：无序区为R[1..n]，有序区为空。
第1趟排序：在无序区R[1..n]中选出关键字最小的记录R[k]，将它与无序区的第1个记录R[1] 交换，使R[1..1]和R[2..n]分别变为记录个数增加1个的新有序区和记录个数减少1个的新无序区。
……
第i趟排序：第i趟排序开始时，当前有序区和无序区分别为R[1..i-1]和R[i..n](1≤i≤n-1)。 该趟排序从当前无序区中选出关键字最小的记录R[k]，将它与无序区的第1个记录R[i]交换，使R[1..i] 和R[i+1..n]分别变为记录个数增加1个的新有序区和记录个数减少1个的新无序区。

这样，n个记录的文件的直接选择排序可经过n-1趟直接选择排序得到有序结果。
算法实现
直接选择排序算法，Java实现，代码如下所示：
直接选择排序算法，Python实现，代码如下所示：
排序过程
首先，从0~n-1个元素中找到最小的元素，交换到0位置上；
其次，再从1~n-1中找到次最小的元素，交换到1位置上；
……；
最后从n-2~n-1中找到最小的元素，交换到n-2位置上。n-1位置上一定是最大的元</p>]]></content:encoded>
			<wfw:commentRss>http://shiyanjun.cn/archives/793.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>内部排序算法：直接插入排序</title>
		<link>http://shiyanjun.cn/archives/790.html</link>
		<comments>http://shiyanjun.cn/archives/790.html#comments</comments>
		<pubDate>Fri, 28 Mar 2014 09:11:23 +0000</pubDate>
		<dc:creator><![CDATA[Yanjun]]></dc:creator>
				<category><![CDATA[算法]]></category>

		<guid isPermaLink="false">http://shiyanjun.cn/?p=790</guid>
		<description><![CDATA[<p>基本思想
假设待排序的记录存放在数组R[0..n-1]中。初始时，R[0]自成1个有序区，无序区为R[1..n-1]。 从i=1起直至i=n-1为止，依次将R[i]插入当前的有序区R[0..i-1]中，生成含n个记录的有序区。
算法实现
直接插入排序算法，Java实现，代码如下所示：
直接插入排序算法，Python实现，代码如下所示：
排序过程
直接插入排序的执行过程，如下所示：

初始化无序区和有序区：数组第一个元素为有序区，其余的元素作为无序区。
遍历无序区，将无序区的每一个元素插入到有序区正确的位置上。具体执行过程为：
每次取出无序区的第一个元素，如果该元素tmp大于有序区最后一个元素，不做任何操作；
如果tmp小于有序区最后一个元素，说明需要插入到有序区最后一个元素前面的某个位置，从后往前扫描有序区，如果有序区元素大于tmp，将有序区元素后移（第一次后移：tmp小于有序区最大的元素，有序区最大的元素后移覆盖无序区第一个元素，而无序区第一个元素的已经拷贝到tmp中；第二次后移：tmp小于有序区从后向前第二个的元素，有序区从后向前第二个元素后移覆盖有序区最大元素的</p>]]></description>
	<p>基本思想
假设待排序的记录存放在数组R[0..n-1]中。初始时，R[0]自成1个有序区，无序区为R[1..n-1]。 从i=1起直至i=n-1为止，依次将R[i]插入当前的有序区R[0..i-1]中，生成含n个记录的有序区。
算法实现
直接插入排序算法，Java实现，代码如下所示：

public abstract class Sorter {
     public abstract void sort(int[] array);
}

public class StraightInsertionSorter extends Sorter {

     @Override
     public void sort(int[] array) {
          int tmp;
          for (int i = 1; i &lt; array.length; i++) {
               tmp = array[i]; // array[i]的拷贝
               // 如果右侧无序区第一个元素array[i] &lt; 左侧有序区最大的array[i-1]，
               // 需要将有序区比array[i]大的元素向后移动。
               if (array[i] &lt; array[i - 1]) {
                    int j = i - 1;
                    while (j &gt;= 0 &amp;&amp; tmp &lt; array[j]) { // 从右到左扫描有序区
                    </p>			<content:encoded><![CDATA[<p>基本思想
假设待排序的记录存放在数组R[0..n-1]中。初始时，R[0]自成1个有序区，无序区为R[1..n-1]。 从i=1起直至i=n-1为止，依次将R[i]插入当前的有序区R[0..i-1]中，生成含n个记录的有序区。
算法实现
直接插入排序算法，Java实现，代码如下所示：
直接插入排序算法，Python实现，代码如下所示：
排序过程
直接插入排序的执行过程，如下所示：

初始化无序区和有序区：数组第一个元素为有序区，其余的元素作为无序区。
遍历无序区，将无序区的每一个元素插入到有序区正确的位置上。具体执行过程为：
每次取出无序区的第一个元素，如果该元素tmp大于有序区最后一个元素，不做任何操作；
如果tmp小于有序区最后一个元素，说明需要插入到有序区最后一个元素前面的某个位置，从后往前扫描有序区，如果有序区元素大于tmp，将有序区元素后移（第一次后移：tmp小于有序区最大的元素，有序区最大的元素后移覆盖无序区第一个元素，而无序区第一个元素的已经拷贝到tmp中；第二次后移：tmp小于有序区从后向前第二个的元素，有序区从后向前第二个元素后移覆盖有序区最大元素的</p>]]></content:encoded>
			<wfw:commentRss>http://shiyanjun.cn/archives/790.html/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
