C#冒泡排序,选择排序,插入排序,快速排序使用委托来测试排序时间

冒泡排序:相邻的两个元素比较,如果a[j]>a[j+1],则交换位置。一次循环,最大值放到最后位置

选择排序:以第一个元素为基准,如果a[i]>a[j],则交换位置。将最小的数放在索引0的位置,将第二个较小的数放在索引1的位置...

插入排序:将第一个元素认为是最小的,放到索引0的位置,如果第二个元素比第一个元素小,则第二个元素放到索引0的位置,第一个元素被挤到后面。第N个元素插入合适的位置:从索引0的元素开始查找,插入的位置满足a[j] <= a[N] <= a[j+1]。

快速排序:比如以第一个元素pivot作为分割数,第一次大循环将大于pivot的数放在pivot的后面,小于pivot的数放在pivot的前面。此时split所在的索引为splitIndex. 将数组分为前[0,splitIndex]和 后[splitIndex,length-1] 两部分。前、后分别进行排序,以此递归即可

在.net core3.1新建控制台应用程序SortAlgorithmDemo。

测试源程序如下:

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

namespace SortAlgorithmDemo
{
    class Program
    {
        static void Main(string[] args)
        {
            int[] array = GenerateRandomArray();
            TestSort("冒泡排序", BubbleSort, array);
            array = GenerateRandomArray();
            TestSort("选择排序", SelectSort, array);
            array = GenerateRandomArray();
            TestSort("插入排序", InsertSort, array);
            array = GenerateRandomArray();
            TestSort("快速排序", QuickSort, array);
            Console.ReadLine();
        }

        /// <summary>
        /// 测试各种排序算法的统一入口
        /// </summary>
        /// <param name="sortCategory">排序算法类型</param>
        /// <param name="actionSort">一个委托,对应使用的排序算法函数</param>
        /// <param name="array">要排序的数组</param>
        static void TestSort(string sortCategory, Action<int[]> actionSort, int[] array)
        {
            Console.WriteLine($"开始测试【{sortCategory}】...");
            PrintArray(array);
            Stopwatch stopwatch = new Stopwatch();
            stopwatch.Start();
            actionSort(array);
            stopwatch.Stop();
            Console.WriteLine($"【{sortCategory}】花费时间:【{stopwatch.Elapsed.TotalMilliseconds}】ms。排序后结果显示:");
            PrintArray(array);
        }

        /// <summary>
        /// 生成一个32个元素的随机数组
        /// </summary>
        /// <returns></returns>
        static int[] GenerateRandomArray()
        {
            int[] array = new int[32];
            for (int i = 0; i < array.Length; i++)
            {
                array[i] = new Random(Guid.NewGuid().GetHashCode()).Next(1, 1000);
            }
            return array;
        }

        /// <summary>
        /// 将数组平均分成两行,来打印
        /// </summary>
        /// <param name="array"></param>
        static void PrintArray(int[] array)
        {
            int middle = array.Length / 2;//将数组一份为2
            Span<int> spanFront = new Span<int>(array, 0, middle);
            Console.WriteLine(string.Join(",", spanFront.ToArray()));
            Span<int> spanBehind = new Span<int>(array, middle, array.Length - middle);
            Console.WriteLine(string.Join(",", spanBehind.ToArray()));
        }

        /// <summary>
        /// 冒泡排序:相邻的两个元素比较,如果a[j]>a[j+1],则交换位置。一次循环,最大值放到最后位置
        /// </summary>
        /// <param name="array"></param>
        static void BubbleSort(int[] array)
        {
            for (int i = 0; i < array.Length - 1; i++)
            {
                for (int j = 0; j < array.Length - 1 - i; j++)
                {
                    if (array[j] > array[j + 1])
                    {
                        int temp = array[j];
                        array[j] = array[j + 1];
                        array[j + 1] = temp;
                    }
                }
            }
        }

        /// <summary>
        /// 选择排序:以第一个元素为基准,如果a[i]>a[j],则交换位置。将最小的数放在索引0的位置,将第二个较小的数放在索引1的位置...
        /// </summary>
        /// <param name="array"></param>
        static void SelectSort(int[] array)
        {
            for (int i = 0; i < array.Length; i++)
            {
                for (int j = i + 1; j < array.Length; j++)
                {
                    if (array[i] > array[j])
                    {
                        int temp = array[i];
                        array[i] = array[j];
                        array[j] = temp;
                    }
                }
            }
        }

        /// <summary>
        /// 插入排序:将第一个元素认为是最小的,放到索引0的位置,如果第二个元素比第一个元素小,则第二个元素放到索引0的位置,第一个元素被挤到后面。
        /// 第N个元素插入合适的位置:从索引0的元素开始查找,插入的位置满足a[j] &lt;= a[N] &lt;= a[j+1]。
        /// </summary>
        /// <param name="array"></param>
        static void InsertSort(int[] array)
        {
            for (int i = 1; i < array.Length; i++)
            {
                //插入的索引位置共有3种:头、中间、尾
                //当前元素需要插入的索引:默认插入位置不变,就是尾巴位置
                int insertIndex = i;
                //如果当前索引小于最小的,则插入索引0的位置,就是头部位置
                if (array[i] < array[0])
                {
                    //插入索引0的位置
                    insertIndex = 0;
                }
                else
                {
                    //找出第一个 当前值 在 array[j]与array[j + 1]之间,则插入的索引(j + 1)
                    for (int j = 0; j + 1 < i; j++)
                    {
                        if (array[j] < array[i] && array[i] <= array[j + 1])
                        {
                            insertIndex = j + 1;
                            break;
                        }
                    }
                }

                //从insertIndex到i之间的元素整体向后移动一个索引,将当前元素插入到索引【insertIndex】位置
                int temp = array[i];//记录当前值
                for (int j = i; j > insertIndex; j--)
                {
                    array[j] = array[j - 1];
                }
                array[insertIndex] = temp;
            }
        }

        /// <summary>
        /// 快速排序:比如以第一个元素pivot作为分割数,第一次大循环将大于pivot的数放在pivot的后面,小于pivot的数放在pivot的前面。此时split所在的索引为splitIndex
        /// 将数组分为前[0,splitIndex]和 后[splitIndex,length-1] 两部分。前、后分别进行排序,以此递归即可
        /// </summary>
        /// <param name="array"></param>
        static void QuickSort(int[] array)
        {
            PartialSort(array, 0, array.Length - 1);
        }

        /// <summary>
        /// 获取分割点索引,并将大值放在分割点的后面,小值放在分割点的前面。
        /// 然后独自对分割后的两个【部分数组】进行独自排序
        /// </summary>
        /// <param name="array"></param>
        /// <param name="fromIndex"></param>
        /// <param name="toIndex"></param>
        static void PartialSort(int[] array, int fromIndex, int toIndex) 
        {
            if (toIndex <= fromIndex)
                return;
            //获取分割索引,本次分割将小值放在分割索引的前面,将大值放在分割索引的后面
            int splitIndex = GetPartialIndex(array, fromIndex, toIndex);
            //前面的一部分独自排序
            PartialSort(array, fromIndex, splitIndex - 1);
            //后面的一部分独自排序
            PartialSort(array, splitIndex + 1, toIndex);
        }

        /// <summary>
        /// 进行一次大的排序,以起始索引的值作为支点pivot(分割点),将大于pivot放在右边,小于pivot放在左边
        /// </summary>
        /// <param name="array"></param>
        /// <param name="fromIndex"></param>
        /// <param name="toIndex"></param>
        /// <returns></returns>
        static int GetPartialIndex(int[] array, int fromIndex, int toIndex)
        {
            //比如以第一个元素为支点pivot,分割点
            int pivotValue = array[fromIndex];
            while (fromIndex < toIndex)
            {
                //从后向前查找比支点pivot小的值
                while (fromIndex < toIndex && pivotValue < array[toIndex])
                {
                    toIndex--;
                }
                //比pivot小的放左边
                array[fromIndex] = array[toIndex];
                //从前向后搜索比pivot大的值,比pivot大的放右边
                while (fromIndex < toIndex && array[fromIndex] < pivotValue)
                {
                    fromIndex++;
                }
                //比pivot大的放右边
                array[toIndex] = array[fromIndex];
            }
            //循环结束,此时 fromIndex=toIndex。
            //左边都比pivot小,右边都比pivot大。
            array[fromIndex] = pivotValue;
            return toIndex;
        }
    }
}
 

程序运行结果:

很多人都普遍认为 快速排序 是最快的。但实际测试反而比冒泡,插入排序还要慢。

原因:只有32个元素进行排序。递归对栈stack进行操作需要耗时少许时间。

快速排序多用于随机海量数据进行排序,当数组元素较少时,建议不要使用快速排序。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

斯内科

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

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

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

打赏作者

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

抵扣说明:

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

余额充值