数据结构——快速排序的介绍

这篇具有很好参考价值的文章主要介绍了数据结构——快速排序的介绍。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

快速排序

快速排序是霍尔(Hoare)于1962年提出的一种二叉树结构的交换排序方法。快速排序是一种常用的排序算法,其基本思想是通过选择一个元素作为"基准值",将待排序序列分割成两个子序列,其中一个子序列的元素都小于等于基准值,另一个子序列的所有素都大于基准值。然后对这两个子序列分别进行递归排序,最后将排好序的子序列合并起来,即可得到完整的有序序列。

思想

任取待排序元素序列中的某元素作为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中所有元素均小于基准值,右子序列中所有元素均大于基准值,然后最左右子序列重复该过程,直到所有元素都排列在相应位置上为止。数据结构——快速排序的介绍

霍尔版本

霍尔版本单趟排序代码实现

定义两个下标left和right。假设keyi在最左边,那么右边先走。当右边找到比keyi小的就停下。然后左边开始走,当左边找到比keyi大的就停下。交换左右的值。然后直到左右指针碰面,那么将left和keyi的值交换。
数据结构——快速排序的介绍
数据结构——快速排序的介绍

void QuickSort(int* arr,int begin, int end)
{
   	int left = begin;
    int right = end;
    int keyi = left;
    while (left < right)
    {
        //右边先走
        while (left < right && arr[right] >= arr[keyi])
        {
            right--;
        }
        while (left < right && arr[left] <= arr[keyi])
        {
           left++;
        }
        Swap(&arr[left], &arr[right]);
    }
    Swap(&arr[keyi], &arr[left]);
}

霍尔版本排序代码实现

当单趟排序把第一个keyi的数据放到它应该蹲的位置时,此时数组就可以分成三个部分,分别是[begin,keyi-1],keyi,[keyi+1,end]。此时依据二叉树的递归分治的思路将子区间的数据再次选左边为keyi来进行单趟排序,直到子区间不存在。最后就能够将数据排序。
数据结构——快速排序的介绍

针对已有序数组的优化

针对已经有序数组的排序,上面的代码有一个致命的问题。即未优化的快排最坏的情况下时间复杂度为O(N^2)。当数据量大的时候,还会有因为递归而栈溢出的问题。下面介绍第一种优化的方式,即随机数选keyi。

随机数选keyi

通过取数组长度的随机数做keyi,可以在一定程度上避免了完全有序或者接近有序的情况下快速排序的时间复杂度问题。下面简单看一下处理的方式
数据结构——快速排序的介绍

三数取中

通过最左边、最右边和中间位置的值作比较,取中间值来做下标keyi。这样在一定程度上可以优化有序或局部有序情况下,快速排序效率下降的问题。

数据结构——快速排序的介绍
数据结构——快速排序的介绍

挖坑法

挖坑法单趟排序代码实现

由于霍尔大佬的方法比较晦涩难懂,所以就有了我们现在要介绍的挖坑法。挖坑法顾名思义就是根据快排思想下的优化出来的一个版本。先假设key在最左边的数,所以坑位在左边。那么从右边开始走,当碰到比key小的就把它放到坑中,并且将坑位改变到停下的位置。左边同理。
数据结构——快速排序的介绍

void QuickSort1(int* arr, int begin, int end)
{
    int left = begin;
    int right = end;
    随机选key
    通过随机数来选择key,优化了顺序和逆序的情况下的时间复杂度
    //int randi = left + (rand() % (right - left));
    //
    //Swap(&arr[randi], &arr[left]);

    //三数取中优化
    int ret = GetMidNum(arr, left, right);
    if (left != ret)
        Swap(&arr[ret], &arr[left]);

    //左边做key
    int key = arr[left];
    int hole = left;
    while (left < right)
    {
        //右边先走
        while (left < right && arr[right] >= key)
        {
            right--;
        }
        //右边比key小就把它填到坑里,并改变坑位
        arr[hole] = arr[right];
        hole = right;
        while (left < right && arr[left] <= key)
        {
            left++;
        }
        //左边比key大就把它填到坑里,并改变坑位
        arr[hole] = arr[left];
        hole = left;
    }
    //最后坑位就是key应该蹲的位置
    arr[hole] = key;
}

挖坑法代码实现

数据结构——快速排序的介绍

前后指针法

前后指针法单趟排序代码实现

实现思路如下:首先定义两个指针prev和cur。以最左边作key,cur找小,当cur指向的内容比key小,++prev,prev的值和cur值交换位置(位置重合可以不交换)。当cur找到的值比key大时,++cur。这种方法的大体情况分为两种,一、prev紧跟cur。二、prev和cur直接间隔这一段比key的值。那么此时比key大的值会逐步往后翻,比key小的值会逐步往前甩。
数据结构——快速排序的介绍
数据结构——快速排序的介绍
数据结构——快速排序的介绍

前后指针法代码实现

数据结构——快速排序的介绍

小区间优化

我们知道快速排序其实就是运用了二叉树结构分治的思想来进行排序的。在二叉树这种结构中,当高度为h时,我们考虑最优情况下(满二叉树),最后一层的结点就是2^(h-1)个。占据整棵树的一半。倒数第二层的结点个数为2 ^ (h-2)个,占整棵树结点的25%。其实只要消灭了倒数三层的递归其实就可以在大体上减少递归带来的损耗,提高效率,并且可以让栈区空间的损耗降低。在一个局部有序的小区间内进行优化,我们可以选择的排序有很多种。但是,根据我们前面所学知识我们可以发现,其实使用堆排序和希尔排序相对于小区间优化的优势并没有很明显。前者需要建堆,后者需要根据gap来进行预排序。选择插入排序来小区间优化其实是最适合的。因为在局部有序的区间内,插入排序的效率是最高的。
数据结构——快速排序的介绍

数据结构——快速排序的介绍

快速排序非递归实现

利用栈来存需要递归的区间,然后根据栈后进先出的性质来模拟递归的顺序。把区间化成子区间进行继续排序。直到区间不存在或区间只有一个数就停止将区间的下标入栈。
数据结构——快速排序的介绍

数据结构——快速排序的介绍

快速排序的特性总结

一、快速排序是一个综合性能较好和使用场景比较广泛的排序。
二、快速排序的时间复杂度为O(NLogN)。
数据结构——快速排序的介绍
在最好情况下,快速排序的时间复杂度为O(nlogn)。当待排序的序列能够均匀地分成两个子序列时,每次分割操作都能将序列大致平分,此时递归调用层数为logn,每层需要的比较次数为n,因此总比较次数为O(N
LogN)。在最坏情况下,快速排序的时间复杂度为O(n ^ 2)。当待排序的序列已经有序或基本有序(例如,序列已经是升序排列,但选择的基准值总是最小或最大元素),每次分割操作只能切割出一个子序列,递归调用的层数为n,每层需要的比较次数为n,因此总比较次数为n ^ 2。然而,通过随机选择基准值或使用三数取中法等优化方法,可以减少最坏情况发生的可能性,从而提高了快速排序的平均性能。在实际应用中,快速排序通泛使用。
三、快速排序是一个不稳定的排序。文章来源地址https://www.toymoban.com/news/detail-502510.html

代码获取

到了这里,关于数据结构——快速排序的介绍的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 数据结构——排序算法之快速排序

        个人主页: 日刷百题 系列专栏 : 〖C/C++小游戏〗 〖Linux〗 〖数据结构〗   〖C语言〗 🌎 欢迎各位 → 点赞 👍+ 收藏 ⭐️+ 留言 📝  ​ ​ 快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法。 基本思想: 任取待排序元素序列中 的某元素作为基准值,按照

    2024年01月21日
    浏览(31)
  • 【数据结构--八大排序】之快速排序

    💐 🌸 🌷 🍀 🌹 🌻 🌺 🍁 🍃 🍂 🌿 🍄🍝 🍛 🍤 📃 个人主页 :阿然成长日记 👈点击可跳转 📆 个人专栏: 🔹数据结构与算法🔹C语言进阶 🚩 不能则学,不知则问,耻于问人,决无长进 🍭 🍯 🍎 🍏 🍊 🍋 🍒 🍇 🍉 🍓 🍑 🍈 🍌 🍐 🍍 前言: 前面,我花费

    2024年02月08日
    浏览(29)
  • 数据结构--快速排序

    快速排序是通过二叉树的思想,先设定一个值,通过比较,比它大的放在它的右边,比它小的放在它的左边;这样相当于在二叉树中,小的放在左子树,大的放在右子树,设定的值就是根;再通过递归的思想,将它们继续按这种方式进行排序,排到最后就排好了;这就是快速

    2024年02月08日
    浏览(30)
  • 【数据结构】快速排序详解

    目录 一、基本介绍 二、快排的实现 1. 调试环境 2.快排的单趟排序 (1)Hoare版本 (2)挖坑法 (3)前后指针法 2.递归过程 三、快排的优化 1. 优化取key方式,防止栈溢出 2. 小区间优化 四、快排的非递归方式         排序算法是日常使用最频繁的一个算法,生活中也很常

    2024年02月09日
    浏览(32)
  • 【数据结构】第十三站:排序(中)快速排序

    快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法,其基本思想为:任取待排序元素序列中的某元素作为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中所有元素均小于基准值,右子序列中所有元素均大于基准值,然后最左右子序列重复该过程,

    2024年02月01日
    浏览(31)
  • 【数据结构与算法】:选择排序与快速排序

    🔥 个人主页 : Quitecoder 🔥 专栏 :数据结构与算法 我的博客即将同步至腾讯云开发者社区,邀请大家一同入驻:腾讯云 欢迎来到排序的第二个部分:选择排序与快速排序! 选择排序是一种简单直观的比较排序算法。该算法的基本思想是在每一轮中选出当前未排序部分的最

    2024年03月17日
    浏览(36)
  • 数据结构——lesson11排序之快速排序

    hello hello~ ,这里是大耳朵土土垚~💖💖 ,欢迎大家点赞🥳🥳关注💥💥收藏🌹🌹🌹 💥 个人主页:大耳朵土土垚的博客 💥 所属专栏:数据结构学习笔记 、排序算法合集 💥对于数据结构顺序表、链表、堆以及排序有疑问的都可以在上面数据结构专栏和排序合集专栏进行

    2024年04月16日
    浏览(51)
  • 【数据结构初阶】八大排序(二)——快速排序&&冒泡排序

    大家好我是沐曦希💕 书接【数据结构初阶】八大排序(一)——希尔排序堆排序直接插入排序直接选择排序 基本思想:所谓交换,就是根据序列中两个记录键值的比较结果来对换这两个记录在序列中的位置,交换排序的特点是: 将键值较大的记录向序列的尾部移动,键值较小

    2024年02月21日
    浏览(36)
  • 【数据结构】 七大排序详解(贰)——冒泡排序、快速排序、归并排序

    ==冒泡排序(Bubble Sort)==也是一种简单直观的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会

    2024年02月09日
    浏览(39)
  • 数据结构与算法:快速排序

    荷兰国旗问题 想要理解快速排序,就先理解这个问题: [LeetCode75.颜色分类] 荷兰国旗是由红白蓝三色组成的: 现在将其颜色打乱 然后根据一定的算法,将其复原为红白蓝三色,这就叫做荷兰国旗问题。 在LeetCode的题目中,其将荷兰国旗的三个颜色用0,1,2来表达,也就是说

    2024年01月15日
    浏览(34)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包