iis服务器助手广告广告
返回顶部
首页 > 资讯 > 后端开发 > 其他教程 >C#实现快速排序算法
  • 719
分享到

C#实现快速排序算法

2024-04-02 19:04:59 719人浏览 薄情痞子
摘要

快速排序是应用最广泛的排序算法,流行的原因是它实现简单,适用于各种不同情况的输入数据且在一般情况下比其他排序都快得多。 快速排序是原地排序(只需要一个很小的辅助栈),将长度为 N 的

快速排序是应用最广泛的排序算法,流行的原因是它实现简单,适用于各种不同情况的输入数据且在一般情况下比其他排序都快得多。

快速排序是原地排序(只需要一个很小的辅助栈),将长度为 N 的数组排序所需的时间和 N lg N 成正比。

1.算法

快速排序也是一种分治的排序算法。它将一个数组分成两个子数组,将两部分独立地排序。

快速排序和归并排序是互补:归并排序是将数组分成两个子数组分别排序,并将有序数组归并,这样数组就是有序的了;而快速排序将数组通过切分变成部分有序数组,然后拆成成两个子数组,当两个子数组都有序时整个数组也就有序了。

归并排序的递归调用发生在处理数组之前,快速排序的递归调用是发生在处理数组之后。

快速排序中切分的位置取决于数组的内容。

    public class Quick: BaseSort
    {
        public new static long usedTimes = 0;
        public static void Sort(IComparable[] a)
        {
            usedTimes = 0;
            Stopwatch timer = new Stopwatch();
            timer.Start();
            Sort(a,0,a.Length-1);
            timer.Stop();
            usedTimes = timer.ElapsedMilliseconds;
        }

        public static void Sort(IComparable[] a, int lo, int hi)
        {
            if (hi <= lo)
                return;

            //切分
            int j = Partition(a,lo,hi);
            //Console.WriteLine(j);
            Sort(a,lo,j-1);
            Sort(a,j+1,hi);
        }
        public static int CompareCount = 0;
        public static int Partition(IComparable[] a, int lo, int hi)
        {
            int i = lo;
            int j = hi + 1;
            var v = a[lo];

            while (true)
            {
                //从左往右依次和 v 比较,直到找到 >= v 的值 索引i (索引i 左边的值都小于切分元素)
                while (Less(a[++i], v))
                {
                    CompareCount++;
                    if (i == hi)
                        break;
                }

                //从右往左依次和 v 比较,直到找到 <= v 的值 索引j(索引j 右边的值都大于于切分元素)
                while (Less(v, a[--j]))
                {
                    CompareCount++;
                    if (j == lo)
                        break;
                }

                //当 i >= j 时就找到了切分元素位置,位置为 j ,退出循环
                if (i >= j)
                    break;
                //如果 i 和 j 没有相遇,将 i 和 j 的值交换,继续循环,直到相遇
                Exch(a,i,j);
            }

            //将切分元素放到切分位置 j 
            Exch(a,lo,j);
            return j;
        }
    }

该算法的关键在于切分 ,在Sort(IComparable[] a, int lo, int hi) 方法中,切分后 a[lo] 到 a[j-1] 中的所有元素都不大于 a[ j ] ,a[j+1] 到 a[ hi ] 中的所有元素都不小于 a[ j ] ,然后对左子数组和右子数组进行递归。因为切分的过程总能排定一个元素,当切分到剩一个元素时,子数组就是有序的。当左数组和右数组都有序时,整个数组也就有序了。

切分方法:先随意取 a[ lo ] 作为切分元素,即那个将被排定的元素。然后从数组的左端向右扫描直到找到大于等于它的元素,再从数组右端向左开始扫描直到找到小于等于它的元素。如果找到的这两个元素不是同一个元素(索引不同),那么这个元素就还没被排定;如果相同意味着这个元素已被排定。如果没被排定,就交换这两个元素,继续扫描,直到左右索引相遇,即可返回将切分元素和找到的索引位置的元素交换,返回索引 j 。

排序实列:

注意点

1. 原地切分

该算法是原地切分,如果使用辅助数组需要将切分后的数组复制回去的额外开销。

2.越界

要防止扫描指针跑出数组边界。

3.保持随机性

该算法对所有子数组都是一视同仁的。

4.终止循环

该算法有三个循环都要注意什么时候终止。

5.处理切分元素值有重复的情况

该算法左右扫描都会在遇到相等值时停下来,尽管这样会不必要的等值交换,但在某些情况下能够避免算法的运行时间变为平方级别。

6.终止递归

任何递归调用都要先考虑什么时候终止。

2.性能

快速排序运行时间的增长量级为 NlogN 。

快速排序切分方法的内循环用一个递增的索引将数组元素和一个定值比较,这种循环很简洁。它比归并排序和希尔排序都快,因为归并排序和希尔排序在内循环中移动元素。

快速排序的另一个速度优势在于它的比较次数很少(如果每次都对半分的话需要 N/2 * logN 次比较)。但是排序效率还是依赖切分数组的效果,而这依赖于切分元素的值 。切分一个较大的数据组,切分可能发生在任何一个位置。

快速排序的最好情况是每次都能将数组对半分。在这种情况下快速排序所用的比较次数正好满足分治递归的 C(N) = 2C(N/2) + N 公式。2C(N/2) 表示将两个子数组排序的成本, N 表示 切分元素和所有数组元素比较的成本。C(N) ~ N log N 。平均而言切分元素都能落在数组中间。

快速排序在最坏情况下需要 ~ N^2 / 2 次比较,即每次切分总有一个数组是空的(逆序),比较次数为: N + (N-1)+ (N-2) ...+2+1 = (N+1)N/2 。这种情况不仅算法所需的时间是平方级别的,所需的空间是线性的。

快速排序平均需要 ~ 2N lnN 次比较(以及1/6的交换)。归并排序也可以做到这个量级,但是快速排序移动数据次数少(即交换次数),所以快速排序更快,尽管比较次数比归并排序多了约 39%。

当数组切分不平衡时(第一次用最小的切分,第二次用第二小的切分...)会倒置一个大数组需要切分很多次(上面说的逆序),所以非重复数组需要随机打乱;当存在大量重复元素时,排序过程会进行很多次交换,重复数组可以使用稍后提到的三向切分的快速排序。

3.改进

1.切换到插入排序

当将一个大数组切分成一定小的数组时使用插入排序给小数组排序,这样就不需要继续递归调用 Sort() 方法了。

将if (hi <= lo)return; 改为

if(hi <= lo + M){ Insertion.Sort(a, lo, hi); return;}

转换参数 M 的最佳值和系统相关,5 ~ 15 最佳。

2.三取样切分

改进快速排序性能的另一个方法是使用子数组的一小部分元素的中位数来切分数组。这样得到的切分更好,但是需要计算中位数。一般取样大小为3并用大小居中的元素切分最好。

3.熵最优排序

实际应用中经常会出现大量重复元素的数组,这会影响快排的性能。例如,一个全部重复的子数组就不需要排序了,但上面的算法会继续切分。三向切分的快速排序可以将有大量重复元素的数组从线性对数级别提高到线性级别。

三向切分是将数组切分成小于,等于和大于三部分。它从左到右遍历数组一次,维护一个指针 lt 使得 a[lo ... lt-1] 中的元素都小于 v(切分元素),一个指针 gt 使得 a[gt+1 ... hi] 中的元素都大于 v ,一个指针 i 使得 a[ lt ... i ] 中元素都等于 v , a[ i ... gt ] 中的元素都还未确定。一开始 lo 和 i 相等:

  • a[i]小于v:与 a[i] 交换 a[lt] 并增加lt 和i
  • a[i]大于v:将 a[i] 与  a[gt] 交换并减少gt
  • a[i]等于v:递增i

    public class Quick: BaseSort
    {
        public new static long usedTimes = 0;

        //三向切分
        public static void Sort3Way(IComparable[] a)
        {
            usedTimes = 0;
            Stopwatch timer = new Stopwatch();
            timer.Start();
            Sort3Way(a, 0, a.Length - 1);
            timer.Stop();
            usedTimes = timer.ElapsedMilliseconds;
        }
        public static void Sort3Way(IComparable[] a, int lo, int hi)
        {
            if (hi < lo)
                return;
            int lt = lo, i = lo + 1, gt = hi;
            IComparable v = a[lo];
            while (i <= gt)
            {
                int cmp = a[i].CompareTo(v);
                if (cmp < 0)
                    Exch(a, lt++, i++);
                else if (cmp > 0)
                    Exch(a, i, gt--);
                else
                    i++;

            }

            Sort3Way(a,lo,lt-1);
            Sort3Way(a,gt+1,hi);
        }
    }

对于若干不同主键的随机数组,归并排序的时间复杂度是线性对数的,而三向切分快速排序是线性的。三向切分最坏的情况是所有键值都不同。当存在重复主键时,性能回避归并排序好很多。

到此这篇关于C#实现快速排序的文章就介绍到这了。希望对大家的学习有所帮助,也希望大家多多支持编程网。

--结束END--

本文标题: C#实现快速排序算法

本文链接: https://www.lsjlt.com/news/146181.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • C#实现快速排序算法
    快速排序是应用最广泛的排序算法,流行的原因是它实现简单,适用于各种不同情况的输入数据且在一般情况下比其他排序都快得多。 快速排序是原地排序(只需要一个很小的辅助栈),将长度为 N 的...
    99+
    2022-11-13
  • C语言实现快速排序算法实例
    首先我们要对一组数据进行排序: 在数组中选一个基准数(通常为数组第一个,黄圈圈标记了); 将数组中小于基准数的数据移到基准数左边,大于基准数的移到右边,怎么移动,后面说; 对于基准数...
    99+
    2022-11-13
  • C语言如何实现快速排序算法
    这篇文章将为大家详细讲解有关C语言如何实现快速排序算法,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。代码#define  _CRT_SECURE_NO_WARNINGS 1/...
    99+
    2023-06-22
  • C/C++实现快速排序算法的两种方式实例
    目录介绍流程如下实现方式一方式二总结介绍 快速排序是对冒泡排序算法的一种改进,快速排序算法通过多次比较和交换来实现排序。 流程如下 (图片来自百度) 实现 以下有两种实现方式,说是...
    99+
    2022-11-12
  • C语言实现单链表的快速排序算法
    目录背景设计思路算法主要步骤快速排序算法实现整个程序源代码测试案例总结背景 传统QuickSort算法最大不足之处在于,由于其基于可索引存储结构设计(一般为数组或索引表),因而无法用...
    99+
    2022-11-13
  • C++快速排序算法简明理解
    目录一、问题描述二、想法三、算法实现总结一、问题描述 [问题] 应用快速排序方法对一个记录序列进行升序排列。快速排序(quick sort)的分治策略如下。 (1)划分:选定一个记录...
    99+
    2022-11-13
  • python快速排序算法怎么实现
    快速排序是一种常用的排序算法,其算法思想是通过递归地将数组分为较小和较大的两个子数组,然后不断重复这个过程,直到整个数组有序。下面是...
    99+
    2023-08-15
    python
  • go快速排序算法怎么实现
    快速排序(Quick Sort)是一种高效的排序算法,它的基本思想是选择一个基准元素,通过一趟排序将数组分成两部分,其中一部分的所有...
    99+
    2023-10-26
    go
  • 使用 Python 实现快速排序算法
    快速排序是一种高效的排序算法,它采用分治法的思想进行排序。在 Python 中,我们可以使用以下代码实现快速排序算法: def quick_sort(arr): if len(arr) ...
    99+
    2023-09-02
    排序算法 算法
  • java如何实现快速排序算法
    这篇文章将为大家详细讲解有关java如何实现快速排序算法,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。快速排序算法使用的分治法策略来把一个序列分为两个子序列来实现排序的思路:1.从数列中挑出一个元素,称为...
    99+
    2023-06-02
  • java 排序算法之快速排序
    目录简单介绍基本思想思路分析代码实现推导实现完整实现大数据量耗时测试性能分析简单介绍 快速排序(Quicksort) 是对 冒泡排序的一种改进。 基本思想 快速排序算法通过多次比较和...
    99+
    2022-11-12
  • 超详细解析C++实现快速排序算法的方法
    目录一、前言1.分治算法2.分治算法解题方法二、快速排序1.问题分析2.算法设计3.算法分析三、AC代码一、前言 1.分治算法 快速排序,其实是一种分治算法,那么在了解快速排序之前,...
    99+
    2022-11-13
  • 快速掌握java排序算法-快速排序(图文)
    概念快速排序属于交换排序,主要步骤是使用基准元素进行比较,把小于基准元素的移动到一边,大于基准元素的移动到另一边。从而把数组分成两部分,然后再从这两部分中选取出基准元素,重复上面的步骤。过程如下:(推荐视频:java视频教程) 紫色:基准...
    99+
    2017-05-20
    java教程 快速排序 算法
  • 快速排序的算法思想及Python版快速排序的实现示例
    快速排序是C.R.A.Hoare于1962年提出的一种划分交换排序。它采用了一种分治的策略,通常称其为分治法(Divide-and-ConquerMethod)。 1.分治法的基本思想 分治法的基本思想是:...
    99+
    2022-06-04
    快速 示例 算法
  • C语言实现快速排序
    目录1. hoare法方法与步骤代码实现2. 挖坑法方法与步骤代码实现3. 前后指针法方法与步骤代码实现4. 快速排序的缺点与优化1.快速排序的缺点2.快速排序的优化① 三数取中法选...
    99+
    2023-05-14
    C语言快速排序算法 C语言快速排序 C语言排序算法
  • C++归并法+快速排序实现链表排序的方法
    本文主要介绍了C++归并法+快速排序实现链表排序的方法,分享给大家,具体如下: 我们可以试用归并排序解决: 对链表归并排序的过程如下。 找到链表的中点,以中点为分界,将链表拆分成...
    99+
    2022-11-12
  • Python中怎么实现快速排序算法
    Python中怎么实现快速排序算法,相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。Python实现快速排序算法快速排序算法是一种基于交换的高效的排序算法,由C.R.A.Hoare...
    99+
    2023-06-02
  • Python实现快速排序算法及去重的快速排序的简单示例
    快速排序由于排序效率在同为O(N*logN)的几种排序方法中效率较高,因此经常被采用。 该方法的基本思想是: 1.先从数列中取出一个数作为基准数。 2.分区过程,将比这个数大的数全放到它的右边,小于或等于它...
    99+
    2022-06-04
    快速 示例 算法
  • C语言实现交换排序算法(冒泡,快速排序)的示例代码
    目录前言一、冒泡排序1.基本思想2.优化3.扩展二、快速排序1.基本思想2.优化3.代码前言 查找和排序是数据结构与算法中不可或缺的一环,是前辈们在算法道路上留下的重要且方便的一些技...
    99+
    2022-11-13
  • C语言常见排序算法之交换排序(冒泡排序,快速排序)
    目录前言1.交换排序——冒泡排序1.1 算法思想1.2 动图演示1.3 冒泡最好的情况 2. 交换排序——快速排序...
    99+
    2022-11-13
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作