排序算法

十大排序

  • 冒泡排序
  • 选择排序
  • 插入排序
  • 希尔排序
  • 快速排序
  • 归并排序
  • 堆排序
  • 基数排序
  • 桶排序
  • 计数排序

术语

  1. 稳定排序:如果 a 原本在 b 的前面,且 a == b,排序之后 a 仍然在 b 的前面,则为稳定排序。
  2. 非稳定排序:如果 a 原本在 b 的前面,且 a == b,排序之后 a 可能不在 b 的前面,则为非稳定排序。
  3. 原地排序:原地排序就是指在排序过程中不申请多余的存储空间,只利用原来存储待排数据的存储空间进行比较和交换的数据排序。
  4. 非原地排序:需要利用额外的数组来辅助排序。
  5. 时间复杂度:一个算法执行所消耗的时间。
  6. 空间复杂度:运行完一个算法所需的内存大小。
  7. 内排序:所有的排序都在内存中进行。
  8. 外排序:需要内存和硬盘交换数据进行排序。

总结
在这里插入图片描述

  • 从平均来看:高级算法堆排,快排和归并排序优于其他算法。
  • 对于基本有序或数据量较少的情况,简单算法冒泡排序和插入排序更优。
  • 在最坏情况下,堆排序和归并排序优于其他算法。
  • 堆排序和归并排序发挥比较稳定,快排在优化情况发挥最佳。
  • 归并排序和快排在提升速度的同时也占用了更大的额外空间,堆排序在快速情况下占用空间也小。
  • 在高级算法中只有归并排序保持稳定性。
  • 优化的快排(在数据量小于某一指标时换为插入排序)是综合性能最佳的排序算法。

------>>算法实现

排序详解

1、选择排序(SelctionSort)

  • 首先,找到数组中最小的那个元素,将它和数组的第一个元素交换位置(如果第一个元素就是最小元素那么它就和自己交换)。
  • 其次,在剩下的元素中找到最小的元素,将它与数组的第二个元素交换位置。
  • 如此往复,直到将整个数组排序。这种方法我们称之为选择排序。
    在这里插入图片描述

1、时间复杂度:O(n2)
2、空间复杂度:O(1)
3、非稳定排序
4、原地排序

2、插入排序(Insertion Sort)

  • 从数组第2个元素开始抽取元素。
  • 把它与左边第一个元素比较,如果左边第一个元素比它大,则继续与左边第二个元素比较下去,直到遇到不比它大的元素,然后插到这个元素的右边。
  • 继续选取第3,4,….n个元素,重复步骤 2 ,选择适当的位置插入。
    在这里插入图片描述

1、时间复杂度:O(n2)
2、空间复杂度:O(1)
3、稳定排序
4、原地排序

3、冒泡排序(BubbleSort)

  • 把第一个元素与第二个元素比较,如果第一个比第二个大,则交换他们的位置。接着继续比较第二个与第三个元素,如果第二个比第三个大,则交换他们的位置….
  • 我们对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样一趟比较交换下来之后,排在最右的元素就会是最大的数。
  • 除去最右的元素,我们对剩余的元素做同样的工作,如此重复下去,直到排序完成。
    在这里插入图片描述

1、时间复杂度:O(n2)
2、空间复杂度:O(1)
3、稳定排序
4、原地排序

4、希尔排序(Shell Sort)

  • 希尔排序可以说是插入排序的一种变种。无论是插入排序还是冒泡排序,如果数组的最大值刚好是在第一位,要将它挪到正确的位置就需要 n - 1 次移动。也就是说,原数组的一个元素如果距离它正确的位置很远的话,则需要与相邻元素交换很多次才能到达正确的位置,这样是相对比较花时间了。
  • 希尔排序就是为了加快速度简单地改进了插入排序,交换不相邻的元素以对数组的局部进行排序。
  • 希尔排序采用插入排序的方法,先让数组中任意间隔为 h 的元素有序,刚开始 h 的大小可以是 h = n / 2,接着让 h = n / 4,让 h 一直缩小,当 h = 1 时,也就是此时数组中任意间隔为1的元素有序,此时的数组就是有序的了。
    在这里插入图片描述

1、时间复杂度:O(nlogn)
2、空间复杂度:O(1)
3、非稳定排序
4、原地排序

5、归并排序(Merge Sort)

  • 将一个大的无序数组有序,我们可以把大的数组分成两个,然后对这两个数组分别进行排序,之后在把这两个数组合并成一个有序的数组。由于两个小的数组都是有序的,所以在合并的时候是很快的。
  • 通过递归的方式将大的数组一直分割,直到数组的大小为 1,此时只有一个元素,那么该数组就是有序的了。
  • 之后再把两个数组大小为1的合并成一个大小为2的,再把两个大小为2的合并成4的 …… 直到全部小的数组合并起来。
    在这里插入图片描述

1、时间复杂度:O(nlogn)
2、空间复杂度:O(n)
3、稳定排序
4、非原地排序

  • 外部排序最常用的算法是多路归并排序,即将原文件分解成多个能够一次性装入内存的部分,分别把每一部分调入内存完成排序。然后,对已经排序的子文件进行多路归并排序。(外部排序指的是大文件的排序,即待排序的记录存储在外存储器上,待排序的文件无法一次装入内存,需要在内存和外部存储器之间进行多次数据交换,以达到排序整个文件的目的。)

6、快速排序(Quicksort)

  • 我们从数组中选择一个元素,我们把这个元素称之为中轴元素,然后把数组中所有小于中轴元素的元素放在其左边,所有大于或等于中轴元素的元素放在其右边,显然,此时中轴元素所处的位置的是有序的。也就是说,我们无需再移动中轴元素的位置。
  • 从中轴元素那里开始把大的数组切割成两个小的数组(两个数组都不包含中轴元素),接着我们通过递归的方式,让中轴元素左边的数组和右边的数组也重复同样的操作,直到数组的大小为1,此时每个元素都处于有序的位置。
    在这里插入图片描述

1、时间复杂度:O(nlogn)
2、空间复杂度:O(logn)
3、非稳定排序
4、原地排序

7、堆排序(HeapSort)

  • 堆的特点就是堆顶的元素是一个最值,大顶堆的堆顶是最大值,小顶堆则是最小值。
  • 堆排序就是把堆顶的元素与最后一个元素交换,交换之后破坏了堆的特性,我们再把堆中剩余的元素再次构成一个大顶堆,然后再把堆顶元素与最后第二个元素交换….如此往复下去,等到剩余的元素只有一个的时候,此时的数组就是有序的了。
    在这里插入图片描述

1、时间复杂度:O(nlogn)
2、空间复杂度:O(1)
3、非稳定排序
4、原地排序

8、计数排序

  • 计数排序是一种适合于最大值和最小值的差值不是不是很大的排序。
  • 把数组元素作为数组的下标,然后用一个临时数组统计该元素出现的次数,例如 temp[i] = m, 表示元素 i 一共出现了 m 次。
  • 最后再把临时数组统计的数据从小到大汇总起来,此时汇总起来是数据是有序的。

在这里插入图片描述

#K表示临时数组的大小
1、时间复杂度:O(n+k)
2、空间复杂度:O(k)
3、稳定排序
4、非原地排序

9、桶排序

  • 桶排序就是把最大值和最小值之间的数进行瓜分,例如分成 10 个区间,10个区间对应10个桶,我们把各元素放到对应区间的桶中去,再对每个桶中的数进行排序,可以采用归并排序,也可以采用快速排序之类的。
  • 之后每个桶里面的数据就是有序的了,我们在进行合并汇总。
    在这里插入图片描述

#k 表示桶的个数
1、时间复杂度:O(n+k)
2、空间复杂度:O(n+k)
3、稳定排序
4、非原地排序

10、基数排序(RadixSort)

  • 先以个位数的大小来对数据进行排序,接着以十位数的大小来多数进行排序,接着以百位数的大小……
  • 排到最后,就是一组有序的元素了。不过,他在以某位数进行排序的时候,是用“桶”来排序的。
  • 由于某位数(个位/十位….)的大小范围为0-9,所以我们需要10个桶,然后把具有相同数值的数放进同一个桶里,之后再把桶里的数按照0号桶到9号桶的顺序取出来,这样一趟下来,按照某位数的排序就完成了。
    在这里插入图片描述

1、时间复杂度:O(kn)
2、空间复杂度:O(n+k)
3、稳定排序
4、非原地排序

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值