前面整理了一篇关于排序算法的基础类库:基本排序算法类SortHelper
这里我们来看看这几个算法哪个效率更高一点呢?
1、先从理论来看看这几个算法
1、冒泡排序法
基本思想:两两比较待排序数据元素的大小,发现两个数据元素的次序相反时即进行交换,直到没有反序的数据元素为止。
2、插入排序法
基本思想:通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。插入排序在实现上,通常采用in-place排序(即只需用到O(1)的额外空间的排序),因而在从后向前扫描过程中,需要反复把已排序元素逐步向后挪位,为最新元素提供插入空间。
3、选择排序法
基本思想:每一趟从待排序的数据元素中选出最小(或最大)的一个元素,顺序放在已排好序的数列的最后,直到全部待排序的数据元素排完。
4、希尔排序法
基本思想:先 取一个小于n的证书d1作为第一个增量,把文件的全部记录分成d1组。所有距离为d1的倍数的记录放在同一组中。先在各组内进行直接插入排序,然后取第二 个增量d2<d1重复上述的分组和排序,直到所取的增量dt=1,即所有记录放在同一组中进行直接插入排序为止。该方法实际上是一种分组插入方法。
2、写个程序来看看上面几个算法的效率怎么样
1、先看结果,随机生成一个包含20000个不重复的整数数组进行排序,记录每种排序算法的耗时情况如下:
从输出结果可以看出来,效率最低的是冒泡算法
2、源码分一下几个部分:
2.1 主方法如下
static void Main(string[] args)
{
Console.WriteLine("冒泡排序法,插入排序法,选择排序法,希尔排序法");
for (int i = 0; i < 10; i++)
{
SortAction(i);
}
Console.Read();
}
2.2 调用排序算法的方法如下
public static void SortAction(int i)
{
StringBuilder sb = new StringBuilder();
sb.Append("第"+i+"次耗时,");
int[] list = GenerateUniqueRandom(1, 100000, 20000);
int[] list1 = (int[])list.Clone();
int[] list2 = (int[])list.Clone();
int[] list3 = (int[])list.Clone();
int[] list4 = (int[])list.Clone();
Stopwatch sw = new Stopwatch();
//冒泡排序法
sw.Start();
SortHelper.BubbleSort(list1);
sw.Stop();
//Console.WriteLine("冒泡排序法用时:" + sw.ElapsedMilliseconds + "");
sb.Append(sw.ElapsedMilliseconds +",");
sw.Reset();
sw.Restart();
//插入排序法
SortHelper.InsertionSort(list2);
sw.Stop();
//Console.WriteLine("插入排序法用时:" + sw.ElapsedMilliseconds + "");
sb.Append(sw.ElapsedMilliseconds + ",");
sw.Reset();
sw.Restart();
//选择排序法
SortHelper.SelectionSort(list3);
sw.Stop();
//Console.WriteLine("选择排序法用时:" + sw.ElapsedMilliseconds + "");
sb.Append(sw.ElapsedMilliseconds + ",");
sw.Reset();
sw.Restart();
//希尔排序法
SortHelper.ShellSort(list4);
sw.Stop();
//Console.WriteLine("希尔排序法用时:" + sw.ElapsedMilliseconds + "");
sb.Append(sw.ElapsedMilliseconds + ",");
Console.WriteLine(sb);
}
通过Stopwatch记录每次排序的时间消耗,为了避免排序的偶然性,取了10次不同的数组进行排序
2.3 获取包含不重复的随机数组的方法如下
/// <summary>
/// 获取不重复的随机数组
/// </summary>
/// <param name="minValue">最小值</param>
/// <param name="maxValue">最大值</param>
/// <param name="n">数组长度</param>
/// <returns></returns>
public static int[] GenerateUniqueRandom(int minValue, int maxValue, int n)
{
//如果生成随机数个数大于指定范围的数字总数,则最多只生成该范围内数字总数个随机数
if (n > maxValue - minValue + 1)
n = maxValue - minValue + 1;
int maxIndex = maxValue - minValue + 2;// 索引数组上限
int[] indexArr = new int[maxIndex];
for (int i = 0; i < maxIndex; i++)
{
indexArr[i] = minValue - 1;
minValue++;
}
Random ran = new Random();
int[] randNum = new int[n];
int index;
for (int j = 0; j < n; j++)
{
index = ran.Next(1, maxIndex - 1);// 生成一个随机数作为索引
//根据索引从索引数组中取一个数保存到随机数数组
randNum[j] = indexArr[index];
// 用索引数组中最后一个数取代已被选作随机数的数
indexArr[index] = indexArr[maxIndex - 1];
maxIndex--; //索引上限减 1
}
return randNum;
}