排序比较

各种排序运行时间比较

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

算法 最坏情况运行时间 平均情况/期望运行时间
插入排序 θ(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);
            }
        }
    }

并利用如下测试代码进行测试(其中通过改变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();
        }
    }

以下比较不同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

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

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

时间: 2024-10-15 18:32:45

排序比较的相关文章

经典排序算法 - 冒泡排序Bubble sort

 原文出自于 http://www.cnblogs.com/kkun/archive/2011/11/23/bubble_sort.html 经典排序算法 - 冒泡排序Bubble sort 原理是临近的数字两两进行比较,按照从小到大或者从大到小的顺序进行交换, 这样一趟过去后,最大或最小的数字被交换到了最后一位, 然后再从头开始进行两两比较交换,直到倒数第二位时结束,其余类似看例子 例子为从小到大排序, 原始待排序数组| 6 | 2 | 4 | 1 | 5 | 9 | 第一趟排序(外循环) 第

算法 希尔排序

希尔排序 Shell Sort 介绍: 希尔排序(Shell Sort)也称缩小增量排序,是直接插入排序算法的一种更高效的改进版本. 该方法的基本思想是:先将整个待排元素序列分割成若干个子序列(由相隔某个"增量"的元素组成的)分别进行直接插入排序,然后依次缩减增量再进行排序,待整个序列中的元素基本有序(增量足够小)时,再对全体元素进行一次直接插入排序.因为直接插入排序在元素基本有序的情况下(接近最好情况),效率是很高的,因此希尔排序在时间效率比直接插入排序有较大提高. 执行流程: 首先

算法 排序NB二人组 堆排序 归并排序

参考博客:基于python的七种经典排序算法     常用排序算法总结(一) 序前传 - 树与二叉树 树是一种很常见的非线性的数据结构,称为树形结构,简称树.所谓数据结构就是一组数据的集合连同它们的储存关系和对它们的操作方法.树形结构就像自然界的一颗树的构造一样,有一个根和若干个树枝和树叶.根或主干是第一层的,从主干长出的分枝是第二层的,一层一层直到最后,末端的没有分支的结点叫做叶子,所以树形结构是一个层次结构.在<数据结构>中,则用人类的血统关系来命名,一个结点的分枝叫做该结点的"

数字在排序数组中出现的次数

题目:统计一个数字在排序数组中出现的次数.例如输入排序数组{1,2,3,3,3,3,4,5}和数字3,由于3在这个数组中出现了4次,因此输出4. 程序实现: import java.util.Scanner; public class Test38 { public static void main(String[] args) { /**  * 初始化数组,测试数据可以多种途径初始化  */   Scanner in = new Scanner(System.in); /*int[] a = 

算法 排序lowB三人组 冒泡排序 选择排序 插入排序

参考博客:基于python的七种经典排序算法   [经典排序算法][集锦]     经典排序算法及python实现 首先明确,算法的实质 是 列表排序.具体就是操作的列表,将无序列表变成有序列表! 一.排序的基本概念和分类 所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作.排序算法,就是如何使得记录按照要求排列的方法. 排序的稳定性: 经过某种排序后,如果两个记录序号同等,且两者在原无序记录中的先后秩序依然保持不变,则称所使用的排序方法是稳定的,反之是不稳定

C/C++算法竞赛入门经典Page11 例题1-5 三整数排序

题目:输入3个整数,从小到大排序后输出 样例输入: 20 7 33 样例输出: 7 20 33 首先,先声明三个整数a,b,c和一个临时变量t: int a,b,c,t;//1,b,c为三个整数,t为临时变量 输入三个整数: scanf("%d%d%d",&a,&b,&c); 进行3次if判断: 1.如果b>a,则a,b对调 2.如果c>a,则a,c对调 3.如果c>b,则b,c对调 代码: if(b>=a){ t=b; b=a; a=t

排序与查找

1.冒泡法排序 2.选择排序 3.二分法查找(有序数组) 4.无序数组(基本查找)

使用插件bootstrap-table实现表格记录的查询、分页、排序等处理

在业务系统开发中,对表格记录的查询.分页.排序等处理是非常常见的,在Web开发中,可以采用很多功能强大的插件来满足要求,且能极大的提高开发效率,本随笔介绍这个bootstrap-table是一款非常有名的开源表格插件,在很多项目中广泛的应用.Bootstrap-table插件提供了非常丰富的属性设置,可以实现查询.分页.排序.复选框.设置显示列.Card view视图.主从表显示.合并列.国际化处理等处理功能,而且该插件同时也提供了一些不错的扩展功能,如移动行.移动列位置等一些特殊的功能,插件可

AC日记——双栈排序 洛谷 P1155

双栈排序 思路: 二分图染+模拟: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 1005 #define maxm 2000005 int n,head[maxn],E[maxm],V[maxm],cnt,col[maxn]; int minn[maxn],ai[maxn],sta1[maxn],sta2[maxn],top1,top2; bool if_[maxn][maxn]; inline void in(

输入password登录到主界面,录入学生编号,排序后输出

n 题目:输入password登录到主界面,录入学生编号,排序后输出 n 1.  语言和环境 A.实现语言 C语言 B.环境要求 VC++ 6.0 n 2.  要求 请编写一个C语言程序.将若干学生编号按字母顺序(由小到大)输出. 程序的功能要求例如以下: 1)  输入password"admin",正确则进入主界面,错误则直接推出(exit(0)): 2)从键盘输入5个学生编号"BJS1001","BJS2001"."BJS1011&