0

0

递归实现冒泡排序:两种策略与核心原理深度解析

心靈之曲

心靈之曲

发布时间:2025-10-31 14:54:01

|

946人浏览过

|

来源于php中文网

原创

递归实现冒泡排序:两种策略与核心原理深度解析

本文深入探讨了递归实现冒泡排序的两种常见方法,重点分析了递归基的选择和递归参数的变化趋势。通过对比不同实现,阐明了尽管递归参数可能递增或递减,但核心在于每一步都有效缩小问题规模。文章旨在消除对递归理解的常见误区,并提供清晰的实现示例和注意事项。

递归冒泡排序概述

冒泡排序是一种基础的排序算法,其工作原理是重复遍历待排序的列表,比较相邻元素并交换那些顺序错误的元素,直到整个列表有序。这种算法的特点是,在每一轮遍历后,未排序部分的最大(或最小)元素会“冒泡”到其最终位置。例如,一轮完整的遍历会将当前未排序部分的最大元素放置到其末尾。正是这种“缩小未排序范围”的特性,使得冒泡排序可以自然地用递归方式实现。

递归的核心在于将一个大问题分解为与自身相似的更小问题,直到达到一个可以直接解决的“基本情况”(Base Case)。对于递归冒泡排序,每次递归调用都负责将一个元素放置到其正确位置,然后对剩余的子数组进行排序。

传统递归实现:参数递减法

在递归实现冒泡排序时,一种常见的策略是使用一个递减的参数来表示当前需要排序的子数组的长度。

核心思想: 每次递归调用执行一轮冒泡操作,将当前未排序子数组的最大元素移动到其末尾。完成这一步后,这个最大元素就已就位,下一轮递归只需要处理剩余的 n-1 个元素。

示例代码:

import java.util.Arrays;

public class RecursiveBubbleSort {

    /**
     * 传统递归冒泡排序方法,通过递减参数n控制排序范围。
     * 每一趟将当前子数组的最大元素“冒泡”到末尾。
     * @param arr 待排序数组
     * @param n 当前需要排序的子数组长度
     */
    public static void sortingRecursionDecreasing(int[] arr, int n) {
        // 递归基:当子数组长度为1时,说明只剩一个元素,无需排序,直接返回。
        if (n == 1) {
            return;
        }

        // 执行一趟冒泡排序,将当前子数组(长度为n)的最大元素移到 arr[n-1]
        for (int i = 0; i < n - 1; i++) {
            if (arr[i] > arr[i + 1]) {
                // 交换元素
                int temp = arr[i];
                arr[i] = arr[i + 1];
                arr[i + 1] = temp;
            }
        }

        // 递归调用:对剩余的 n-1 个元素进行排序
        sortingRecursionDecreasing(arr, n - 1);
    }

    public static void main(String[] args) {
        int[] array1 = {64, 34, 25, 12, 22, 11, 90};
        System.out.println("原始数组1: " + Arrays.toString(array1));
        sortingRecursionDecreasing(array1, array1.length); // 初始调用,对整个数组排序
        System.out.println("排序后数组1 (递减参数): " + Arrays.toString(array1));
    }
}

解析:

  • 递归基 (n == 1):当待排序子数组的长度 n 减至 1 时,表示只剩一个元素,它自然是有序的,此时递归终止。
  • 循环 (for (int i = 0; i :此循环执行一轮冒泡排序,遍历 arr[0] 到 arr[n-1] 范围内的元素,将最大元素交换到 arr[n-1] 位置。
  • 递归调用 (sortingRecursionDecreasing(arr, n - 1)):在完成一轮冒泡后,arr[n-1] 已是正确位置,因此下一轮递归只需要处理前 n-1 个元素。

另一种递归实现:参数递增法

除了递减参数的方法,我们也可以采用递增参数来追踪排序进度。在这种方法中,参数 n 可以表示已经有多少个元素被“固定”在数组的末尾(即已经排好序的元素数量)。

Tome
Tome

先进的AI智能PPT制作工具

下载

核心思想: 与递减参数法类似,每次递归调用同样执行一轮冒泡操作,将当前未排序部分的最大元素放置到正确位置。不同的是,我们通过递增 n 来表示已经有多少个元素排好序,从而动态调整内层循环的范围。

示例代码:

import java.util.Arrays;

public class RecursiveBubbleSort {

    /**
     * 另一种递归冒泡排序方法,通过递增参数n控制排序范围。
     * n表示已经有多少个元素被排序并固定在数组末尾。
     * @param arr 待排序数组
     * @param n 已经排序的元素数量(从数组末尾开始计数)
     */
    public static void bubbleRecursionIncreasing(int[] arr, int n) {
        // 递归基:当 n 等于数组长度时,表示所有元素都已排序,递归终止。
        // 或者,当 n 等于 arr.length - 1 时,意味着只剩一个元素未排序,它自然是有序的。
        // 当前实现中 n == arr.length 是一个稍微宽松的基准,意味着最后一次循环可能不执行任何操作。
        if (n == arr.length) {
            return;
        }

        // 执行一趟冒泡排序,将当前未排序部分(从 arr[0] 到 arr[arr.length-1-n])的最大元素移到 arr[arr.length-1-n]
        // 注意循环条件:arr.length - 1 - n 会随着 n 的增加而减小,从而缩小每次冒泡的范围。
        for (int i = 0; i < arr.length - 1 - n; i++) {
            if (arr[i] > arr[i + 1]) {
                // 交换元素
                int temp = arr[i];
                arr[i] = arr[i + 1];
                arr[i + 1] = temp;
            }
        }

        // 递归调用:增加 n,表示又有一个元素被排序到正确位置
        bubbleRecursionIncreasing(arr, n + 1);
    }

    public static void main(String[] args) {
        int[] array2 = {64, 34, 25, 12, 22, 11, 90};
        System.out.println("原始数组2: " + Arrays.toString(array2));
        bubbleRecursionIncreasing(array2, 0); // 初始时,0个元素已排序
        System.out.println("排序后数组2 (递增参数): " + Arrays.toString(array2));
    }
}

解析:

  • 递归基 (n == arr.length):当 n 增加到与数组总长度相等时,表示所有元素都已排序,递归终止。
  • 循环 (for (int i = 0; i :这里的 arr.length - 1 - n 是关键。它定义了当前一轮冒泡需要遍历的范围。随着 n 的增加,这个上限会减小,从而有效缩小了每次冒泡操作的范围,因为 n 个元素已经排好序并位于数组末尾,无需再参与比较。
  • 递归调用 (bubbleRecursionIncreasing(arr, n + 1)):每次递归调用后,n 递增,表示又有一个元素被放置到其最终位置。

递归参数与问题规模的理解

对于递归,一个常见的误解是认为“递归的输入参数必须越来越小”。然而,更准确的理解是:每次递归调用所处理的“问题规模”必须越来越小,最终才能收敛到递归基。

参数递增法中,虽然参数 n 的值在递增,但它控制的内层循环的上限 arr.length - 1 - n 却是在递减的。这意味着每次递归调用,实际需要处理的元素数量都在减少,即问题规模在有效缩小。例如,当 n=0 时,循环范围是 0 到 arr.length - 2;当 n=1 时,循环范围是 `

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
string转int
string转int

在编程中,我们经常会遇到需要将字符串(str)转换为整数(int)的情况。这可能是因为我们需要对字符串进行数值计算,或者需要将用户输入的字符串转换为整数进行处理。php中文网给大家带来了相关的教程以及文章,欢迎大家前来学习阅读。

463

2023.08.02

int占多少字节
int占多少字节

int占4个字节,意味着一个int变量可以存储范围在-2,147,483,648到2,147,483,647之间的整数值,在某些情况下也可能是2个字节或8个字节,int是一种常用的数据类型,用于表示整数,需要根据具体情况选择合适的数据类型,以确保程序的正确性和性能。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

544

2024.08.29

c++怎么把double转成int
c++怎么把double转成int

本专题整合了 c++ double相关教程,阅读专题下面的文章了解更多详细内容。

113

2025.08.29

C++中int的含义
C++中int的含义

本专题整合了C++中int相关内容,阅读专题下面的文章了解更多详细内容。

200

2025.08.29

length函数用法
length函数用法

length函数用于返回指定字符串的字符数或字节数。可以用于计算字符串的长度,以便在查询和处理字符串数据时进行操作和判断。 需要注意的是length函数计算的是字符串的字符数,而不是字节数。对于多字节字符集,一个字符可能由多个字节组成。因此,length函数在计算字符串长度时会将多字节字符作为一个字符来计算。更多关于length函数的用法,大家可以阅读本专题下面的文章。

928

2023.09.19

页面置换算法
页面置换算法

页面置换算法是操作系统中用来决定在内存中哪些页面应该被换出以便为新的页面提供空间的算法。本专题为大家提供页面置换算法的相关文章,大家可以免费体验。

412

2023.08.14

C++ 设计模式与软件架构
C++ 设计模式与软件架构

本专题深入讲解 C++ 中的常见设计模式与架构优化,包括单例模式、工厂模式、观察者模式、策略模式、命令模式等,结合实际案例展示如何在 C++ 项目中应用这些模式提升代码可维护性与扩展性。通过案例分析,帮助开发者掌握 如何运用设计模式构建高质量的软件架构,提升系统的灵活性与可扩展性。

8

2026.01.30

c++ 字符串格式化
c++ 字符串格式化

本专题整合了c++字符串格式化用法、输出技巧、实践等等内容,阅读专题下面的文章了解更多详细内容。

9

2026.01.30

java 字符串格式化
java 字符串格式化

本专题整合了java如何进行字符串格式化相关教程、使用解析、方法详解等等内容。阅读专题下面的文章了解更多详细教程。

8

2026.01.30

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
Kotlin 教程
Kotlin 教程

共23课时 | 3万人学习

C# 教程
C# 教程

共94课时 | 8万人学习

Java 教程
Java 教程

共578课时 | 53.5万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号