蓝桥杯Python赛道备赛——Day3:排序算法(二)(归并排序、堆排序、桶排序)

ops/2025/3/15 13:07:45/

   本博客是蓝桥杯备赛系列中排序算法的第二期,包括:归并排序、堆排序和桶排序。每一个算法都在给出概念解释的同时,给出了示例代码,以供低年级师弟师妹们学习和练习。

   由于本期的三个算法的复杂度相对来说要高于上一期的三个算法,因此,每个算法均以某个待排序的数组为例,进行逐步分析。

   前序知识:
(1)Python基础语法
(2)Python基础算法
(3)基本数据结构:二叉树初步(知道他是啥就好,详细的数据结构内容计划在Day4讲解)。

   Tips:若对基本数据结构不太了解,可以先往下看,当看到不太懂的内容(如:“堆”)时,再去搜索。


排序算法(二)

      • 一、归并排序
      • 二、堆排序
      • 三、桶排序

一、归并排序

1. 流程示意图:
在这里插入图片描述

2. 举例说明:
   就像上图中所描述的那样,先进行拆分,再逐步合并。
(1)步骤1:递归拆分

原始数组:[38,27,43,3,9,82,10]
第1层拆分:左=[38,27,43]=[3,9,82,10]
第2层拆分:左左=[38] 左右=[27,43] | 右左=[3,9] 右右=[82,10]
继续拆分直到所有子数组长度为1

(2)步骤2:有序合并

左子数组:[27,38,43]  右子数组:[3,9,10,82]
比较过程:3<27 → 填3;9<27 → 填9;10<27 → 填10;27<82 → 填27...
最终结果:[3,9,10,27,38,43,82]

3. 性能分析
(1)优点:

  • 稳定排序(相同值保持原顺序)
  • 时间复杂度稳定O(n log n)
  • 适合链表等非连续存储结构

(2)缺点:

  • 需要额外O(n)存储空间
  • 递归调用栈可能造成内存开销
  • 小规模数据效率低于插入排序

4. 示例代码:

python"># 归并排序
import numpy as npdef merge_sort(arr):# 递归终止条件:当数组长度<=1时直接返回if len(arr) <= 1:return arr# 分治步骤:将数组平分成左右两部分mid = len(arr) // 2left = merge_sort(arr[:mid])  # 递归处理左半部分right = merge_sort(arr[mid:]) # 递归处理右半部分# 合并两个有序数组return merge(left, right)def merge(left, right):merged = np.empty(len(left)+len(right), dtype=left.dtype) # 创建空数组存放结果l = r = i = 0  # 初始化三个指针# 比较左右数组元素并填充while l < len(left) and r < len(right):if left[l] <= right[r]:merged[i] = left[l]l += 1else:merged[i] = right[r]r += 1i += 1# 处理剩余元素merged[i:] = left[l:] if l < len(left) else right[r:]return merged# 示例运行
arr = np.array([38, 27, 43, 3, 9, 82, 10])
print("原数组:", arr)
sorted_arr = merge_sort(arr)
print("归并排序结果:", sorted_arr)

二、堆排序

1. 流程示意图:
在这里插入图片描述

2. 举例说明:
(1)步骤1:构建“大根堆”(确保“子节点”永远小于其“双亲节点”)

初始数组:[12,11,13,5,6,7]
构建堆过程:调整节点1(11)→ 无交换调整节点0(12)→ 与13交换 → [13,11,12,5,6,7]

(2)步骤2:排序阶段,本质是“大根堆”的性质维护

第1次交换后:[7,11,12,5,6,13]
重新堆化后:[12,11,7,5,6,13]
第2次交换后:[6,11,7,5,12,13]
...

3. 性能分析
(1)优点:

  • 原地排序(空间复杂度O(1))
  • 最坏情况仍保持O(n log n)
  • 适合实时数据处理

(2)缺点:

  • 不稳定排序
  • 缓存不友好(跳跃访问)
  • 实现复杂度较高

4. 示例代码:

python"># 堆排序
import numpy as npdef heapify(arr, n, i):largest = i  # 初始化最大元素为根节点left = 2 * i + 1right = 2 * i + 2# 检查左子节点是否大于根if left < n and arr[left] > arr[largest]:largest = left# 检查右子节点是否大于当前最大值if right < n and arr[right] > arr[largest]:largest = right# 如果最大值不在根节点,进行交换并递归调整if largest != i:arr[i], arr[largest] = arr[largest], arr[i]heapify(arr, n, largest)def heap_sort(arr):n = len(arr)# 构建最大堆(从最后一个非叶子节点开始)for i in range(n//2 - 1, -1, -1):heapify(arr, n, i)# 逐个提取元素for i in range(n-1, 0, -1):arr[i], arr[0] = arr[0], arr[i]  # 交换堆顶和末尾元素heapify(arr, i, 0)  # 调整剩余元素的堆结构return arr# 示例运行
arr = np.array([12, 11, 13, 5, 6, 7])
print("\n原数组:", arr)
heap_sort(arr)
print("堆排序结果:", arr)

三、桶排序

1. 基本步骤:
(1)步骤1:分桶策略
   示例:数据范围0-49,桶大小10 → 5个桶(0-9,10-19,…40-49)
(2)步骤2:桶内排序
   使用任意排序算法,对桶内的数据进行排序。因此,桶内排序算法的选择将影响整体性能。

2. 性能分析
(1)优点:

  • 线性时间复杂度O(n+k)(k为桶数量)
  • 稳定排序(若桶内排序稳定)
  • 适合外部排序场景

(2)缺点:

  • 依赖数据均匀分布
  • 需要额外内存存储桶
  • 空桶会造成空间浪费

3. 示例代码:

python"># 桶排序
import numpy as npdef bucket_sort(arr, bucket_size=5):# 确定数据范围min_val, max_val = np.min(arr), np.max(arr)# 计算需要的桶数量bucket_count = (max_val - min_val) // bucket_size + 1buckets = [[] for _ in range(bucket_count)]  # 初始化空桶# 元素分配到桶中for num in arr:idx = (num - min_val) // bucket_sizebuckets[idx].append(num)# 对每个桶内部排序(这里使用内置排序)sorted_arr = np.empty_like(arr)i = 0for bucket in buckets:if len(bucket) > 0:sorted_bucket = np.sort(bucket)  # 实际比赛可用其他排序算法sorted_arr[i:i+len(sorted_bucket)] = sorted_bucketi += len(sorted_bucket)return sorted_arr# 示例运行
arr = np.array([29, 25, 3, 49, 9, 37, 21, 43])
print("\n原数组:", arr)
sorted_arr = bucket_sort(arr)
print("桶排序结果:", sorted_arr)

http://www.ppmy.cn/ops/165946.html

相关文章

数学 :矩阵

文章目录 前言1. 基本矩阵运算1.1 矩阵加法1.2 矩阵减法1.3 矩阵乘法 2. 转置矩阵3. 旋转矩阵小结 【全文大纲】 : https://blog.csdn.net/Engineer_LU/article/details/135149485 前言 在许多应用场合下&#xff0c;我们都需要用矩阵来表示公式&#xff0c;接下来简洁描述矩阵…

C++ 滑动窗口

前言 C 中滑动窗口分两种&#xff0c;一种是给定窗口长度&#xff0c;还有一种是不定长窗口长度。 本篇文章主要讲解这两种状态的滑动窗口&#xff0c;结合例题让读者更好的理解 一、给定窗口长度K 一般的&#xff0c;对于给定窗口长度的题&#xff0c;通常要求我们对窗口内…

6、STL中list的使用方法

一、了解 list 是标准模板库&#xff08;STL&#xff09;提供的一个双向链表容器。它与 std::vector 或 std::array 不同&#xff0c;不支持随机访问&#xff08;即通过下标直接访问元素&#xff09;[只能用迭代器访问元素]&#xff0c;但支持在任意位置的高效插入和删除操作。…

关于使用Visual Studio编码问题

目录 1.修改区域 2. 使用/utf-8命令 3.手改 问题&#xff1a;今天遇到很烦问题&#xff0c;同一份代码&#xff0c;张三说他的代码格式是utf-8&#xff0c;李四说他的是GB2312(简中)的&#xff0c;然后李四上传代码&#xff0c;张三说是乱码&#xff0c;张三上传代码&#xf…

第九课:异步爬虫进阶:aiohttp与多线程的技术博客

在Python爬虫开发中&#xff0c;性能优化始终是一个重要的课题。随着网络数据的爆炸式增长&#xff0c;传统的同步爬虫在面对大量请求时显得力不从心。异步爬虫和多线程技术应运而生&#xff0c;成为提升爬虫性能的关键手段。本文将深入探讨Python异步爬虫进阶技术&#xff0c;…

SAP Commerce(Hybris)促销模块(一):优惠券配置

基于Hybris的Backoffice后台管理系统&#xff0c;创建一个基于模板的促销规则&#xff0c;并配置上对应的优惠活动。 架构设计 先从一张架构图说起 Hybris的促销模块&#xff0c;是基于Promotion引擎来实现的&#xff0c;可以通过Backoffice来进行配置。 通过上面的架构图又可…

笔记本电脑开机自动启用自定义电源计划方法

笔记本电脑开机自动启用电源计划方法 **方法一:通过任务计划程序设置(推荐)** 获取电源计划的GUID o 按 Win + S,搜索 cmd,右键选择 以管理员身份运行。 o 输入以下命令查看所有电源计划及其GUID: powercfg /list o 找到你创建的电源计划,记录其GUID(例如:8c5e7fda-e8…

TDengine 使用教程:从入门到实践

TDengine 是一款专为物联网&#xff08;IoT&#xff09;和大数据实时分析设计的时序数据库。它能够高效地处理海量的时序数据&#xff0c;并提供低延迟、高吞吐量的性能表现。在本文中&#xff0c;我们将带领大家从 TDengine 的安装、基本操作到一些高级功能&#xff0c;帮助你…