【算法系列 | 1】深入解析排序算法之—冒泡排序

序言

心若有阳光,你便会看见这个世界有那么多美好值得期待和向往。

决定开一个算法专栏,希望能帮助大家很好的了解算法。主要深入解析每个算法,从概念到示例。

我们一起努力,成为更好的自己!

今天第1讲,讲一下排序算法的---冒泡排序算法

一、算法介绍

冒泡排序(Bubble Sort)是一种简单的排序算法,它重复地遍历要排序的列表,一次比较两个元素,并且如果它们的顺序错误就交换它们。遍历的过程持续多次,每一轮都会将未排序部分的最大元素浮动到最右侧。这个过程像气泡一样逐步上浮,因此得名"冒泡排序"。

1.1 原理介绍

冒泡排序算法通过多次遍历未排序部分,比较并交换相邻元素,将最大值逐步移动至右侧,实现对整个列表的排序。

下面是冒泡排序的基本步骤:

  1. 比较相邻元素: 从列表的第一个元素开始,依次比较相邻的两个元素,如果它们的顺序是错误的(比如,前面的元素大于后面的元素),则交换它们。

  2. 一轮遍历: 重复第一步,直到整个列表都被遍历一次。在这一轮的遍历过程中,最大的元素就像气泡一样浮到了最右侧。

  3. 重复: 重复以上两个步骤,每一轮都会把未排序部分的最大元素浮动到正确的位置。未排序部分逐渐减小,直到整个列表排序完成。

这个过程可以形象地理解为气泡上浮的过程,因为每一轮排序都会使一个最大的元素"浮"到正确的位置。

下面通过一个简单的示意图来图解冒泡排序算法的过程:

考虑要排序的列表:[5, 3, 8, 4, 2]

初始状态:

csharp 复制代码
[5, 3, 8, 4, 2]

第一轮遍历:

比较并交换相邻元素,将最大值冒泡到右侧:

csharp 复制代码
[3, 5, 4, 2, 8]

第二轮遍历:

继续比较并交换相邻元素:

csharp 复制代码
[3, 4, 2, 5, 8]

第三轮遍历:

再次比较并交换:

csharp 复制代码
[3, 2, 4, 5, 8]

第四轮遍历:

最终得到排序后的列表:

csharp 复制代码
[2, 3, 4, 5, 8]

这个过程就好像气泡逐渐上浮的过程一样,最大的元素被依次交换到正确的位置,最终实现整个列表的升序排序。

1.2 优缺点

优点:

  1. 简单易懂: 冒泡排序的实现非常简单,易于理解和实现,适合初学者学习排序算法的入门。

  2. 空间复杂度低: 冒泡排序是一种原地排序算法,不需要额外的存储空间,只需要少量辅助变量,因此空间复杂度较低。

缺点:

  1. 性能较差: 冒泡排序的时间复杂度为O(n^2),其中n是待排序元素的数量。这使得它在处理大型数据集时效率较低,不适合大规模数据排序。

  2. 不稳定性: 在相邻元素相等时,冒泡排序可能会交换它们的位置,导致相同元素的相对位置发生改变,因此它是一种不稳定的排序算法。

  3. 适用场景受限: 冒泡排序适用于少量元素的情况,对于大规模数据集,更高效的排序算法如快速排序、归并排序等更为适用。

  4. 比较次数较多: 冒泡排序每一轮都要比较相邻元素的大小,并可能进行交换,导致比较次数较多,尤其是在已经有序的情况下,仍然需要进行多轮比较。

1.3 复杂度

时间复杂度:

  1. 冒泡排序的时间复杂度取决于元素的数量和列表的初始顺序。在最坏情况下,冒泡排序需要进行n×(n−1)/2 次比较和交换操作,其中n是待排序元素的数量。因此,冒泡排序的最坏时间复杂度是O(n2)。

  2. 在最好的情况下,如果列表已经是有序的,冒泡排序只需要进行一轮遍历,进行n−1 次比较,但没有交换操作。此时的最好时间复杂度是O(n)。然而,由于冒泡排序每轮都要进行比较,即使在最好情况下,它的比较次数也较多。

  3. 平均情况下,冒泡排序的时间复杂度仍然是O(n2)。这使得冒泡排序在处理大规模数据时性能较差,不如一些更为高效的排序算法。

空间复杂度:

冒泡排序是一种原地排序算法,它不需要额外的存储空间,只需要少量辅助变量。因此,冒泡排序的空间复杂度是O(1)。

1.4 使用场景

以下是一些冒泡排序适用的场景:

  1. 小规模数据: 冒泡排序适用于小规模数据集的排序。在数据量较小时,冒泡排序的简单实现可能比更复杂的排序算法更容易理解和实现。

  2. 教学和学习: 由于其简单直观的原理,冒泡排序常常用于教学和学习排序算法。它为学习者提供了一个入门级别的算法,用于理解排序的基本概念。

  3. 已基本有序的数据: 如果输入数据已经基本有序,冒泡排序的性能可能比较好。因为冒泡排序每次只会比较相邻元素,若列表已经接近有序状态,则只需要少量的遍历就能完成排序。

  4. 适用于部分排序: 如果只需要对列表的一部分元素进行排序,而不是整个列表,冒泡排序可能比其他算法更具竞争力。它可以提前终止,一旦发现列表已经有序,就无需进行额外的比较和交换。

二、代码实现

2.1 Java代码实现

2.1.1 代码示例

ini 复制代码
public class BubbleSort {

    // 冒泡排序函数
    public static void bubbleSort(int[] array) {
        int n = array.length;

        // 外层循环控制轮数,每一轮都会将一个最大元素冒泡到最右侧
        for (int i = 0; i < n - 1; i++) {
            
            // 内层循环负责相邻元素的比较和交换
            // 注意内层循环每轮都会将一个未排序部分的最大元素浮动到最右侧
            for (int j = 0; j < n - i - 1; j++) {
                
                // 比较相邻元素,如果顺序错误则交换
                if (array[j] > array[j + 1]) {
                    // 交换array[j]和array[j + 1]
                    int temp = array[j];
                    array[j] = array[j + 1];
                    array[j + 1] = temp;
                }
            }
        }
    }

    public static void main(String[] args) {
        // 示例数组
        int[] arr = {64, 34, 25, 12, 22, 11, 90};

        System.out.println("原始数组:");
        printArray(arr);

        // 调用冒泡排序算法
        bubbleSort(arr);

        System.out.println("\n排序后的数组:");
        printArray(arr);
    }

    // 辅助函数,用于打印数组
    public static void printArray(int[] array) {
        int n = array.length;
        for (int i = 0; i < n; ++i) {
            System.out.print(array[i] + " ");
        }
        System.out.println();
    }
}

2.1.2 代码详解

  1. bubbleSort 函数实现了冒泡排序算法,其中外层循环控制排序的轮数,内层循环负责相邻元素的比较和交换。

  2. main 函数中创建了一个示例数组,调用了 bubbleSort 进行排序,然后打印排序前和排序后的数组。

  3. printArray 函数用于打印数组内容,方便观察算法执行结果。

这个代码示例展示了冒泡排序的基本实现,可以通过调用 bubbleSort 函数对需要排序的数组进行排序。

2.1.3 运行结果

2.2 Python代码实现

2.2.1 代码示例

python 复制代码
def bubble_sort(arr):
    """
    冒泡排序算法实现

    Parameters:
    - arr: 待排序的数组

    Returns:
    - None(原地排序,直接修改输入数组)
    """
    n = len(arr)

    # 外层循环控制轮数,每一轮都会将一个最大元素冒泡到最右侧
    for i in range(n - 1):
        
        # 内层循环负责相邻元素的比较和交换
        # 注意内层循环每轮都会将一个未排序部分的最大元素浮动到最右侧
        for j in range(n - i - 1):
            
            # 比较相邻元素,如果顺序错误则交换
            if arr[j] > arr[j + 1]:
                # 交换arr[j]和arr[j + 1]
                arr[j], arr[j + 1] = arr[j + 1], arr[j]


# 示例数组
arr = [64, 34, 25, 12, 22, 11, 90]

print("原始数组:")
print(arr)

# 调用冒泡排序算法
bubble_sort(arr)

print("\n排序后的数组:")
print(arr)

2.2.2 代码详解

代码中有以下几个关键点:

  1. bubble_sort 函数实现了冒泡排序算法,其中外层循环控制排序的轮数,内层循环负责相邻元素的比较和交换。

  2. 示例数组 arr 包含了需要排序的数据。

  3. 调用 bubble_sort 函数对示例数组进行排序。

  4. 打印排序前和排序后的数组,观察算法执行结果。

这个Python代码示例展示了冒泡排序的基本实现,通过调用 bubble_sort 函数可以对需要排序的数组进行排序。

2.2.3 运行结果

好啦,今天就到这里啦,下期见喽~~🙉

相关推荐
import_random36 分钟前
[macos]rocketmq(安装)
后端
程序员小假1 小时前
你会不会使用 SpringBoot 整合 Flowable 快速实现工作流呢?
java·后端
明月与玄武1 小时前
快速掌握Django框架设计思想(图解版)
后端·python·django
陪我一起学编程1 小时前
关于ORM增删改查的总结——跨表
数据库·后端·python·django·restful
南囝coding2 小时前
这个 361K Star 的项目,一定要收藏!
前端·后端·github
虎鲸不是鱼2 小时前
Spring Boot3流式访问Dify聊天助手接口
java·spring boot·后端·大模型·llm
onlooker66662 小时前
Go语言底层(五): 深入浅出Go语言的ants协程池
开发语言·后端·golang
武子康2 小时前
Java-46 深入浅出 Tomcat 核心架构 Catalina 容器全解析 启动流程 线程机制
java·开发语言·spring boot·后端·spring·架构·tomcat
寻月隐君3 小时前
Solana 开发实战:Rust 客户端调用链上程序全流程
后端·rust·web3
丘山子3 小时前
别再滥用 None 了!这才是 Python 处理缺失值的好方法
后端·python·面试