十大排序算法(演示动画)

排序算法

  • 点击蓝字有演示视频
    在这里插入图片描述
  1. 冒泡排序(Bubble Sort):【】
    从第一个元素开始,根据大小比较是否交换相邻数字的位置

  2. 插入排序(Insertion Sort):【】
    以第一个元素为一个排序好的数组,根据大小为下一个数找到合适的位置插入已经排序的数列

  3. 选择排序(Selection Sort):【】
    从头到尾遍历一次,选择最值放到端点,然后继续下一轮不包括这个已经排序过的数的从头到尾的遍历

  4. 希尔排序(Shell Sort):【】
    对于n个元素的数组,用n/2为间隔分组,分组后的组内用插入排序,然后用n/4为间隔分组,分组后的组内用选择排序,直到最后间隔为1,进行最后一次排序

  5. 归并排序(Merge Sort):【】
    对于n个元素的数组,先分成n个只有一个元素的数组,此时这个单个元素的数组可视为是有序数组,然后两两合并有序数组的同时进行排序(从两个数组的第一个元素开始比较大小,小的先出,大的留下来进行下一轮比较),最后迭代合并为n个元素的数组

  6. 快速排序(Quick Sort):【】
    随机选择数组中的一个数a作为切分点,遍历一遍数组,把比这个数a大的数都挪到这个数a右边,比这个数a小的数都挪到这个数a左边,然后再对这个数a左侧和右侧的两个数组递归使用同样的方法处理,直到某个子数组在被切分点切分后的一边只剩下一个元素,那这个切分点的这一边排序完成,直到最后所有切分点的两边都排序完成,整个数组完成排序。

    快速排序没有比较全面的视频演示,可以看文章最后关于快速排序详细操作的说明进行了解

  7. 堆排序(Heap Sort):【】
    第一个数作为根节点,第二个数往下排,同时从第二个数开始每次都要和其父节点比较来确定是否需要交换子父节点的位置,若交换,则接着比较交换之后的父节点,直到不需要交换或者一直交换到成为了根节点。(堆只关注当前节点和父节点,当前节点和子节点之间的关系,不要想那么复杂)

  8. 计数排序(Counting Sort):【适用于数据量大但是数据分布范围小的排序】
    先正序遍历一遍原数组,得到最大值(max)、最小值(min)以及两值间的数的个数(range),包括最大值和最小值。声明一个大小为range,元素数值全为0的计数数组(count),下标0对应最小值,以此类推下标range-1对应最大值。再次正序遍历一遍,每遍历到一个数就让计数数组中对应下标的数值加1。声明一个大小为range的结果数组(res),然后倒序遍历(倒序是为了维持计数排序的稳定性)原数组,每遍历到一个数a,就去计数数组中a对应的下标查询这个下标对应的数值,将这个值减1,并将减1后的值当做结果数组中的下标将此数a插入。直到倒序遍历结束,所有数据都插入到结果数组中。

  9. 桶排序(Bucket Sort):【】
    先遍历一次,得到最大值和最小值,然后在最大值和最小值这个大区间内分为多个区间也就是多个桶(区间的个数以及每个区间的范围需要自己根据情况分析自己确定),在每个桶内排序之后将桶合并。

  10. 基数排序(Radix Sort):【】
    从最低位开始,按照最低位从0到9分为9个桶,然后从0到9依次把桶内数据排列出来,然后从更高一位开始,按照这一位的数字大小放入桶0到9十个桶中,直到最高位,最后一次放入桶后依次把桶内数据排列出来之后排序完成。

快速排序详细操作
经过在百度和b站搜索快速排序后,发现这些博客和讲解视频都只讲了选取第一个数或者最后一个数作为基准点的快速排序,对于随机选取数作为基准点的快速排序甚至都没有找到相关的讲解,因此我根据规律,自己推导了一下随机选数作为基准点的这一种快速排序,并把这三种排序汇总了一下,有逻辑不对的地方希望提出指正。
快速排序运用了递归的思想,快速排序共分为三种:
① 选取数组的第一个数作为基准点(pivot)对数组进行切分,此时左指针指向第二个数,右指针指向最后一个数,右指针优先移动,右指针遇到比pivot小的数就停止,让左指针开始移动,左指针遇到比pivot大的数停止,左右指针都停止后交换其二者指向的数,交换后右指针优先移动,两指针按照同样的规则递归进行移动停止交换等,直到两指针重合,此时两指针同时指向的数和pivlot数交换,此时三指针重合,至此第一轮切分结束,递归进行后续的切分直到全部排序完成。
②选取数组的最后一个数作为基准点(pivot)对数组进行切分,此时右指针指向倒数第二个数,左指针指向第一个数,左指针优先移动,左指针遇到比pivot小的数就停止,让右指针开始移动,右指针遇到比pivot大的数停止,左右指针都停止后交换其二者指向的数,交换后左指针优先移动,两指针按照同样的规则迭代进行移动停止交换等,直到两指针重合,此时两指针同时指向的数和pivlot位置交换。至此第一轮切分结束,递归进行后续的切分直到全部排序完成。
③选取数组中随机一个数(包括左右端点)作为基准点(pivot)对数组进行切分,这一方法对前面两种情况也适用,此时左指针指向第一个数,右指针指向最后一个数,左指针和右指针的移动优先级可以随意定,但是定了之后不能改。例如定下来左指针优先级更高,那就先移动左指针,直到左指针遇到比基准点大的数或者遇到基准点停止,此时移动右指针,直到遇到比基准点小的数或者遇到基准点的指针停止,两指针都停止后交换值,若是有指针是因为遇到基准点指针停止的,那么不仅两个指针所指的数要交换,基准点的指针也要同时交换(比如基准点指针现在和左指针重合,交换后则和右指针重合),三个指针按照同样的规则迭代进行移动停止交换等,直到三个指针重合,至此第一轮切分结束,递归进行后续的切分直到全部排序完成。

计数排序、桶排序、基数排序都是桶排序思想(非比较排序)的体现

  • 基数排序用LSD(least significant digit sort最低有效数字排序)而不用MSD(most significant digit sort最高有效数字排序)的原因是,MSD在实现上更麻烦,需要用到更多的桶。如果用MSD的话,比如先从百位开始排,第一次分为十个桶后,排十位时又要每个桶内再分为十个小桶,排个位时又要再如此,就产生了1000个桶,也就是103个桶,这里的3为最大数字的总位数。而使用LSD的话,每次放入桶再排列出来之后,由于是使用低有效位生成的桶,整体依然是无序的,所以之前的十个桶依然可以接着用,MSD不能接着用的原因是分桶之后每个桶的大小排序已经确定了,不能接着用,想继续往低位排的话得生成新的桶。
  • 桶排序使用不多,因为每个桶(区间)的数据量不好确定,用数组的话每个桶都需要申请跟原数组同样大的空间,空间效率不高;用链表的话在桶内排序时相当于冒泡排序,时间效率又不高;用ArrayList的话,在扩容时又会产生性能上的影响,时间效率不高。
  • 完全二叉树:每个父节点最多两个子节点,每一层节点排满之后再去排下一层,每一层从左到右排。
  • 堆:在完全二叉树的基础上,每个父节点大于等于两个子节点(大顶堆),每个父节点小于等于两个子节点(小顶堆)。
  • 迭代:是重复反馈过程的活动,其目的通常是为了逼近所需目标或结果。每一次对过程的重复称为一次“迭代”,而每一次迭代得到的结果会作为下一次迭代的初始值
  • 递归:程序调用自身的编程技巧。 一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解。递归的能力在于用有限的语句来定义对象的无限集合。一般来说,递归需要有边界条件、递归前进段和递归返回段。当边界条件不满足时,递归前进;当边界条件满足时,递归返回

在这里插入图片描述
顺口溜解释:选择 冒泡 插入,
快速 归并 堆,希尔,桶 计数,基数,
对应的时间复杂度为
n2 ,nlogn,n1.3
n+k ,n×k
稳定性对应为
不稳 稳 稳 不稳 稳,
不稳 不稳 稳 稳 稳。

排序的稳定性:经过排序算法排序之后,原数组中的数值相等的数位置原顺序则为稳定排序,顺序发生了变化则为不稳定排序。
排序稳定性的意义:对于基本类型的排序无意义,但是对于引用类型的:例如对全班同学先按照年龄排序再按照身高排序时,若第二次按照身高排序时使用的算法是不稳定的,则会影响第一次排序定好的顺序。

交换:冒泡排序 快速排序
插入: 插入排序 希尔排序
选择: 选择排序 堆排序
归并:归并排序
非比较排序:桶排序 计数排序 基数排序
桶思想: 桶排序 计数排序 基数排序

在这里插入图片描述时间复杂度O(1) < O(logN) < O(N) < O(N logN) < O(N2) < O(N3) < O(2N)<O(N!)

原地排序(In-place):
原地排序就是指不申请多余的空间来进行的排序,就是在原来的排序数据中比较和交换的排序。例如堆排序等都是原地排序,归并排序,计数排序等,需要在其他结构内(桶或子数组)排序,不是原地排序。
属于原地排序的是:希尔排序、冒泡排序、插入排序、选择排序、堆排序、快速排序。

参考:b站马士兵说,以及文章中的超链接

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

在外面要叫头哥

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值