数据结构与算法篇-排序算法-统一视角

排序算法 -- 统一视角

本系列文章尝试从"问题拆分+基准情况+组合解"这个统一视角出发,理解各种排序。

问题求解流程

  • 第一步:原问题怎么拆分?
  • 第二步:最小的子问题是什么?
  • 第三步:如何组合子问题的解得到原问题的解?

本系列文章合集:


选择排序

子问题定义

selectionSort(arr, start):表示当前要排序的子区间是arr[start...n-1]

初始子问题(原问题)

selectionSort(arr, 0):表示当前要排序的子区间是arr[0...n-1]

基准情况

start >= n-1表示当前要排序的子区间是arr[start...n-1]的长度为 0 或者 1。因为单个元素或者空集是有序的,所以该问题已解决,不用继续拆分了。

问题拆分

拆分前:selectionSort(arr, start)

目标:保证位置start对应的元素已在其最终位置上。

操作:从左向右遍历未排序区间,找到最小值,与未排序区间的首个元素交换

拆分后:selectionSort(arr, start+1)

组合子问题的解


冒泡排序

子问题定义

bubbleSort(arr, start):表示当前要排序的子区间是arr[start...n-1]

初始子问题(原问题)

bubbleSort(arr, 0):表示当前要排序的子区间是arr[0...n-1]

基准情况

start >= n-1表示当前要排序的子区间是arr[start...n-1]的长度为 0 或者 1。因为单个元素或者空集是有序的,所以该问题已解决,不用继续拆分了。

问题拆分

拆分前:bubbleSort(arr, start)

目标:保证位置start对应的元素已在其最终位置上。

操作:从右向左遍历未排序区间arr[start...n-1],不断比较相邻元素,如果逆序就交换,最终使得最小值冒泡到该区间的左侧。

拆分后:bubbleSort(arr, start+1)

组合子问题的解


插入排序

子问题定义

insertSort(arr, start)

  • 表示当前要排序的子区间是arr[start...n-1]
  • 区间arr[0...start-1]已有序

初始子问题(原问题):
insertSort(arr, 1)

  • 表示当前要排序的子区间是arr[1...n-1]
  • 区间arr[0...0]已有序,因为此时该区间只有 1 个元素。

基准情况

start >= n表示当前要排序的子区间是arr[n...n-1]的长度为 0 ,且区间arr[0...start-1]已有序。因为空集是有序的,所以该问题已解决,不用继续拆分了。

问题拆分

拆分前:insertSort(arr, start)

目标:保证位置start对应的元素已在其最终位置上。

操作:取未排序区间arr[start...n-1]的首个元素arr[start],从已有序区间arr[0...start-1]中找到其正确的插入位置,将其插入。

拆分后:insertSort(arr, start+1)

组合子问题的解


归并排序

子问题定义

mergeSort(arr, left, right):表示当前要排序的子区间是arr[left...right]

初始子问题(原问题)

mergeSort(arr, 0, n-1):表示当前要排序的子区间是arr[0...n-1]

基准情况

left >= right:表示当前要排序的子区间是arr[left...right],它的长度为 1或者 0,因为单个元素或者空集是有序的,不用继续拆分了。

问题拆分

拆分前:mergeSort(arr, left, right)

操作:取区间的中点mid = left + (right-left)/2

拆分后:mergeSort(arr, left, mid)mergeSort(arr, mid+1, right)

组合子问题的解

合并,即两个有序的子区间arr[left...mid]arr[mid+1...right]合并成一个整体有序的区间arr[left...right]


堆排序

子问题定义

heapSort(arr, heapSize)

  • 当前要排序的子区间是arr[0...heapSize-1]

区间划分状态:

  • 区间arr[0...heapSize-1] 已经是一个合法的堆
  • 区间arr[heapSize..n-1]已有序,且每个元素都在最终位置上

初始子问题(原问题)

heapSort(arr, n)

  • 当前要排序的子区间是arr[0...n-1]

区间划分状态:

  • 区间arr[0...n-1] 已经是一个合法的堆
  • 区间arr[n..n-1]已有序,且每个元素都在最终位置上

基准情况

heapSize<=1

heapSort(arr, 1)

  • 当前要排序的子区间是arr[0...0]

区间划分状态:

  • 区间arr[0...0] 已经是一个合法的堆
  • 区间arr[1..n-1]已有序,且每个元素都在最终位置上

问题拆分

拆分前:heapSort(arr, heapSize)

目标:将当前堆区间的最大值放在其最终位置heapSize-1

操作:

  • 将当前堆区间arr[0, heapSize-1]的最大值跟arr[heapSize-1]交换
  • heapSize--;
  • 对缩小后的堆区间arr[0,heapSize-1]执行下沉操作,以恢复堆性质

拆分后:heapSort(arr, heapSize-1)

组合子问题的解


相关推荐
计算机安禾1 天前
【算法分析与设计】第4篇:分治策略的理论框架与经典案例
数据结构·算法·排序算法
夏日听雨眠1 天前
数据结构(BF算法 )
数据结构·算法·排序算法
图码1 天前
[特殊字符] 高效统计排序数组中目标元素的出现次数
数据结构·算法·排序算法·柔性数组·图搜索
Severus_black1 天前
【初阶数据结构与算法】八大排序之插入排序(直接插入、希尔),一次性讲清!
数据结构·算法·排序算法
代码中介商2 天前
排序算法完全指南(五):快速排序深度详解
数据结构·算法·排序算法
清木!3 天前
排序算法比较
数据结构·算法·排序算法
Noushiki3 天前
常见的排序算法
算法·排序算法
历程里程碑3 天前
56 . 高效ET非阻塞IO服务器设计指南
java·运维·服务器·开发语言·数据结构·c++·排序算法
代码中介商4 天前
排序算法完全指南(三):插入排序深度详解
算法·排序算法
承渊政道4 天前
【贪心算法】(经典实战应用解析(六):整数替换、俄罗斯套娃信封问题、可被三整除的最⼤和、距离相等的条形码、重构字符串)
c++·算法·leetcode·贪心算法·排序算法·动态规划·哈希算法