跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI 生图工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
Javajava算法

数据结构实战:选择排序原理与 Java 实现

选择排序通过每趟选取最小元素并交换位置来实现排序。涵盖直接选择、树形选择及堆排序三种变体,解析其核心思想与执行流程。结合 Java 代码示例,演示了建堆、筛选及交换的具体实现逻辑,并分析了各算法的时间复杂度与空间开销,帮助理解不同场景下的排序策略选择。

乱七八糟发布于 2026/3/29更新于 2026/9/1051 浏览
数据结构实战:选择排序原理与 Java 实现

选择排序详解

选择排序的核心思想在于每一趟从待排序列中选取一个关键字值最小的记录,将其放到已排序序列的末尾。第 1 趟从 n 个记录中选出最小值,第 2 趟从剩余的 n-1 个记录中选出次小值,依此类推,直到所有记录归位。

直接选择排序

核心思路

首先在所有记录中找出关键字最小的记录,与第一个记录交换;然后在剩余记录中找次小记录,与第二个记录交换。重复此过程,直到整个序列有序。

直接选择排序演示

执行示例

假设待排序序列为 { 5, 3, 6, 4, 7, 1, 8, 2 }。初始视为无序序列,每趟遍历后,有序区长度 +1,无序区长度 -1。图示中红色标记代表已排序区域,实际推导时可用方框标注。

代码实现

public void selectSort() {
    RecordNode temp;
    // 进行 i-1 次遍历,this.curlen 为数组长度
    for(int i=0; i<this.curlen-1; i++) {
        int min = i;
        // 在无序区寻找最小值索引
        for(int j=i+1; j<this.curlen; j++) {
            if (r[j].key.compareTo(r[min].key) < 0) {
                min = j;
            }
        }
        // 如果找到更小的元素,则交换位置
        if (min != i) {
            temp = r[i];
            r[i] = r[min];
            r[min] = temp;
        }
    }
}

性能分析

直接选择排序的时间复杂度始终为 O(n²),空间复杂度为 O(1)。虽然移动次数较少,但比较次数固定,稳定性较差(不稳定排序)。

树形选择排序

核心思路

先对 n 个记录两两比较,将较小者作为优胜者上升到父结点。重复此过程,直到选出最小关键字值。整个过程可用一棵含有 n 个叶子结点的完全二叉树表示。

树形选择排序演示

执行示例

以序列 { 52, 39, 67, 95, 70, 8, 25, 52 } 为例。叶子节点位于最后一层,两两 PK,谁小谁上父亲节点。找到最小值后,将其替换为无穷大'∞',再次两两 PK 即可找到次小值,以此类推完成排序。

树形选择排序次小值查找

性能分析

相比直接选择排序,树形选择减少了比较次数,时间复杂度约为 O(n log n),但需要额外的辅助空间来存储树结构。

堆排序

定义与方法

堆是一种特殊的完全二叉树结构。若所有非终端结点的值均不大于其左右孩子结点,称为大顶堆;反之则为小顶堆。堆排序利用堆的性质,每次将堆顶元素(最大或最小值)与末尾元素交换,再重新调整堆。

大小顶堆示意图

筛选过程

所谓'筛选',是指当堆顶被破坏后,从上往下调整使整棵树恢复堆性质的过程。例如,最大值 98 与末尾元素交换后,原末尾元素下沉至根节点,此时需重新筛选,确保左/右子树仍满足堆条件。

堆排序筛选过程

建初始堆

建堆是一个从下往上进行'筛选'的过程。对于长度为 n 的序列,从最后一个非叶节点开始向前遍历,依次调整节点性质。注意调整过程中可能会打破子树的堆性质,需递归继续调整。

建堆过程演示

代码实现

public class HeapSort {
    public static void heapSort(int[] arr) {
        if (arr == null || arr.length == 0) {
            return;
        }
        int len = arr.length;
        // 构建大顶堆
        buildMaxHeap(arr, len);
        // 交换堆顶和当前末尾节点,重置大顶堆
        for (int i = len - 1; i > 0; i--) {
            swap(arr, 0, i);
            len--;
            heapify(arr, 0, len);
        }
    }

    private static void buildMaxHeap(int[] arr, int len) {
        // 从最后一个非叶节点开始向前遍历
        for (int i = (int)Math.floor(len / 2) - 1; i >= 0; i--) {
            heapify(arr, i, len);
        }
    }

    private static void heapify(int[] arr, int i, int len) {
        int left = 2 * i + 1;
        int right = 2 * i + 2;
        int largestIndex = i;

        if (left < len && arr[left] > arr[largestIndex]) {
            largestIndex = left;
        }
        if (right < len && arr[right] > arr[largestIndex]) {
            largestIndex = right;
        }

        if (largestIndex != i) {
            swap(arr, i, largestIndex);
            // 互换后子节点值变化,需递归调整
            heapify(arr, largestIndex, len);
        }
    }

    private static void swap(int[] arr, int i, int j) {
        int temp = arr[i];
        arr[i] = arr[j];
        arr[j] = temp;
    }
}

性能分析

堆排序的时间复杂度为 O(n log n),空间复杂度为 O(1)。它是不稳定排序,但在处理大规模数据时表现优于直接选择排序。

总结

  • 直接选择排序:逻辑简单,适合小规模数据,但效率较低。
  • 树形选择排序:减少比较次数,适合外部排序场景,但空间开销较大。
  • 堆排序:效率高,适合大规模数据。升序建大堆,降序建小堆。筛选是破坏后调整,建堆是从下往上调整。

目录

  1. 选择排序详解
  2. 直接选择排序
  3. 核心思路
  4. 执行示例
  5. 代码实现
  6. 性能分析
  7. 树形选择排序
  8. 核心思路
  9. 执行示例
  10. 性能分析
  11. 堆排序
  12. 定义与方法
  13. 筛选过程
  14. 建初始堆
  15. 代码实现
  16. 性能分析
  17. 总结

更多推荐文章

查看全部
  • 10 个提升 AI 模型能力的必备技能
  • QGroundControl 跨平台安装指南:多系统快速部署实战
  • Linux 搭建 Web 服务器指南:Nginx 与 Apache 实战
  • PyQt5 入门教程:基础与常用控件详解
  • 计算机视觉基础理论与实战应用指南
  • 中国 AI 大模型未来五年五大潜力应用场景展望
  • Java File 类核心 API 详解与使用
  • LangChain Agent 中间件详解:提升可靠性与可控性
  • JeecgBoot 低代码平台 AI 功能与零代码开发指南
  • Capacitor 实战指南:将 Web 项目打包为跨平台应用
  • ASR 自动语音识别原理与 Whisper 模型详解
  • 无人机电力设备智能巡检检测数据集:缺陷检测与分类
  • 近端策略优化算法 PPO 详解与 PyTorch 实现
  • JSP 文件上传实战:原理、实现与安全注意事项
  • Linux 调试器 gdb 和 cgdb 使用指南
  • 用 QQ 私聊打造全自动化运维助手
  • Z-Image-Turbo WebUI 本地部署与实战指南
  • 2025 年 11 月 14 日全球 AI 前沿动态
  • Qwen Code 与 OpenSpec 实战指南:AI 驱动开发安装与落地
  • 创建 GitHub 私有仓库并上传本地项目

相关免费在线工具

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online