快速排序与堆排序

2023-12-29

快速排序和堆排序都进行就地排序。哪个更好?首选哪种应用和案例?


堆排序是 O(N log N) 保证的,这比快速排序中最坏的情况要好得多。堆排序不需要更多内存来让另一个数组像合并排序那样放置有序数据。那么为什么商业应用程序坚持使用快速排序呢?与其他实现相比,快速排序有何特别之处?

我自己测试了这些算法,发现快速排序确实有一些特别之处。它运行速度很快,比Heap和Merge算法快得多。

快速排序的秘密是:它几乎不进行不必要的元素交换。交换很费时间。

使用堆排序,即使所有数据都已排序,您也将交换 100% 的元素来对数组进行排序。

如果使用合并排序,情况会更糟。您将把 100% 的元素写入另一个数组中,然后将其写回到原始数组中,即使数据已经排序。

使用快速排序,您不会交换已经订购的内容。如果你的数据是完全有序的,那么你几乎不需要交换任何东西!尽管对于最坏的情况有很多争论,但在主元的选择上稍加改进,除了获取数组的第一个或最后一个元素之外,都可以避免这种情况。如果从第一个、最后一个和中间元素之间的中间元素得到一个主元,就足以避免最坏的情况。

Quicksort的优越之处不是最坏的情况,而是最好的情况!在最好的情况下,你会进行相同数量的比较,好吧,但你几乎什么也不交换。在一般情况下,您会交换部分元素,但不是全部元素,如堆排序和合并排序。这就是快速排序的最佳时机。更少的交换,更快的速度。

下面在我的计算机上用 C# 实现,在发布模式下运行,使用中间枢轴比 Array.Sort 快 3 秒,使用改进枢轴则比 Array.Sort 快 2 秒(是的,获得良好枢轴需要一定的开销)。

static void Main(string[] args)
{
    int[] arrToSort = new int[100000000];
    var r = new Random();
    for (int i = 0; i < arrToSort.Length; i++) arrToSort[i] = r.Next(1, arrToSort.Length);

    Console.WriteLine("Press q to quick sort, s to Array.Sort");
    while (true)
    {
        var k = Console.ReadKey(true);
        if (k.KeyChar == 'q')
        {
            // quick sort
            Console.WriteLine("Beg quick sort at " + DateTime.Now.ToString("HH:mm:ss.ffffff"));
            QuickSort(arrToSort, 0, arrToSort.Length - 1);
            Console.WriteLine("End quick sort at " + DateTime.Now.ToString("HH:mm:ss.ffffff"));
            for (int i = 0; i < arrToSort.Length; i++) arrToSort[i] = r.Next(1, arrToSort.Length);
        }
        else if (k.KeyChar == 's')
        {
            Console.WriteLine("Beg Array.Sort at " + DateTime.Now.ToString("HH:mm:ss.ffffff"));
            Array.Sort(arrToSort);
            Console.WriteLine("End Array.Sort at " + DateTime.Now.ToString("HH:mm:ss.ffffff"));
            for (int i = 0; i < arrToSort.Length; i++) arrToSort[i] = r.Next(1, arrToSort.Length);
        }
    }
}

static public void QuickSort(int[] arr, int left, int right)
{
    int begin = left
        , end = right
        , pivot
        // get middle element pivot
        //= arr[(left + right) / 2]
        ;

    //improved pivot
    int middle = (left + right) / 2;
    int
        LM = arr[left].CompareTo(arr[middle])
        , MR = arr[middle].CompareTo(arr[right])
        , LR = arr[left].CompareTo(arr[right])
        ;
    if (-1 * LM == LR)
        pivot = arr[left];
    else
        if (MR == -1 * LR)
            pivot = arr[right];
        else
            pivot = arr[middle];
    do
    {
        while (arr[left] < pivot) left++;
        while (arr[right] > pivot) right--;

        if(left <= right)
        {
            int temp = arr[right];
            arr[right] = arr[left];
            arr[left] = temp;

            left++;
            right--;
        }
    } while (left <= right);

    if (left < end) QuickSort(arr, left, end);
    if (begin < right) QuickSort(arr, begin, right);
}
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

快速排序与堆排序 的相关文章

  • Perl 和 Unix 如何以相同的顺序对 Unicode 字符串进行排序?

    我正在尝试获取 Perl 和 GNU Linuxsort 1 程序就如何对 Unicode 字符串进行排序达成一致 我在跑sort with LANG en US UTF 8 在Perl程序中我尝试了以下方法 use Unicode Col
  • Python 旅行商贪婪算法 [关闭]

    Closed 这个问题需要调试细节 help minimal reproducible example 目前不接受答案 因此 我为旅行推销员问题创建了一种排序 并按 x 坐标和 y 坐标进行排序 我正在尝试实施贪婪搜索 但无法做到 此外 每
  • 总和不小于 key 的数组的最小子集

    给定一个数组 假设为非负整数 我们需要找到最小长度子集 使得元素之和不小于 K K 是作为输入提供的另一个整数 是否有可能找到时间复杂度为 O n n 的大 oh 的解决方案 我目前的想法是这样的 我们可以在 O n log n 中对数组进
  • 如何计算 3D Morton 数(交织 3 个整数的位)

    我正在寻找一种快速计算 3D Morton 数的方法 这个网站 http www graphics stanford edu seander bithacks html InterleaveBMN有一个基于幻数的技巧来处理 2D Morto
  • 如何按键中的值对 Redis 哈希进行排序

    Redis 有没有一种好方法来获取按值排序的哈希中的键 我查看了文档 但没有找到直接的方法 另外有人可以解释一下redis中的排序是如何实现的 以及什么吗 本文档 http redis io commands SORT using hash
  • 使用什么算法来确定使系统达到“零”状态所需的最小操作数?

    这是一种更通用的问题 不是特定于语言的 有关要使用的想法和算法的更多信息 系统如下 它登记朋友群体之间的小额贷款 Alice and Bill要去吃午饭 比尔的卡坏了 所以爱丽丝支付了他的餐费 10 美元 第二天Bill and Charl
  • Java按日期升序对列表对象进行排序[重复]

    这个问题在这里已经有答案了 我想按一个参数对对象列表进行排序 其日期格式为 YYYY MM DD HH mm 按升序排列 我找不到正确的解决方案 在 python 中使用 lambda 很容易对其进行排序 但在 Java 中我遇到了问题 f
  • 排序矩阵的选择算法

    这是谷歌面试问题 给定一个 N N 矩阵 所有行均已排序 所有列均已排序 找到矩阵的第 K 个最大元素 在 n 2 中执行它很简单 我们可以使用堆或合并排序 n lg n 对它进行排序 然后得到它 但是有没有更好的方法 比 n lg n 更
  • 如何在 javascript 中实现映射或排序集

    Javascript 有使用数字索引的数组 john Bob Joe 以及可以像关联数组或 映射 一样使用的对象 允许对象值使用字符串键 john 28 bob 34 joe 4 在 PHP 中 两者都很容易A 按值排序 同时保留密钥 和B
  • 计算序列而无法存储值?

    问题陈述 here http www spoj com problems EC SER 令 S 为无限整数序列 S0 a S1 b Si Si 2 Si 1 对于所有 i gt 2 你有两个整数 a 和 b 您必须回答有关序列中第 n 个元
  • 调度算法,找到设定长度的所有非重叠区间

    我需要为我的管理应用程序实现一种算法 该算法将告诉我何时可以将任务分配给哪个用户 我实现了一个蛮力解决方案 它似乎有效 但我想知道是否有更有效的方法来做到这一点 为了简单起见 我重写了算法以对数字列表进行操作 而不是数据库查询等 下面我将尝
  • 查找字符串中最常见的子字符串的算法

    是否有任何算法可用于查找字符串中最常见的短语 或子字符串 例如 以下字符串将 hello world 作为其最常见的两个单词短语 hello world this is hello world hello world repeats thr
  • 如何按日期对包含通过合并 get_posts 结果创建的 WP po​​st 对象的数组进行排序?

    我想通过合并 2 个单独的帖子的结果来创建单个帖子数组get posts查询 并按发布日期对数组进行排序 在我下面的代码中 get posts 为 args b and args a已合并为一个数组 但它们是分开的 的 9 个标题 args
  • Java 中查看 ArrayList 是否包含对象的最有效方法

    我有一个 Java 对象的 ArrayList 这些对象有四个字段 我用其中两个字段来将对象视为与另一个对象相等 我正在寻找最有效的方法 给定这两个字段 以查看数组是否包含该对象 问题在于这些类是基于 XSD 对象生成的 因此我无法修改类本
  • 从二叉堆中查找第 k 个最小元素的 O(klogk) 时间算法

    我们有一个 n 节点二叉堆 其中包含n不同的项目 根部的最小项目 为一个k lt n 发现O klogk 时间算法选择kth堆中的最小元素 O klogn 很明显 但无法找出O klogk 一 也许我们可以使用第二个堆 但不确定 好吧 你的
  • 从给定的项目列表创建子列表

    我首先要说的是以下问题不是为了家庭作业目的即使因为我几个月前就完成了软件工程师的工作 无论如何 今天我正在工作 一位朋友向我询问了这个奇怪的排序问题 我有一个包含 1000 行的列表 每行代表一个数字 我想创建 10 个子列表 每个子列表都
  • 如何以最低的价格优化购物车?

    我有一个我想买的物品清单 这些商品由不同的商店提供 价格也不同 商店有单独的送货费用 我正在寻找一种最佳的购物策略 以及支持它的java库 以最低的总价购买所有商品 Example 商品 1 在 Shop1 的售价为 100 美元 在 Sh
  • 对包含元组的元组进行排序[重复]

    这个问题在这里已经有答案了 我有以下元组 其中包含元组 MY TUPLE A Apple C Carrot B Banana 我想根据以下内容对这个元组进行排序second内部元组中包含的值 即 对 Apple Carrot Banana
  • 查找最接近点的多边形顶点的索引

    Heading 我需要找到最接近点的多边形的索引 所以在这种情况下 输出将是 4 和 0 这样 如果添加了红点 我就知 道将顶点放置在数组中的位置 有谁知道从哪里开始 抱歉 如果标题有误导性 我不知道如何正确表达它 In this case
  • 确定一组日期的事件重复模式

    我正在寻找一种模式 算法或库 它将采用一组日期并在退出时返回重复的描述 即集合 11 01 2010 11 08 2010 11 15 2010 11 22 2010 11 29 2010 会产生类似 十一月的每个星期一 的结果 有没有人以

随机推荐

  • JFrame 中的图像相互覆盖,而不是相互显示两个图像[重复]

    这个问题在这里已经有答案了 public class Board extends JFrame public void bd JFrame frame new JFrame JLabel background1 new JLabel new
  • Cassandra 中用于差异比较的 Merkle 树

    我正在读一本document http docs datastax com en cassandra 3 0 cassandra operations opsRepairNodesManualRepair html关于卡桑德拉的修复 它说
  • Android studio 1.1.0 设置 minifyEnabled true 导致应用程序出现问题

    这是我的 gradle build 文件 defaultConfig minSdkVersion 15 targetSdkVersion 21 versionCode 2 versionName 1 0 buildTypes release
  • 如何在 Python 中对 URL 参数进行百分比编码?

    If I do url http example com p urllib quote query 它不编码 to 2F 破坏 OAuth 规范化 它不处理 Unicode 它会抛出异常 有更好的图书馆吗 From Python 3 文档
  • 如何使“setup.py bdist_egg”忽略特定源文件?

    我正在尝试为 django 应用程序构建一个包 但排除所有测试模块 我尝试过设置 exclude tests tests tests tests on find packages并定义一个MANIFEST in 但测试始终会被编译并包含在捆
  • Google SMS Retriever API 无法检索 SMS 消息

    我正在尝试使用 Google 的短信检索器 API 进行自动短信验证 我已按照指示进行操作here https developers google com identity sms retriever overview但我的应用程序没有收到
  • 在WebView中加载本地html?

    我想将本地 html 加载到 WebView 中而不使用 file 因为这不允许 cookie 有没有办法使用 localhost 之类的东西 其次 我找不到在 getSettings 中启用 cookie 的方法 因为使用 file 时不
  • 如何限制只有一台机器才能访问Web应用程序?

    我需要确保访问我的 Web 应用程序的每个用户都只能从一台计算机上执行此操作 因此 100 个用户意味着 100 台计算机 最好的解决方案是什么 在首次登录时检测并存储 IP 是个好主意吗 我认为即使在会话的生命周期内 IP 也可能会发生变
  • 如何摆脱“允许<网站>运行'silverlight'?”在 webdriver 中使用 firefoxprofile 对 Firefox 发出警报

    当使用机器人 api 拖放时 我的鼠标位置受到询问 允许运行 silverlight 的警报的干扰 在全屏模式下运行 firefox 甚至我的 webdriver api 也会受到此警报的影响 因为原本在一个按钮上发生的点击却在另一个按钮上
  • UIViewController -viewDidLoad 没有被调用

    作为 Cocoa 的新手 我遇到了一些问题Interface Builder UIViewController和朋友 我有一个UIViewController子类具有UIView在 xib 中定义 并将控制器的视图出口连接到视图 xib 的
  • WooCommerce 添加到购物车验证:阻止添加到购物车

    我遇到了 woocommerce 的问题 我花了几天时间试图解决 我正在为一个人创建一个网站 他希望我在产品页面上添加自定义输入 我自己无法做到这一点 所以我在网上使用了自由职业者 在产品页面上 我有一个添加到购物车按钮 数量输入和日期输入
  • 在 VBA 中搜索单元格引用的公式

    在 VBA 中 我想搜索 Excel 公式 字符串 以查找单元格引用 具体来说 我想找到字符串中存在相对单元格引用 任何相对单元格引用 而不是特定单元格引用 或混合单元格引用的位置 我不需要找到绝对的单元格引用 尽管我可以检查并忽略它们 我
  • 在 Windows 10 中使用 PS 将程序固定到任务栏

    我正在尝试使用以下代码将程序固定到 Windows 10 RTM 中的任务栏 shell new object com Shell Application folder shell Namespace Join Path env Syste
  • 更新浏览器地址栏而不重新加载

    我喜欢 facebook 在图像之间滚动时更改浏览器地址栏 URL 的方式 以及它在 IE7 上的工作方式 但是 我只找到了有关如何在 HTML5 浏览器上执行此操作的信息 并且我想支持 IE7 由于这是一个 HTML5 解决方案 因此如下
  • 如何为Notepad++编写宏?

    我想为 Notepad 编写一个宏 它应该分别用 char4 char5 char6 替换 char1 char2 char3 Notepad 中的宏只是一堆编码操作 您开始录制 对缓冲区进行操作 也许激活菜单 停止录制然后播放宏 经过调查
  • java中如何将日期时间转换为时间戳

    论坛会员 我在 java 中遇到一个日期时间问题 实际上我正在收到开始日期格式为 2012 02 27T01 10 10我想将收到的日期插入到具有日期时间数据类型的数据库中 实际上我尝试通过下面的代码将收到的开始日期转换为日期时间 Stri
  • Android Eclipse Lint API 检查

    谢谢 P T 看起来像是问题的正确答案在 Eclipse 中构建多 SDK Android 应用程序而不会丢失编译时检查 https stackoverflow com questions 7642249 但是 当我尝试按照建议使用 Tar
  • 读取 spacy 中的文本文件语料库

    我看到的使用 spacy 的所有示例都只是在单个文本文件 尺寸很小 中读取 如何将文本文件语料库加载到 spacy 中 我可以通过腌制语料库中的所有文本来使用 textacy 来做到这一点 docs textacy io spacy rea
  • Azure Blob、文件和磁盘存储

    快问 我已经阅读了大量有关 azure blob 文件 磁盘存储选项的信息 并且我有一个如此简单的存储要求 以至于我对最佳选择感到困惑 我正在阅读的大部分信息都完全超出了我的理解范围 我希望有人能够将视野缩小到更合理的优点 缺点 我的情况如
  • 快速排序与堆排序

    快速排序和堆排序都进行就地排序 哪个更好 首选哪种应用和案例 堆排序是 O N log N 保证的 这比快速排序中最坏的情况要好得多 堆排序不需要更多内存来让另一个数组像合并排序那样放置有序数据 那么为什么商业应用程序坚持使用快速排序呢 与