常用排序算法哪个效率更高之从理论到实践

前面整理了一篇关于排序算法的基础类库:基本排序算法类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;
}

  • 2
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

MarcoPro

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值