码迷,mamicode.com
首页 > 编程语言 > 详细

排序比较

时间:2015-01-28 21:04:02      阅读:337      评论:0      收藏:0      [点我收藏+]

标签:

各种排序运行时间比较

以下表格展现各算法的运行时间:

算法 最坏情况运行时间 平均情况/期望运行时间
插入排序 θ(n2) θ(n2)
归并排序 θ(nlgn) θ(nlgn)
堆排序 O(nlgn)
快速排序 θ(n2) θ(nlgn)

建立一个类,将之前写的各种排序算法纳入其中,Code如下:

技术分享
    class SortMehod
    {   //-----快速排序----
        private int Partition(List<int> array, int p, int r)
        {
            int x = array[r], temp;
            int i = p - 1;         //类似于一个指示,在该指示左边的值均小于x
            for (int j = p; j < r; j++)
            {
                if (array[j] <= x)    //遇到比x小的,放到i的下一位去
                {
                    i++;
                    temp = array[i];
                    array[i] = array[j];
                    array[j] = temp;
                }
            }
            array[r] = array[i + 1];
            array[i + 1] = x;
            return i + 1;
        }
        public void QuickSort(List<int> array, int p, int r)
        {
            int q;
            if (p < r)  //进行递归的条件
            {
                q = Partition(array, p, r);
                QuickSort(array, p, q - 1);
                QuickSort(array, q + 1, r);
            }
        }
        //-----归并排序----
        private void Merge(List<int> array, int p, int q, int r)
        {
            int len1 = q - p + 1, n1 = 0;  //用于临时存储两边元素的数组的参数
            int len2 = r - q, n2 = 0;
            int[] arr1 = new int[len1];   //建立两个临时数组,用于储存数组值
            int[] arr2 = new int[len2];
            for (int i = 0; i < len1; i++)  //将array值拷贝到临时存放数组
                arr1[i] = array[p + i];
            for (int j = 0; j < len2; j++)
                arr2[j] = array[j + q + 1];
            for (int k = p; k < r + 1; k++)  //将两个数组中的值按升序放回到array数组中
            {
                if (arr1[n1]<arr2[n2])
                    array[k] = arr1[n1++];
                else
                    array[k] = arr2[n2++];
                if (n1 == len1)       //此处为arr1数组已全部取完后的处理情况
                {
                    for (int m = k + 1; m < r + 1; m++)
                        array[m] = arr2[n2++];
                    break;
                }
                if (n2 == len2)
                {
                    for (int m = k + 1; m < r + 1; m++)
                        array[m] = arr1[n1++];
                    break;
                }
            }
        }
        public void MergeSort(List<int> array, int p, int r)
        {
            if (p < r)
            {
                int q = (p + r) / 2;
                MergeSort(array, p, q);
                MergeSort(array, q + 1, r);
                Merge(array, p, q, r);
            }
        }
        //----插入排序-----
        public void InsertSort(List<int> array)
        {
            for (int i = 1; i < array.Count; i++)   //将第i个数插入已排好序的[0...i-1]中
            {
                int key = array[i];
                int position = i;  //用于记录将要插入的位置
                for (int j = i; j >= 0; j--) //将要前面数与要插入数进行比较,如果比key大,往后移一位
                {
                    if (array[j] > key) //由于int实现了IComparable接口
                    {
                        array[j + 1] = array[j];
                        position = j;
                    }
                }
                array[position] = key;
            }
        }
        //----堆排序----
        private void MaxHeapify(List<int> array, int i, int length) //此处加个length是为了堆排序时取出最大下标
        {
            int largest = i;
            int left = 2 * i + 1, right = 2 * i + 2;
            if (left < length && array[left] > array[i]) //找出i,2i+1,2i+2中最大那个值的下标
                largest = left;
            if (right < length && array[right] > array[largest])
                largest = right;
            if (largest != i)
            {
                int temp = array[i];       //将最大值放入i中
                array[i] = array[largest];
                array[largest] = temp;
                MaxHeapify(array, largest, length);   //将被改动那个下标再次递归进行维护
            }
        }
        private void BuildMaxHeap(List<int> array)
        {
            for (int i = (array.Count - 2) / 2; i >= 0; i--) //此处i从(n-2)/2开始,因为没有子节点的节点无需进行"维护"
                MaxHeapify(array, i, array.Count);
        }
        public void HeapSort(List<int> array)
        {
            BuildMaxHeap(array);
            for (int i = array.Count - 1; i > 0; i--) //每次将堆得根与最大下标的值互换,并将最大下标"剔除"
            {
                int temp = array[i];
                array[i] = array[0];
                array[0] = temp;
                MaxHeapify(array, 0, i);
            }
        }
    }
View Code

并利用如下测试代码进行测试(其中通过改变N的大小,来改变排序的量)

技术分享
    class Program
    {
        static void Main(string[] args)
        {
            int N = 100000;
            Console.WriteLine("几种排序算法的性能比较:");
            Random rnd=new Random();
            SortMehod sort = new SortMehod();
            Stopwatch sw = new Stopwatch();    //用于计时的代码
            List<int> arr1 = new List<int>();
            List<int> arr2 = new List<int>();
            List<int> arr3 = new List<int>();
            List<int> arr4 = new List<int>();
            List<int> arr5 = new List<int>();
            for(int i=0;i<N;i++)
                arr1.Add(rnd.Next(0,N));
            foreach(int a in arr1)
            {
                arr2.Add(a);
                arr3.Add(a);
                arr4.Add(a);
                arr5.Add(a);
            }     
            Console.Write("归并排序耗时:    ");
            sw.Reset();
            sw.Start();
            sort.MergeSort(arr2,0,arr2.Count-1);
            sw.Stop();
            TimeSpan ts = sw.Elapsed;
            Console.Write("{0} ms", ts.TotalMilliseconds);
            Console.WriteLine();
            Console.Write("堆排序耗时:      ");
            sw.Reset();
            sw.Start();
            sort.HeapSort(arr3);
            sw.Stop();
            ts = sw.Elapsed;
            Console.Write("{0} ms", ts.TotalMilliseconds);
            Console.WriteLine();
            Console.Write("快速排序耗时:    ");
            sw.Reset();
            sw.Start();
            sort.QuickSort(arr4,0,arr4.Count-1);
            sw.Stop();
            ts = sw.Elapsed;
            Console.Write("{0} ms", ts.TotalMilliseconds);
            Console.WriteLine();
            Console.Write("自带排序耗时:    ");
            sw.Reset();
            sw.Start();
            arr5.Sort();
            sw.Stop();
            ts = sw.Elapsed;
            Console.Write("{0} ms", ts.TotalMilliseconds);
            Console.WriteLine();
            Console.Write("插入排序耗时:    ");
            sw.Reset();
            sw.Start();
            sort.InsertSort(arr1);
            sw.Stop();
            ts = sw.Elapsed;
            Console.Write("{0} ms", ts.TotalMilliseconds);
            Console.WriteLine();
            Console.ReadKey();
        }
    }
View Code

 以下比较不同N情况下不同算法,以及List自带的Sort的运行时间:

①N=1000(测试四次的结果如下)

N=1000
归并排序 1.9566 1.6052 1.3499 1.5165
堆排序 2.1112 2.0532 1.6554 1.8805
快速排序 1.214 1.4247 1.077 1.1416
自带排序 0.1171 0.1153 0.1165 0.1122
插入排序 7.9769 9.9052 8.8179 9.5882

②N=10000(测试四次的结果如下)

N=10000
归并排序 7.5157 8.2317 8.2776 8.4587
堆排序 12.573 14.3051 14.4609 13.5613
快速排序 4.8044 5.3743 5.2867 5.7667
自带排序 0.8953 1.1639 1.1706 0.8995
插入排序 686.8003 773.3787 797.0869 691.3083

③N=100000(测试四次的结果如下)

N=100000
归并排序 65.0672 67.563 68.7529 65.7621
堆排序 171.2636 175.288 171.3451 179.607
快速排序 57.0721 52.1234 53.8658 54.4496
自带排序 12.3026 11.6844 11.1253 10.4057
插入排序 63958.22 62566.23 62345.36 62768.1

④N=1000000(插入明显掉队,踢踢踢)

N=1000000
归并排序 768.613 751.9485 747.2539 758.8756
堆排序 2137.371 1682.949 1660.753 1701.584
快速排序 681.6198 635.0487 618.8926 634.7716
自带排序 129.4649 133.6034 143.659 130.8897

⑤N=10000000(插入明显掉队,踢踢踢)

N=10000000
归并排序 8052.816 8128.458 8020.946 8012.873
堆排序 21705.06 22002.53 21969.92 21700.73
快速排序 7168.563 7285.977 7214.105 7078.338
自带排序 1500.894 1545.198 1536.903 1516.837

由以上可以明显看到   自带排序(据说也是快速排序,为毛快那么多!不科学)>快速排序>归并排序>堆排序>插入排序

自带排序的源码怎么看呢?以及自带排序为什么比快速排序快呢?(希望知道的朋友告知一下)

排序比较

标签:

原文地址:http://www.cnblogs.com/Paul-chen/p/4257050.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!