数据结构之排序

插入排序

直接插入排序

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

直接插入排序思想: 把数组分成有序区间 和无序区间 。 初始:[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只适用于除根以外,左右子树本身已经是堆的场景。

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

相关推荐
All for pursuit.3 小时前
【回溯-6】79.单词搜索
数据结构·c++·算法·leetcode
Benny_Tang3 小时前
AT_arc180_d [ARC180D] Division into 3 题解
数据结构·c++·算法
殷色玫瑰3 小时前
C++ STL:stack、queue、priority_queue 与容器适配器详解
java·开发语言·数据结构·c++·算法·visualstudio
秋名RG5 小时前
时间复杂度、空间复杂度与算法稳定性详解
数据结构·算法·排序算法
白色的北极熊5 小时前
c语言 求余运算符
c语言·数据结构·算法
by209996 小时前
list 的使用:把节点、位置和操作联系起来的综合叙述(上)
数据结构·c++·笔记·list
東隅已逝,桑榆非晚6 小时前
数据结构队列
数据结构·笔记·学习
老王爱玩车6 小时前
字符串和字符串函数
c语言·开发语言·数据结构·学习
H.莓飛6 小时前
【数据结构】二叉树
linux·数据结构·算法
梦帮科技7 小时前
【3.0修订版】创世与节点工程:genesis.json 与 node.toml 解剖
数据结构·算法·json·去中心化·区块链·智能合约·信任链