经典排序算法
来源:互联网 发布:linux查看80端口占用 编辑:程序博客网 时间:2024/04/29 08:38
1、经典排序算法 - 快速排序Quick sort
原理,通过一趟扫描将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据都要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列
举个例子
如无序数组[6 2 4 1 5 9]
a),先把第一项[6]取出来,
用[6]依次与其余项进行比较,
如果比[6]小就放[6]前边,2 4 1 5都比[6]小,所以全部放到[6]前边
如果比[6]大就放[6]后边,9比[6]大,放到[6]后边,//6出列后大喝一声,比我小的站前边,比我大的站后边,行动吧!霸气十足~
一趟排完后变成下边这样:
排序前 6 2 4 1 5 9
排序后 2 4 1 5 6 9
b),对前半拉[2 4 1 5]继续进行快速排序
重复步骤a)后变成下边这样:
排序前 2 4 1 5
排序后 1 2 4 5
前半拉排序完成,总的排序也完成:
排序前:[6 2 4 1 5 9]
排序后:[1 2 4 5 6 9]
排序结束
以下代码实现仅供参考
static int partition(int[] unsorted, int low, int high)
{
int pivot= unsorted[low];
while (low< high)
{
while (low< high && unsorted[high] > pivot) high--;
unsorted[low] = unsorted[high];
while (low< high && unsorted[low] <= pivot) low++;
unsorted[high] = unsorted[low];
}
unsorted[low] = pivot;
return low;
}
static void quick_sort(int[]unsorted, int low, int high)
{
int loc =0;
if (low< high)
{
loc = partition(unsorted, low,high);
quick_sort(unsorted, low, loc -1);
quick_sort(unsorted, loc + 1, high);
}
}
static void Main(string[] args)
{
int[] x ={ 6, 2, 4,1, 5, 9 };
quick_sort(x, 0, x.Length -1);
foreach (var itemin x)
{
Console.WriteLine(item + ",");
}
Console.ReadLine();
}
2、经典排序算法 - 桶排序Bucket sort
补充说明三点
1,桶排序是稳定的
2,桶排序是常见排序里最快的一种,比快排还要快…大多数情况下
3,桶排序非常快,但是同时也非常耗空间,基本上是最耗空间的一种排序算法
我自己的理解哈,可能与网上说的有一些出入,大体都是同样的原理
无序数组有个要求,就是成员隶属于固定(有限的)的区间,如范围为[0-9](考试分数为1-100等)
例如待排数字[6 2 4 1 5 9]
准备10个空桶,最大数个空桶
[6 2 4 1 5 9] 待排数组
[0 0 0 0 0 0 0 0 0 0] 空桶
[0 1 2 3 4 5 6 7 8 9] 桶编号(实际不存在)
1,顺序从待排数组中取出数字,首先6被取出,然后把6入6号桶,这个过程类似这样:空桶[ 待排数组[ 0 ] ] = 待排数组[ 0 ]
[6 2 4 1 5 9] 待排数组
[0 0 0 0 0 0 6 0 0 0] 空桶
[0 1 2 3 4 5 6 7 8 9] 桶编号(实际不存在)
2,顺序从待排数组中取出下一个数字,此时2被取出,将其放入2号桶,是几就放几号桶
[6 2 4 1 5 9] 待排数组
[0 0 2 0 0 0 6 0 0 0] 空桶
[0 1 2 3 4 5 6 7 8 9] 桶编号(实际不存在)
3,4,5,6省略,过程一样,全部入桶后变成下边这样
[6 2 4 1 5 9] 待排数组
[0 12 0 4 5 6 0 0 9] 空桶
[0 12 3 4 5 6 7 8 9] 桶编号(实际不存在)
0表示空桶,跳过,顺序取出即可:1 2 4 5 6 9
以下代码仅供参考
/// <summary>
///桶排序
/// 1),已知其区间,例如[1..10],学生的分数[0...100]等
/// 2),如果有重复的数字,则需要List<int>数组,这里举的例子没有重复的数字
///</summary>
/// <param name="unsorted">待排数组</param>
/// <param name="maxNumber">待排数组中的最大数,如果可以提供的话</param>
/// <returns></returns>
static int[] bucket_sort(int[] unsorted, intmaxNumber = 99)
{
int[]sorted = new int[maxNumber + 1];
for (int i =0; i < unsorted.Length; i++)
{
sorted[unsorted[i]] =unsorted[i];
}
returnsorted;
}
static void Main(string[] args)
{
int[] x ={ 99, 65, 24,47, 50, 88,33, 66,67, 31, 18 };
varsorted = bucket_sort(x,99);
for (int i =0; i < sorted.Length; i++)
{
if(sorted[i] > 0)
Console.WriteLine(sorted[i]);
}
Console.ReadLine();
}
3、经典排序算法 – 插入排序Insertion sort
插入排序就是每一步都将一个待排数据按其大小插入到已经排序的数据中的适当位置,直到全部插入完毕。
插入排序方法分直接插入排序和折半插入排序两种,这里只介绍直接插入排序,折半插入排序留到“查找”内容中进行。
图1演示了对4个元素进行直接插入排序的过程,共需要(a),(b),(c)三次插入。
以下代码仅供参考,欢迎指正
/// <summary>
///插入排序
///</summary>
/// <paramname="unsorted"></param>
static void insertion_sort(int[] unsorted)
{
for (int i =1; i < unsorted.Length; i++)
{
if(unsorted[i - 1] > unsorted[i])
{
int temp= unsorted[i];
int j =i;
while (j> 0 && unsorted[j - 1] >temp)
{
unsorted[j] =unsorted[j - 1];
j--;
}
unsorted[j] = temp;
}
}
}
static void Main(string[] args)
{
int[] x = { 6, 2, 4,1, 5, 9 };
insertion_sort(x);
foreach (var itemin x)
{
if (item> 0)
Console.WriteLine(item + ",");
}
Console.ReadLine();
}
4、经典排序算法 - 基数排序Radix sort
原理类似桶排序,这里总是需要10个桶,多次使用
首先以个位数的值进行装桶,即个位数为1则放入1号桶,为9则放入9号桶,暂时忽视十位数
例如
待排序数组[62,14,59,88,16]简单点五个数字
分配10个桶,桶编号为0-9,以个位数数字为桶编号依次入桶,变成下边这样
| 0 | 0 | 62 | 0 | 14 | 0 | 16 | 0 | 88 | 59 |
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |桶编号
将桶里的数字顺序取出来,
输出结果:[62,14,16,88,59]
再次入桶,不过这次以十位数的数字为准,进入相应的桶,变成下边这样:
由于前边做了个位数的排序,所以当十位数相等时,个位数字是由小到大的顺序入桶的,就是说,入完桶还是有序
| 0 | 14,16 | 0 | 0 | 0 | 59 | 62 | 0 | 88 | 0 |
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |桶编号
因为没有大过100的数字,没有百位数,所以到这排序完毕,顺序取出即可
最后输出结果:[14,16,59,62,88]
代码仅供参考
/// <summary>
///基数排序
///约定:待排数字中没有0,如果某桶内数字为0则表示该桶未被使用,输出时跳过即可
/// </summary>
/// <param name="unsorted">待排数组</param>
/// <param name="array_x">桶数组第一维长度</param>
/// <param name="array_y">桶数组第二维长度</param>
static void radix_sort(int[] unsorted, intarray_x = 10, int array_y = 100)
{
for (int i =0; i < array_x/* 最大数字不超过999999999...(array_x个9) */; i++)
{
int[,]bucket = new int[array_x, array_y];
foreach (var itemin unsorted)
{
int temp= (item / (int)Math.Pow(10, i))%10;
for (int l =0; l < array_y; l++)
{
if (bucket[temp, l] ==0)
{
bucket[temp, l] =item;
break;
}
}
}
for (int o =0, x = 0; x< array_x; x++)
{
for (int y =0; y < array_y; y++)
{
if (bucket[x, y] ==0) continue;
unsorted[o++] =bucket[x, y];
}
}
}
}
static void Main(string[] args)
{
int[] x ={ 999999999, 65, 24, 47, 13,50, 92, 88, 66, 33,22445, 10001,624159, 624158,624155501 };
radix_sort(x);
foreach (var itemin x)
{
if (item> 0)
Console.WriteLine(item + ",");
}
Console.ReadLine();
}
5、经典排序算法 - 鸽巢排序Pigeonhole sort
原理类似桶排序,同样需要一个很大的鸽巢[桶排序里管这个叫桶,名字无所谓了]
鸽巢其实就是数组啦,数组的索引位置就表示值,该索引位置的值表示出现次数,如果全部为1次或0次那就是桶排序
例如
var pigeonHole = new int[100];
pigeonHole[0]的值表示0的出现次数...
pigeonHole[1]的值表示1的出现次数...
pigeonHole[2]的值表示2的出现次数...
参考http://hi.baidu.com/wangxvfeng101/blog/item/a2c22560e57260c58cb10d8c.html
代码仅供参考,欢迎谌误
///鸽巢排序
///</summary>
/// <param name="unsorted">待排数组</param>
/// <param name="maxNumber">待排数组中的最大数,如果可以指定的话</param>
/// <returns></returns>
static int[] pogeon_sort(int[] unsorted, intmaxNumber = 10)
{
int[]pogeonHole = new int[maxNumber + 1];
foreach (var itemin unsorted)
{
pogeonHole[item]++;
}
returnpogeonHole;
/*
* pogeonHole[10] = 4; 的含意是
* 在待排数组中有4个10出现,同理其它
*/
}
static void Main(string[] args)
{
int[] x ={ 99, 65, 24,47, 47, 50, 99, 88,66, 33, 66, 67, 31,18, 24 };
varsorted = pogeon_sort(x,99);
for (int i =0; i < sorted.Length; i++)
{
for (int j =0; j < sorted[i]; j++)
{
Console.WriteLine(i);
}
}
Console.ReadLine();
}
6、经典排序算法 - 归并排序Merge sort
原理,把原始数组分成若干子数组,对每一个子数组进行排序,
继续把子数组与子数组合并,合并后仍然有序,直到全部合并完,形成有序的数组
举例
无序数组[6 2 4 1 5 9]
先看一下每个步骤下的状态,完了再看合并细节
第一步 [6 2 4 1 5 9]原始状态
第二步 [2 6] [1 4] [5 9]两两合并排序,排序细节后边介绍
第三步 [1 2 4 6] [5 9]继续两组两组合并
第四步 [1 2 4 5 6 9]合并完毕,排序完毕
输出结果[1 2 4 5 6 9]
合并细节
详细介绍第二步到第三步的过程,其余类似
第二步:[2 6] [1 4] [5 9]
两两合并,其实仅合并[2 6] [1 4],所以[5 9]不管它,
原始状态
第一个数组[2 6]
第二个数组[1 4]
--------------------
第三个数组[...]
第1步,顺序从第一,第二个数组里取出一个数字:2和1
比较大小后将小的放入第三个数组,此时变成下边这样
第一个数组[2 6]
第二个数组[4]
--------------------
第三个数组[1]
第2步,继续刚才的步骤,顺序从第一,第二个数组里取数据,2和4,
同样的比较大小后将小的放入第三个数组,此时状态如下
第一个数组[6]
第二个数组[4]
--------------------
第三个数组[1 2]
第3步,再重复前边的步骤变成,将较小的4放入第三个数组后变成如下状态
第一个数组[6]
第二个数组[...]
--------------------
第三个数组[1 2 4]
第4步,最后将6放入,排序完毕
第一个数组[...]
第二个数组[...]
--------------------
第三个数组[1 2 4 6]
[ 1 2 4 6 ]与[ 5 9 ]的合并过程与上边一样,不再分解
代码仅供参考
static void merge(int[] unsorted, intfirst, int mid, int last,int[] sorted)
{
int i =first, j = mid;
int k = 0;
while (i< mid && j < last)
if(unsorted[i] < unsorted[j])
sorted[k++] =unsorted[i++];
else
sorted[k++] =unsorted[j++];
while (i< mid)
sorted[k++] = unsorted[i++];
while (j< last)
sorted[k++] = unsorted[j++];
for (int v =0; v < k; v++)
unsorted[first + v] =sorted[v];
}
static void merge_sort(int[] unsorted, intfirst, int last, int[]sorted)
{
if(first + 1 < last)
{
int mid =(first + last) /2;
Console.WriteLine("{0}-{1}-{2}", first, mid, last);
merge_sort(unsorted, first,mid, sorted);
merge_sort(unsorted, mid, last,sorted);
merge(unsorted, first, mid,last, sorted);
}
}
static void Main(string[] args)
{
int[] x ={ 6, 2, 4,1, 5, 9 };
int[]sorted = new int[x.Length];
merge_sort(x, 0, x.Length, sorted);
for (int i =0; i < sorted.Length; i++)
{
if (x[i]> 0)
Console.WriteLine(x[i]);
}
Console.ReadLine();
}
7、经典排序算法 - 冒泡排序Bubble sort
原理是临近的数字两两进行比较,按照从小到大或者从大到小的顺序进行交换,
这样一趟过去后,最大或最小的数字被交换到了最后一位,
然后再从头开始进行两两比较交换,直到倒数第二位时结束,其余类似看例子
例子为从小到大排序,
原始待排序数组| 6 | 2 | 4 | 1 | 5 | 9 |
第一趟排序(外循环)
第一次两两比较6 > 2交换(内循环)
交换前状态| 6 | 2 | 4 | 1 | 5 | 9 |
交换后状态| 2 | 6 | 4 | 1 | 5 | 9 |
第二次两两比较,6 > 4交换
交换前状态| 2 | 6 | 4 | 1 | 5 | 9 |
交换后状态| 2 | 4 | 6 | 1 | 5 | 9 |
第三次两两比较,6 > 1交换
交换前状态| 2 | 4 | 6 | 1 | 5 | 9 |
交换后状态| 2 | 4 | 1 | 6 | 5 | 9 |
第四次两两比较,6 > 5交换
交换前状态| 2 | 4 | 1 | 6 | 5 | 9 |
交换后状态| 2 | 4 | 1 | 5 | 6 | 9 |
第五次两两比较,6 < 9不交换
交换前状态| 2 | 4 | 1 | 5 | 6 | 9 |
交换后状态| 2 | 4 | 1 | 5 | 6 | 9 |
第二趟排序(外循环)
第一次两两比较2 < 4不交换
交换前状态| 2 | 4 | 1 | 5 | 6 | 9 |
交换后状态| 2 | 4 | 1 | 5 | 6 | 9 |
第二次两两比较,4 > 1交换
交换前状态| 2 | 4 | 1 | 5 | 6 | 9 |
交换后状态| 2 | 1 | 4 | 5 | 6 | 9 |
第三次两两比较,4 < 5不交换
交换前状态| 2 | 1 | 4 | 5 | 6 | 9 |
交换后状态| 2 | 1 | 4 | 5 | 6 | 9 |
第四次两两比较,5 < 6不交换
交换前状态| 2 | 1 | 4 | 5 | 6 | 9 |
交换后状态| 2 | 1 | 4 | 5 | 6 | 9 |
第三趟排序(外循环)
第一次两两比较2 > 1交换
交换后状态| 2 | 1 | 4 | 5 | 6 | 9 |
交换后状态| 1 | 2 | 4 | 5 | 6 | 9 |
第二次两两比较,2 < 4不交换
交换后状态| 1 | 2 | 4 | 5 | 6 | 9 |
交换后状态| 1 | 2 | 4 | 5 | 6 | 9 |
第三次两两比较,4 < 5不交换
交换后状态| 1 | 2 | 4 | 5 | 6 | 9 |
交换后状态| 1 | 2 | 4 | 5 | 6 | 9 |
第四趟排序(外循环)无交换
第五趟排序(外循环)无交换
排序完毕,输出最终结果1 2 4 5 6 9
代码仅供参考
static void bubble_sort(int[] unsorted)
{
for (int i =0; i < unsorted.Length; i++)
{
for (int j = i; j < unsorted.Length; j++)
{
if(unsorted[i] > unsorted[j])
{
int temp = unsorted[i];
unsorted[i] =unsorted[j];
unsorted[j] = temp;
}
}
}
}
static void Main(string[] args)
{
int[] x ={ 6, 2, 4,1, 5, 9 };
bubble_sort(x);
foreach (var itemin x)
{
Console.WriteLine(item);
}
Console.ReadLine();
}
冒泡排序动画演示
8、经典排序算法 - 选择排序Selection sort
顾名思意,就是直接从待排序数组里选择一个最小(或最大)的数字,每次都拿一个最小数字出来,
顺序放入新数组,直到全部拿完
再简单点,对着一群数组说,你们谁最小出列,站到最后边
然后继续对剩余的无序数组说,你们谁最小出列,站到最后边
再继续刚才的操作,一直到最后一个,继续站到最后边,现在数组有序了,从小到大
举例
先说看每步的状态变化,后边介绍细节,现有无序数组[6 2 4 1 5 9]
第一趟找到最小数1,放到最前边(与首位数字交换)
交换前:| 6 | 2 | 4 | 1 | 5 | 9 |
交换后:| 1 | 2 | 4 | 6 | 5 | 9 |
第二趟找到余下数字[2 4 6 5 9]里的最小数2,与当前数组的首位数字进行交换,实际没有交换,本来就在首位
交换前:| 1 | 2 | 4 | 6 | 5 | 9 |
交换后:| 1 | 2 | 4 | 6 | 5 | 9 |
第三趟继续找到剩余[4 6 5 9]数字里的最小数4,实际没有交换,4待首位置无须交换
第四趟从剩余的[6 5 9]里找到最小数5,与首位数字6交换位置
交换前:| 1 | 2 | 4 | 6 | 5 | 9 |
交换后:| 1 | 2 | 4 | 5 | 6 | 9 |
第五趟从剩余的[6 9]里找到最小数6,发现它待在正确的位置,没有交换
排序完毕输出正确结果[1 2 4 5 6 9]
第一趟找到最小数1的细节
当前数组是| 6 | 2 | 4 | 1 | 5 | 9 |
先把6取出来,让它扮演最小数
当前最小数6与其它数一一进行比较,发现更小数就交换角色
当前最小数6与2比较,发现更小数,交换角色,此时最小数是2,接下来2与剩余数字比较
当前最小数2与4比较,不动
当前最小数2与1比较,发现更小数,交换角色,此时最小数是1,接下来1与剩余数字比较
当前最小数1与5比较,不动
当前最小数1与9比较,不动,到达末尾
当前最小数1与当前首位数字进行位置交换,如下所示
交换前:| 6 | 2 | 4 | 1 | 5 | 9 |
交换后:| 1 | 2 | 4 | 6 | 5 | 9 |
完成一趟排序,其余步骤类似
代码仅供参考
static void selection_sort(int[] unsorted)
{
for (int i =0; i < unsorted.Length; i++)
{
int min =unsorted[i], min_index = i;
for (int j = i; j < unsorted.Length; j++)
{
if(unsorted[j] < min)
{
min = unsorted[j];
min_index = j;
}
}
if(min_index != i)
{
int temp= unsorted[i];
unsorted[i] =unsorted[min_index];
unsorted[min_index] = temp;
}
}
}
static void Main(string[] args)
{
int[] x ={ 6, 2, 4,1, 5, 9 };
selection_sort(x);
foreach (var itemin x)
{
Console.WriteLine(item);
}
Console.ReadLine();
}
9、经典排序算法 - 希尔排序Shell sort
希尔排序Shell Sort是基于插入排序的一种改进,同样分成两部分,
第一部分,希尔排序介绍
第二部分,如何选取关键字,选取关键字是希尔排序的关键
第一块希尔排序介绍
准备待排数组[6 2 4 1 5 9]
首先需要选取关键字,例如关键是3和1(第一步分成三组,第二步分成一组),那么待排数组分成了以下三个虚拟组:
[6 1]一组
[2 5]二组
[4 9]三组
看仔细啊,不是临近的两个数字分组,而是3(分成了三组)的倍数的数字分成了一组,
就是每隔3个数取一个,每隔三个再取一个,这样取出来的数字放到一组,
把它们当成一组,但不实际分组,只是当成一组来看,所以上边的"组"实际上并不存在,只是为了说明分组关系
对以上三组分别进行插入排序变成下边这样
[1 6] [2 5] [4 9]
具体过程:
[6 1]6和1交换变成[1 6]
[2 5]2与5不动还是[2 5]
[4 9]4与9不动还是[4 9]
第一趟排序状态演示:
待排数组:[6 2 4 1 5 9]
排后数组:[1 2 4 6 5 9]
第二趟关键字取的是1,即每隔一个取一个组成新数组,实际上就是只有一组啦,隔一取一就全部取出来了嘛
此时待排数组为:[1 2 4 6 5 9]
直接对它进行插入排序
还记得插入排序怎么排不?复习一下
[1 2 4]都不用动,过程省略,到5的时候,将5取出,在前边的有序数组里找到适合它的位置插入,就是4后边,6前边
后边的也不用改,所以排序完毕
顺序输出结果:[1 2 4 5 6 9]
第二块希尔排序的关键是如何取关键字,因为其它内容与插入排序一样
那么如何选取关键字呢?就是分成三组,一组,这个分组的依据是什么呢?为什么不是二组,六组或者其它组嘞?
好的增量序列的共同特征:
① 最后一个增量必须为1
② 应该尽量避免序列中的值(尤其是相邻的值)互为倍数的情况
参见 http://baike.baidu.com/view/2217047.htm
这么关键的问题竟然没有一个公式,只给出了两个判定标准
好吧,一般10个待排数字的话,关键依次选取5 3 1即可,其它的情况只能自己判断了,然后看是否符合上述两条"好"的标准
就是说,这个关键的选择是没有规定的,怎么选都可以,仅一条,关键字要越来越小,直到1为止
后补:
增量的取值规则为第一次取总长度的一半,第二次取一半的一半,依次累推直到1为止,刚从下文中看到的这一段描述,感谢!
算法系列15天速成——第三天七大经典排序【下】
以下C#代码实现仅供参考
static void shell_sort(int[] unsorted, int len)
{
intgroup, i, j, temp;
for(group = len / 2; group > 0;group /= 2)
{
for (i =group; i < len; i++)
{
for (j =i - group; j >=0; j -= group)
{
if (unsorted[j] > unsorted[j + group])
{
temp = unsorted[j];
unsorted[j] =unsorted[j + group];
unsorted[j + group]= temp;
}
}
}
}
}
static void Main(string[] args)
{
int[] x ={ 6, 2, 4,1, 5, 9 };
shell_sort(x, x.Length);
foreach (var itemin x)
{
Console.WriteLine(item);
}
Console.ReadLine();
}
10、经典排序算法 - 堆排序Heap sort
堆排序有点小复杂,分成三块
第一块,什么是堆,什么是最大堆
第二块,怎么将堆调整为最大堆,这部分是重点
第三块,堆排序介绍
第一块,什么是堆,什么是最大堆
什么是堆
这里的堆(二叉堆),指得不是堆栈的那个堆,而是一种数据结构。
堆可以视为一棵完全的二叉树,完全二叉树的一个“优秀”的性质是,除了最底层之外,每一层都是满的,这使得堆可以利用数组来表示,每一个结点对应数组中的一个元素.
数组与堆之间的关系
二叉堆一般分为两种:最大堆和最小堆。
什么是最大堆
堆中每个父节点的元素值都大于等于其孩子结点(如果存在),这样的堆就是一个最大堆
因此,最大堆中的最大元素值出现在根结点(堆顶)
节点与数组索引关系
对于给定的某个结点的下标i,可以很容易的计算出这个结点的父结点、孩子结点的下标,而且计算公式很漂亮很简约
第二块,怎么将堆调整为最大堆,这部分是重点
整个过程如下图所示
在4,14,7这个小堆里边,父节点4小于左孩子14,所以两者交换
在4,2,8这个小堆里边,父节点4小于右孩子8,所以两者交换
上图展示了一趟调整的过程,这个过程递归实现,直到调整为最大堆为止
第三块,堆排序介绍
堆排序就是把堆顶的最大数取出,
将剩余的堆继续调整为最大堆,具体过程在第二块有介绍,以递归实现
剩余部分调整为最大堆后,再次将堆顶的最大数取出,再将剩余部分调整为最大堆,这个过程持续到剩余数只有一个时结束
下边三张图详细描述了整个过程
参考文章
http://blog.kingsamchen.com/archives/547#viewSource
原文地址:http://www.cnblogs.com/kkun/archive/2011/11/23/2260312.html
- 经典排序算法
- 【经典算法】快速排序
- 【经典算法】堆排序
- 经典排序算法集合
- zz 经典排序算法
- JAVA经典排序算法
- 冒泡---经典排序算法
- 经典排序算法
- 常见经典排序算法
- 经典排序算法
- 经典算法:快速排序
- 经典排序算法
- 经典算法---冒泡排序
- 常见经典排序算法
- [经典排序算法][集锦]
- [经典排序算法][集锦]
- 经典排序算法
- [经典排序算法][集锦]
- java中synchronized的用法
- 细细品味Flex——BlazeDS开发指南
- SSH2三大框架整合警告
- C#编写自定义控件心得
- c_HelloWorld
- 经典排序算法
- 关于数据库中的事务(transaction),程序员必须记住的三点
- zoj2723
- C#自定义控件-事件-委托
- 事情好多啊
- zoj2772
- 几句话弄清楚Java参数传值还是传引用
- 基于蚁群算法求解求解TSP问题(JAVA)
- zoj2829