排序算法—看谁速度更快(附源代码)

本文通过实验对比了多种排序算法(包括快速排序、选择排序、冒泡排序等)在相同数据集上的性能表现,并记录了每种算法所需的时间。实验采用20000个随机整数作为输入数据,重复进行了五轮测试。

这几天无聊,就去研究排序算法,话不多说,用事实说话。






using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Diagnostics;

namespace 排序算法大PK
{
    class Program
    {
        static void Main(string[] args)
        {
            Console.WriteLine("规则:取20000随机数,比较各自耗时");
            for (int i = 0; i < 5; i++)
            {
                List<int> list = new List<int>();
                //取20000个随机数到集合中
                for (int j = 0; j < 20000; j++)
                {
                    Thread.Sleep(1);
                    list.Add(new Random((int)DateTime.Now.Ticks).Next(0, 1000000));
                }
                Console.WriteLine("\n第" + i + "轮PK:");
                Stopwatch watch = new Stopwatch(); //Stopwatch类可用于准确地测量运行时间
                watch.Start(); //开始或继续测量某个时间间隔的运行时间
                var result = list.OrderBy(single => single).ToList();
                watch.Stop();
                Console.WriteLine("快速排序耗费时间:" + watch.ElapsedMilliseconds + "毫秒");
                Console.WriteLine("输出前十个数:" + string.Join(",", result.Take(10).ToList()));
                watch.Reset();
                watch.Start();
                result = DirectSequence(list);
                watch.Stop();
                Console.WriteLine("选择排序耗费时间:" + watch.ElapsedMilliseconds + "毫秒");
                Console.WriteLine("输出前十个数:" + string.Join(",", result.Take(10).ToList()));
                watch.Reset();
                watch.Start();
                result = BubbleSort(list);
                watch.Stop();
                Console.WriteLine("冒泡排序耗费时间:" + watch.ElapsedMilliseconds + "毫秒");
                Console.WriteLine("输出前十个数:" + string.Join(",", result.Take(10).ToList()));
                watch.Reset();
                watch.Start();
                result = HeapSort(list);
                watch.Stop();
                Console.WriteLine("堆排序耗费时间:" + watch.ElapsedMilliseconds + "毫秒");
                Console.WriteLine("输出前十个数:" + string.Join(",", result.Take(10).ToList()));
                watch.Reset();
                watch.Start();
                result = InsertionSort(list);
                watch.Stop();
                Console.WriteLine("插入排序耗费时间:" + watch.ElapsedMilliseconds + "毫秒");
                Console.WriteLine("输出前十个数:" + string.Join(",", result.Take(10).ToList()));
                watch.Reset();
                watch.Start();
                result = HillSort(list);
                watch.Stop();
                Console.WriteLine("希尔排序耗费时间:" + watch.ElapsedMilliseconds + "毫秒");
                Console.WriteLine("输出前十个数:" + string.Join(",", result.Take(10).ToList()));

                watch.Reset();
                watch.Start(); //开始或继续测量某个时间间隔的运行时间
                result = list.OrderByDescending(single => single).Take(10).ToList();
                watch.Stop();
                Console.WriteLine("快速排序取最大的前十个耗费时间:" + watch.ElapsedMilliseconds + "毫秒");
                Console.WriteLine("输出前十个数:" + string.Join(",", result.Take(10).ToList()));
                watch.Reset();
                watch.Start();
                result = NewHeapSort(list, 10);
                watch.Stop();
                Console.WriteLine("堆排序取最大的前十个耗费时间:" + watch.ElapsedMilliseconds + "毫秒");
                Console.WriteLine("输出前十个数:" + string.Join(",", result.Take(10).ToList()));
            }
            Console.Read();
        }

        #region 冒泡排序
        private static List<int> BubbleSort(List<int> list)
        {
            int temp = 0;
            for (int i = 0; i < list.Count - 1; i++)
            {
                for (int j = list.Count - 1; j > i; j--)
                {
                    if (list[j] < list[j - 1])
                    {
                        temp = list[j - 1];
                        list[j - 1] = list[j];
                        list[j] = temp;
                    }
                }
            }
            return list;
        }
        #endregion

        #region 选择排序
        static List<int> DirectSequence(List<int> list)
        {
            for (int i = 0; i < list.Count - 1; i++)
            {
                int min = i; //假设min的下标的值最小
                for (int j = i + 1; j < list.Count; j++)
                {
                    //如果min下标的值大于j下标的值,则记录较小值下标j
                    if (list[min] > list[j])
                    {
                        min = j;
                    }
                }
                //最后将假想最小值跟真的最小值进行交换
                var temp = list[min];
                list[min] = list[i];
                list[i] = temp;
            }
            return list;
        }
        #endregion

        #region 堆排序
        //构建堆
        static void HeapAdjust(List<int> list, int parent, int length)
        {
            //temp保存当前父节点
            int temp = list[parent];

            //得到左孩子(这可是二叉树的定义,大家看图也可知道)
            int child = 2 * parent + 1;

            while (child < length)
            {
                //如果parent有右孩子,则要判断左孩子是否小于右孩子
                if (child + 1 < length && list[child] < list[child + 1])
                    child++;

                //父亲节点大于子节点,就不用做交换
                if (temp >= list[child])
                    break;

                //将较大子节点的值赋给父亲节点
                list[parent] = list[child];

                //然后将子节点做为父亲节点,已防止是否破坏根堆时重新构造
                parent = child;

                //找到该父亲节点较小的左孩子节点
                child = 2 * parent + 1;
            }
            //最后将temp值赋给较大的子节点,以形成两值交换
            list[parent] = temp;
        }

        ///<summary>
        /// 堆排序
        ///</summary>
        ///<param name="list"></param>
        static List<int> HeapSort(List<int> list)
        {
            //list.Count/2-1:就是堆中父节点的个数
            for (int i = list.Count / 2 - 1; i >= 0; i--)
            {
                HeapAdjust(list, i, list.Count);
            }

            //最后输出堆元素
            for (int i = list.Count - 1; i > 0; i--)
            {
                //堆顶与当前堆的第i个元素进行值对调
                int temp = list[0];
                list[0] = list[i];
                list[i] = temp;

                //因为两值交换,可能破坏根堆,所以必须重新构造
                HeapAdjust(list, 0, i);
            }
            return list;
        }
        #endregion

        #region 堆排序(取前N大的数)
        ///<summary>
        /// 构建堆
        ///</summary>
        ///<param name="list">待排序的集合</param>
        ///<param name="parent">父节点</param>
        ///<param name="length">输出根堆时剔除最大值使用</param>
        static void NewHeapAdjust(List<int> list, int parent, int length)
        {
            //temp保存当前父节点
            int temp = list[parent];

            //得到左孩子(这可是二叉树的定义哇)
            int child = 2 * parent + 1;

            while (child < length)
            {
                //如果parent有右孩子,则要判断左孩子是否小于右孩子
                if (child + 1 < length && list[child] < list[child + 1])
                    child++;

                //父节点大于子节点,不用做交换
                if (temp >= list[child])
                    break;

                //将较大子节点的值赋给父亲节点
                list[parent] = list[child];

                //然后将子节点做为父亲节点,已防止是否破坏根堆时重新构造
                parent = child;

                //找到该父节点左孩子节点
                child = 2 * parent + 1;
            }
            //最后将temp值赋给较大的子节点,以形成两值交换
            list[parent] = temp;
        }

        ///<summary>
        /// 堆排序
        ///</summary>
        ///<param name="list">待排序的集合</param>
        ///<param name="top">前K大</param>
        ///<returns></returns>
        public static List<int> NewHeapSort(List<int> list, int top)
        {
            List<int> topNode = new List<int>();

            //list.Count/2-1:就是堆中非叶子节点的个数
            for (int i = list.Count / 2 - 1; i >= 0; i--)
            {
                NewHeapAdjust(list, i, list.Count);
            }

            //最后输出堆元素(求前K大)
            for (int i = list.Count - 1; i >= list.Count - top; i--)
            {
                //堆顶与当前堆的第i个元素进行值对调
                int temp = list[0];
                list[0] = list[i];
                list[i] = temp;

                //最大值加入集合
                topNode.Add(temp);

                //因为顺序被打乱,必须重新构造堆
                NewHeapAdjust(list, 0, i);
            }
            return topNode;
        }
        #endregion

        #region 插入排序
        static List<int> InsertionSort(List<int> list)
        {
            for (int i = 1; i < list.Count; i++)
            {
                var temp = list[i];
                int j;
                for (j = i - 1; j >= 0 && temp < list[j]; j--)
                {
                    list[j + 1] = list[j];
                }
                list[j + 1] = temp;
            }
            return list;
        }
        #endregion

        #region 希尔排序(“插入排序”的改进版)
        static List<int> HillSort(List<int> list)
        {
            int num = list.Count / 2; //取增量
            while (num >= 1)
            {
                for (int i = num; i < list.Count; i++) //无须序列
                {
                    var temp = list[i];
                    int j;
                    for (j = i - num; j >= 0 && temp < list[j]; j = j - num) //有序序列
                    {
                        list[j + num] = list[j];
                    }
                    list[j + num] = temp;
                }
                num = num / 2;
            }
            return list;
        }
        #endregion

    }
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值