当前位置: 首页 > news >正文

【数据结构详解】——选择排序(动图详解)

目录

  • 🕒 1. 直接选择排序
  • 🕒 2. 堆排序

🕒 1. 直接选择排序

💡 算法思想:第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始(末尾)位置,然后选出次小(或次大)的一个元素,存放在最大(最小)元素的下一个位置,重复这样的步骤直到全部待排序的数据元素排完。
请添加图片描述

代码实现如下:这里可以进行一个优化,最小值和最大值同时选,然后将最小值与起始位置交换,将最大值与末尾位置交换。

void Swap(int* p1, int* p2)
{int tmp = *p1;*p1 = *p2;*p2 = tmp;
}void SelectSort(int* a, int n)
{int begin = 0;  // 起始位置int end = n - 1;  // 结束位置// 循环直到整个数组都被排序while (begin < end){int mini = begin;  // 保存最小元素下标int maxi = begin;  // 保存最大元素下标// 在当前未排序部分查找最小和最大元素的下标for (int i = begin + 1; i <= end; ++i){if (a[i] < a[mini]){mini = i;  // 更新最小元素下标}if (a[i] > a[maxi]){maxi = i;  // 更新最大元素下标}}// 将找到的最小元素交换到起始位置Swap(&a[begin], &a[mini]);// 如果最大元素的位置在起始位置,更新最大元素下标为 miniif (maxi == begin){maxi = mini;}// 将找到的最大元素交换到末尾位置Swap(&a[end], &a[maxi]);// 缩小排序范围++begin;--end;}
}

在这里插入图片描述

选择排序的特性总结:

  1. 选择排序步骤非常好理解,但是效率不是很好(不论数组是否有序都会执行原步骤),实际中很少使用。
  2. 时间复杂度:O(N2)
  3. 空间复杂度:O(1)
  4. 稳定性:不稳定

🕒 2. 堆排序

💡 算法思想:堆排序即利用堆的思想来进行排序,总共分为两个步骤:1. 建堆升序:建大堆;降序:建小堆) 2. 利用堆删除思想来进行排序:建堆和堆删除中都用到了向下调整,因此掌握了向下调整,就可以完成堆排序。

这里以升序为例:

  • 首先应该建一个大堆,不能直接使用堆来实现。可以将需要排序的数组看作是一个堆,但需要将数组结构变成堆结构。
  • 我们可以从堆从下往上的第二行最右边开始依次向下调整直到调整到堆顶,这样就可以将数组调整成一个堆,且如果建立的是大堆,堆顶元素为最大值。
  • 然后按照堆删的思想将堆顶和堆底的数据交换,但不同的是这里不删除最后一个元素。
  • 这样最大元素就在最后一个位置,然后从堆顶向下调整到倒数第二个元素,这样次大的元素就在堆顶,重复上述步骤直到只剩堆顶时停止。

请添加图片描述

// AdjustDown函数:在数组a中,从节点root开始向下调整,使得以root为根的子树满足大顶堆的性质。
void AdjustDown(int* a, int n, int root)
{assert(a);int parent = root; // 当前子树的根节点int child = parent * 2 + 1; // 左孩子节点// 循环直到没有孩子节点while (child < n){// 如果右孩子存在且比左孩子大,则选择右孩子作为比较对象if (child + 1 < n && a[child + 1] > a[child]){child++;}// 如果孩子节点比父节点大,则交换父节点和孩子节点的值,并更新父节点和孩子节点继续向下比较if (a[child] > a[parent]){Swap(&a[child], &a[parent]);parent = child;child = parent * 2 + 1;}else{break; // 如果孩子节点不再比父节点大,则退出循环}}
}void HeapSort(int* a, int n)
{assert(a);// 建立大顶堆for (int i = (n - 1 - 1) / 2; i >= 0; i--){AdjustDown(a, n, i); // 对每个非叶子节点进行向下调整,建立大顶堆}// 交换堆顶元素和末尾元素,并重新调整堆for (int i = n - 1; i > 0; i--){Swap(&a[i], &a[0]); // 将当前堆顶(最大值)与数组末尾元素交换AdjustDown(a, i, 0); // 调整剩余堆为大顶堆,范围缩小为0到i-1}
}

在这里插入图片描述

堆排序的特性总结:

  1. 堆排序使用堆来选数,效率较高,适用于需要频繁插入和删除的场景。
  2. 时间复杂度:O(N*logN)
  3. 空间复杂度:O(1)
  4. 稳定性:不稳定

❗ 转载请注明出处
作者:HinsCoder
博客链接:🔎 作者博客主页

http://www.lryc.cn/news/420325.html

相关文章:

  • 杂项命令(笔记)
  • 代码随想录算法训练营Day38||完全背包问题、leetcode 518. 零钱兑换 II 、 377. 组合总和 Ⅳ 、70. 爬楼梯 (进阶)
  • 超越链端:Web3的无边界技术革命
  • 127. Go反射基本原理
  • 提高PDF电子书的分辨率
  • Spring Cloud全解析:注册中心之zookeeper注册中心
  • 解决戴尔台式电脑休眠后无法唤醒问题
  • MySQL运维-分库分表
  • AGX orin硬件设计
  • AI大模型开发——2.深度学习基础(1)
  • go语言day22 gin-vue-admin全栈项目的依赖安装
  • PHP之docker学习笔记
  • 基于树莓派4B与STM32的UART串口通信实验(代码开源)
  • 【云服务器系列】基于华为云OBS实现Picgo和Typora的完美融合
  • IIC协议
  • 如何在linux系统上部署nginx
  • 香港网站服务器抵御恶意攻击的一些措施
  • 实战:docker部署filesite.io完美解决家庭相册需求-2024.8.10(测试成功)
  • 美团到店面经
  • 【CSS入门】第五课 - font字体
  • STM32-门电路-储存器-寄存器-STM32f1-MCU-GPIO-总线-keil5-点led-寄存器编程
  • 【动态规划算法题记录】343. 整数拆分 | 96.不同的二叉搜索树
  • 网页上预览Excel文件
  • Unity射击游戏开发教程:(31)制造一定追踪行为的敌人
  • springboot mybatis plus 固定查询条件及可选查询条件的组合查询,使用QueryWrapper.and()来解决。
  • 使用ollama取代openai的api进行graphRAG失败记录
  • MyBatis 配置与测试方式
  • C#实现代理服务器
  • react的路由实战使用
  • python 字典转成类 构建类