插入排序——C#实现

来源:互联网 发布:网络电玩加盟多少钱 编辑:程序博客网 时间:2024/06/04 19:41


       一 算法描述

       插入排序是一种针对少量元素的有效的排序算法。其基本操作是将一个数据插入到已经排好序的有序数据中,从而得到一个新的、个数加一的有序数据。在《算法导论》一书中,作者以人们常用的排序扑克牌的例子来说明此算法:

       “开始时,我们的左手为空并且桌子上的牌面向下。然后,我们毎次从桌子上拿走一张牌并将它插入左手中正确的位置。为了找到一张牌的正确位置,我们从右到左将它与已在手中的每张牌进行比较。拿在左手上的牌总是排序好的。”

       

       (图片截取自《算法导论》)


       二 算法实现(c#)

       1 用于整数数组的升序排序

        public static void InsertionSort(int[] array)        {            if (array == null || array.Length < 2)            {                return;            }            int key;            for (int i = 1; i < array.Length; i++)            {                key = array[i];                int j = i - 1;                while (j >= 0 && key < array[j])                {                    array[j + 1] = array[j];                    j--;                }                array[j + 1] = key;            }        }


       2 用于整数数组的降序排序

        public static void InsertionDesSort(int[] array)        {            if (array == null || array.Length < 2)            {                return;            }            int key;            for (int i = 1; i < array.Length; i++)            {                key = array[i];                int j = i - 1;                while (j >= 0 && key > array[j])                {                    array[j + 1] = array[j];                    j--;                }                array[j + 1] = key;            }        }


       3 泛型版本

        public static void InsertionSort<T>(T[] array, Comparison<T> comparison)        {            if (array == null || array.Length < 2)            {                return;            }            T key;            for (int i = 1; i < array.Length; i++)            {                key = array[i];                int j = i - 1;                while (j >= 0 && comparison(array[j], key) > 0)                {                    array[j + 1] = array[j];                    j--;                }                array[j + 1] = key;            }            return;        }


       三 算法分析

       1 插入排序是一种原址排序算法。在整个排序过程中只需要常数个元素存储在数组之外,即空间复杂度为O(1)。

       2 插入排序是稳定的。具有相同值的元素在输出数组中的相对次序与其在输入数组中的相对次序相同。

       3 若输入数组已经排好序,则算法运行时间未最佳情况,此时的时间复杂度是O(n);若输入数组已反向排序,则算法的运行时间未最坏情况,此时的时间复杂度为O(n^2).


       四 运行结果

       在插入排序算法中,影响算法运行时间的主要因素为内层while循环的执行次数。而内层循环的执行次数,则可以根据array[j]与key的比较次数来大致估算(此处内层循环执行的语句的数量约为比较次数的4倍)。因此,如果我们得到了比较语句的执行次数,则可以大致了解到整个算法的执行规模。

       在算法的泛型实现版本中,通过在委托传入的比较方法里加入计数语句,则能很容易的得到比较语句执行的次数。

 

        private static int AscComparison(int x, int y)        {            count++;            if (x > y)            {                return 1;            }            else if (x == y)            {                return 0;            }            else            {                return -1;            }        }

       为了测试该算法的平均运行情况,通过对10000个随机数组进行排序取平均:

        static void Main(string[] args)        {            for (int i = 0; i < 10000; i++)            {                //在1-100内产生10个随机数                int[] randomIntArray = DataCreator.CreateRandomIntArray(1, 100, 10);                Sort.InsertionSort(randomIntArray, AscComparison);                PrintAarry(randomIntArray);            }            int averageCount = count / 10000;            Console.WriteLine(averageCount);        }

       测试结果:

       n = 10,  averageCount = 29 = 0.29 * 10 ^2;

       n = 100,   averageCount = 2567 = 0.2567 * 100 ^ 2;

       n = 1000, averageCount = 250724 = 0.250724 * 1000^2

       由此可得,插入排序算法的平均运行时间复杂度也是θ(n^2).

原创粉丝点击