排序算法总结

1、算法分类:

十大常见排序算法可以分两大类:

  • 比较类排序:通过比较来决定元素间的相对次序,由于时间复杂度不能突破O(nlogn),因此也称为非线性时间比较类排序。
  • 非比较类排序:不通过比较来决定元素间的相对次序,可以突破基于比较排序的时间下界,以线性时间运行,因此也称为线性时间非比较类排序。
    在这里插入图片描述

2、排序算法总结:

在这里插入图片描述
名词解释:

  • n:数据规模
  • k:"桶"的个数
  • In-place:占用常数内存,不占用额外内存
  • Out-place:占用额外内存
  • 稳定:如果a原本在b前面,而a=b,排序之后a仍然在b的前面
  • 不稳定:如果a原本在b的前面,而a=b,排序之后 a 可能会出现在 b 的后面
  • 时间复杂度:对排序数据的总的操作次数。反映当n变化时,操作次数呈现什么规律
  • 空间复杂度:是指算法在计算机内执行时所需存储空间的度量,它也是数据规模n的函数

3. 排序算法详解

3.1 冒泡排序(bubble sort)

重复走访要排序的数列,一次比较两个元素,发现逆序则交换,每次循环把最大的值放到最后。走访数列的工作重复进行直到没有再需要交换,则排序完成。

最坏的情况是逆序,1+2+…+(n-1) = n (n-1) / 2,时间复杂度O(n 2 {^2} 2);最好的情况是已经有序,遍历一遍即可。
在这里插入图片描述

3.2 选择排序 (selection sort)

在未排序序列中找到最小/大的元素,存放在排序序列的起始位置,然后,再从剩余排序元素中继续寻找最小/大元素,放到已排序序列的末尾。直到所有元素排序完毕。

不管数组顺序怎样,比较次数不变,n(n-1)/2,时间复杂度是O(n 2 {^2} 2),但交换移动的次数少,性能略优于冒泡排序。

3.3 插入排序(insertion sort)

通过构建有序序列,对于未排序数据,在已排序序列从后向前扫描,找到相应位置并插入。

如果已经有序,只遍历一次,O(n), 否则还需O(n 2 {^2} 2)。如果排序是随机的,可以计算到平均比较和移动次数是n 2 {^2} 2/4,与冒泡和选择相比,插入排序性能好一点。

3.4 快速排序(quick sort)

挑出一个元素作为基准点(pivot),通过一趟排序将待排记录分隔成独立的两部分(分区操作partition),其中一部分记录的关键字均比另一部分的关键字小,递归地把这两部分继续进行排序,以达到整个序列有序。

如果partition每次都分的很均匀,那递归树的深度就是logn+1,最好的情况时间复杂度是nlogn,最差的就是逆序,每次划分都是一个子序列和一个空的序列,那么比较次数就是n-1 + n-2 + … + 1,O(n 2 {^2} 2)。
在这里插入图片描述

3.5 希尔排序(shell sort)

又叫缩小增量排序。是简单插入排序的加强版,优先比较距离较远的元素,防止小的数在数组末尾。先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行依次直接插入排序。(增量序列个数K)

形式和插入排序一模一样,不过把gap从1变成了从大到小的动态gap,时间复杂度O(nlogn)(或一般来说O(n 3 / 2 {^{3/2}} 3/2)),适用于更广泛的增量序列。

3.6 堆排序 (heap sort)

堆排序(heapsort)指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子节点的键值或索引总是小于(或大于)它的父节点。(是对直接选择排序的有效改进)

思想: 初始时把要排序的数的序列看作是一棵顺序存储的二叉树,调整它们的存储序,使之成为一个 堆,这时堆的根节点的数最大。然后将根节点与堆的最后一个节点交换。然后对前面(n-1)个数重新调整使之成为堆。依此类推,直到只有两个节点的堆,并对它们作交换,最后得到有n个节点的有序序列。从算法描述来看,堆排序需要两个过程,一是建立堆,二是堆顶与堆的最后一个元素交换位置。所以堆排序有两个函数组成。一是建堆的渗透函数,二是反复调用渗透函数实现排序的函数。

最好最坏平均时间复杂度都是nlogn, 因为取堆顶重建时间都是logn, 而最终需要取n-1次。但是初始构建堆的时候需要多次比较, 所以如果序列个数比较少就划不来了。

3.7 归并排序(merge sort)

采用分治法(Divide and conquer),把长度为n的序列分成两个长度为n/2的子序列,再把n/2分成两个n/4的子序列,直到子序列元素为1, 然后再把有序子序列合并为整体有序序列。

和堆排序一样,利用了完全二叉树,改进了冒泡排序(减少循环次数),需要进行logn次循环。每次循环进行n次扫描,时间复杂度保持在O(nlogn),代价是需要额外的内存空间。

3.8 计数排序(counting sort)

计数排序不是基于比较的排序算法,核心在于将输入的数据值转化为键存储在额外开辟的数组空间中。作为一种线性时间复杂度的排序,计数排序要求输入的数据必须是有确定范围的整数。

  • 找出待排序的数组中最大和最小的元素
  • 用一个array来记保存对应index的数字, 空间换时间

3.9 桶排序(bucket sort)

桶排序是计数排序的升级版。它利用了函数的映射关系,高效与否的关键在于这个映射函数的确定。工作原理:假设输入数据服从均匀分布,将数据分到有限数量的桶里,每个桶再分别排序(有可能再使用别的排序算法或以递归方式继续使用桶排序)

3.10 基数排序(Radix sort)

按照低位先排序,然后收集;再按照高位排序,然后再收集;依次类推,直到最高位。

  • 取得数组中的最大数,并取得位数;
  • arr为原始数组,从最低位开始取每个位组成radix数组;
  • 对radix进行计数排序(利用计数排序适用于小范围数的特点);

4. 算法实现

4.1 冒泡排序(bubble sort)

4.2 选择排序 (selection sort)

4.3 插入排序(insertion sort)

4.4 希尔排序(shell sort)

4.5 归并排序(merge sort)

4.6 快速排序(quick sort)

4.7 堆排序 (heap sort)

4.8 计数排序(counting sort)

4.9 桶排序(bucket sort)

4.10 基数排序(Radix sort)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值