数据结构之排序

插入排序

直接插入排序

直接插入排序故名思意就是直接插入

直接插入排序思想: 把数组分成有序区间无序区间 。 初始:[0, i] 是有序区间,i+1 是无序区间第一个元素。 每次拿出无序区间第一个元素tmp = a[i+1],向前在有序区间里找它该插入的位置:

  1. 如果 a[end] > tmp:把有序区间元素向后挪一位,给 tmp 腾出位置;
  2. 一旦 a[end] <= tmp,停止移动;
  3. tmp放到end+1的位置。
  4. 循环,不断扩大有序区间,直到全部有序。

希尔排序

希尔排序在某种角度可以认为是预排序,让数组先变的更加有序,就可以减少排序和调换

什么是希尔排序

希尔排序,也叫缩小增量排序 ,是直接插入排序的优化版本

直接插入排序有个短板:如果一个很小的元素在数组末尾,需要一步一步向前挪,移动次数非常多。 希尔排序的核心思路:先分组,远距离调整元素,让数组整体趋向接近有序;最后再做一次普通直接插入排序(步长 = 1)

本质:分组的直接插入排序 把下标相差 d 的元素分到同一组,每组内部执行直接插入排序;不断缩小步长d,直到 d=1

举例子:数组 [9,8,7,6,5,4,3,2,1],数组长度n=9

  1. 第一轮:步长 d = n/2 = 4 分组:下标相差 4 为一组
    • 组 0:0,4,8
    • 组 1:1,5
    • 组 2:2,6
    • 组 3:3,7 每组内部做直接插入排序。一次性把远距离的大数往后、小数往前挪。
  2. 第二轮:步长 d = d/2 = 2 分组:下标相差 2 一组,继续分组插入排序,数组更加有序。
  3. 第三轮:步长 d = d/2 =1 d=1 等价于普通直接插入排序,此时数组已经接近有序,插入排序速度很快,最终得到完全有序数组。

但是对于d的选择,缩小增量的选择有很多

高德纳(Knuth)提出的经典希尔排序步长(增量)序列

选择排序

简单选择排序

可以简单认为就是在一组未排序的数组中选择当中最小的数交换最前面,在不断重复这个过程

简单选择排序的思路非常直观:不断在未排序区间找到最小值,放到未排序区间的最左端。 把数组分成两部分:

  • 左边:已排序区间
  • 右边:未排序区间

每一轮操作:

  1. 在未排序区间找到最小元素的下标
  2. 将最小元素,和未排序区间第一个元素交换
  3. 已排序区间长度 + 1,未排序区间缩小
  4. 重复直到全部有序

和直接插入排序区分: 插入排序:拿当前元素,往前找位置插入;移动次数少,比较多 选择排序:先找最值,最后一次性交换;比较次数多,交换很少

堆排序

堆排序完整原理

  1. 建堆 :把原始数组调整成大根堆。从最后一个非叶子节点向前,依次执行向下调整AdjustDown
  2. 交换堆顶和末尾元素:堆顶是最大值,把它交换到数组尾部(尾部变成有序区)。
  3. 向下调整:交换之后,堆顶破坏了堆性质,对新堆顶执行向下调整,剩下未排序区间重新恢复大根堆。
  4. 重复步骤 2、3,直到堆的有效元素只剩 1 个,数组全局有序。

重点:向下调整AdjustDown只适用于除根以外,左右子树本身已经是堆的场景。

之前在二叉树那里已经讲过,不做过多赘述

相关推荐
我不会起名字3224 小时前
一天一道算法题(34):回溯法的经典例题(子集)
java·数据结构·python·算法·golang·深度优先·力扣
Logic1016 小时前
C语言/数据结构位运算题解:异或XOR找出货船中的“独特载货量“——只出现一次的数字
c语言·数据结构·数组·位运算·时间复杂度·算法题·异或性质
彧azz7 小时前
DFS与BFS:图遍历的两大核心算法
数据结构·学习·算法·深度优先·广度优先
青山木8 小时前
Hot 100 --- 最长递增子序列
java·数据结构·算法·leetcode·动态规划
土司大王9 小时前
LeetCode hot100——33.搜索旋转排序数组:Java 二分模板与 O(log n) 实现
数据结构·算法·leetcode
程序员阿鹏9 小时前
如何实现MySQL分库分表?
数据结构·数据库·sql·mysql·缓存
ysu_031411 小时前
08-二叉树遍历:四种方式详解
c语言·数据结构·算法·leetcode
Lyyaoo.11 小时前
【二分查找】【中等】搜索二维矩阵/排序数组的第一位和最后位置/搜索旋转排序数组/旋转排序数组中的最小值
java·数据结构·算法
Lyyaoo.12 小时前
【二分查找】【困难】寻找两个有序数组的中位数
java·数据结构·算法