排序算法集合

目录

1.前言

2.直接插入排序:

3.希尔排序( 缩小增量排序 )

4.选择排序

4.1直接选择排序:

4.2堆排序

5.交换排序

5.1冒泡排序

5.2.快速排序

6.归并排序

7.非比较类排序


1.前言

  • 稳定性:假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中,r[i]=r[j],且r[i]在r[j]之前,而在排序后的序列中,r[i]仍在r[j]之前,则称这种排序算法是稳定的;否则称为不稳定的。
  • 内部排序:数据元素全部放在内存中的排序。
  • 外部排序:数据元素太多不能同时放在内存中,根据排序过程的要求不能在内外存之间移动数据的排序。

2.直接插入排序:

  • 当插入第i(i>=1)个元素时,前面的array[0],array[1],…,array[i-1]已经排好序,此时用array[i]的排序码与array[i-1],array[i-2],…的排序码顺序进行比较,找到插入位置即将array[i]插入,原来位置上的元素顺序后移
  • 如果要排降序,只需将内层循环条件改为大于比较即可:key > arr[index]
  • 1.时间复杂度O(N^2)
  • 2.插入排序应用场景:元素集合越接近有序,直接插入排序算法的时间效率越高
  • 3.空间复杂度:O(1),它是一种稳定的排序算法
  • 4. 稳定性:稳定

3.希尔排序( 缩小增量排序 )

  • 场景:元素序列比较随机(不是接近有序),而且元素数量比较大,要求:按照插入排序方式来排序
  • 稳定性:不稳定,只要是隔着区间交换或这插入都不稳定
  • 时间复杂度:
    • 希尔排序的时间复杂度不好计算,因为gap的取值方法很多,导致很难去计算,因此在好些树中给出的希尔排序的时间复杂度都不固定:
    • 《数据结构(C语言版)》--- 严蔚敏
    • 《数据结构-用面相对象方法与C++描述》--- 殷人昆
    • 代码实现时,gap是按照Knuth提出的方式取值的,而且Knuth进行了大量的试验统计,时间复杂度按照O(N^1.25) ~O(1.6*N^1.25)来计算
  • 空间复杂度:O(1)

4.选择排序

  • 基本思想:
    • 每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始(或末尾)位置,直到全部待排序的数据元素排完 。
  • 4.1直接选择排序:

    • 在元素集合array[i]--array[n-1]中选择关键码最大(小)的数据元素
    • 若它不是这组元素中的最后一个(第一个)元素,则将它与这组元素中的最后一个(第一个)元素交换
    • 在剩余的array[i]--array[n-2](array[i+1]--array[n-1])集合中,重复上述步骤,直到集合剩余1个元素
    • 1. 直接选择排序思考非常好理解,但是效率不是很好。实际中很少使用
    • 2. 时间复杂度:O(N^2)
    • 3. 空间复杂度:O(1)
    • 4. 稳定性:不稳定
  • 直接选择排序优化
    • 在一次选择过程中,既然可以找到最大元素的位置,那必然也可以找到最小元素位置
    • maxPos标记的最大元素与区间最后一个位置元素进行交换
    • minPos标记的最小元素与区间第一个元素进行交换
    • 每趟选择就可以将两个元素处理好
    • 缺陷:部分元素可能存在重复比较
  • 4.2堆排序

    • 排升序要建大堆,排降序建小堆。
    • 1. 堆排序使用堆来选数,效率就高了很多。
    • 2. 时间复杂度:O(N*logN)
    • 3. 空间复杂度:O(1)
    • 4. 稳定性:不稳定

5.交换排序

  • 5.1冒泡排序

    • 1. 冒泡排序是一种非常容易理解的排序
    • 2. 时间复杂度:O(N^2)
    • 3. 空间复杂度:O(1)
    • 4. 稳定性:稳定
  • 5.2.快速排序

    • 快排大的思想:
      • 1.从区间中找一个元素作为基准值,然后按照基准值将区间划分成两部分
      • 2.递归:使用快排对基准值的左侧进行排序,使用快排对基准值的右侧进行排序
      • 快速排序主体框架
    • 划分的方式:
      • hoare版本:提出快速排序的大佬
      • 挖坑法
      • 前后指针法
    • 空间复杂度:O(logN)
    • 稳定性:不稳定
    • 快排时间复杂度法分析:
      • 基准值取得好,划分区间比较均匀
      • 最糟糕的情况
      • 快排不适合排:序列有序或者接近有序----数据越杂乱越好
    • 快排优化:
      • 1.基准值选择问题
        • 一般情况下不会直接拿区间最左侧或者最右侧的数据作为基准值,因为按照这种方式获取基准值,拿到最大或者最小值的概率可能会非常高,严重影响快排的效率
        • 三数取中法:最左侧、最中间、最右侧位置的数据,取这三个数据最中间的数据作为基准值
      • 假设:待排序集合中元素非常多,将来就会导致平衡二叉树的高度非常高---递归的深度:即递归到某个区间中只有一个元素时,递归才会回退
      • 存在的问题:
        • 1.递归深度达到一定程度---可能会导致栈溢出
        • 2.越往下递归,区间中数据越来越少,当区间中元素越来越少时,快排就不是最理想的排序算法了
      • 2.递归时区间中元素过少时可以采用插入排序优化
      • 3.待排序数据如果非常多,递归深度会非常深,在没有达到递归出口时,栈溢出?
        • 方式一:
          • 1.可以算递归深度----n个元素-->H = log2N,如果超过程序中涉及的递归总次数阈值,采用堆排序方法(时间复杂度相等)
          • 2.递归转循环
            • 方式1
            • 方式2:

6.归并排序

  • 主要步骤:
    • 1.划分,对区间进行均分
    • 2.递归处理左区间,递归处理右区间
    • 3.合并,将两个有序的区间进行合并
  • 归并排序循环方式:
  • 总结:
    • 1. 归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题(外部排序)。
    • 2. 时间复杂度:O(N*logN)
    • 3. 空间复杂度:O(N)
    • 4. 稳定性:稳定
  • 归并排序应用于海量数据:
    • 假设现在有100G的数据,且当前能够的使用的内存只有1G

7.非比较类排序

  • 计数排序
    • 应用场景:数据密集集中在某个范围中
    • 步骤:
      • 1.求范围,找到数据中的最大值和最小值,range=MaxValue - MinValue+1;
      • 2.统计区间中每个元素出现的次数
      • 3.数据回收:按照计数数组的下标来进行回收
  • 基数排序:
    • LSD:低关键码优先:循环处理,个位--->十位--->百位·····
    • 对于每个数据,每一位上的数字都在0~9范围内
      • 1.划分:按照对应位上的数字将元素放入到对应的桶中
      • 2.回收:按照桶号由小到大的顺序,每个桶中按照先放先回收----回收数据

猜你喜欢

转载自blog.csdn.net/sy2453/article/details/125929475
今日推荐