【数据结构排序算法篇】----冒泡排序【实战演练】

简介: 【数据结构排序算法篇】----冒泡排序【实战演练】

作为一名对技术充满热情的学习者,我一直以来都深刻地体会到知识的广度和深度。在这个不断演变的数字时代,我远非专家,而是一位不断追求进步的旅行者。通过这篇博客,我想分享我在某个领域的学习经验,与大家共同探讨、共同成长。请大家以开放的心态阅读,相信你们也会在这段知识之旅中找到启示。



前言

冒泡排序顾名思义,想泡泡一样慢慢冒上去,今天,我们就来深刻理解冒泡排序的排序步骤,通过一些联系给大家讲解如何解决有关冒泡排序算法的一些问题。


一、什么是冒泡排序

冒泡排序(Bubble Sort)是一种基础的排序算法。它的工作原理是通过重复地遍历要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。遍历数列的工作是重复进行的,直到没有再需要交换的元素为止,这时数列就完全排序好了。

  • 冒泡排序的名称来自于较小的元素会像“气泡”一样逐渐通过交换“浮”到数列的顶端,而较大的元素则沉到底部。

这里有一个简单的冒泡排序算法的例子:

假设我们有一个数组 arr[5] = {5, 2, 9, 1, 5},我们要对它进行升序排序

冒泡排序的具体步骤如下:

1.从数组的第一个元素开始,比较相邻元素的值。

2.如果前一个元素比后一个元素大(针对升序排序),交换它们的位置。

3.对数组的每一对相邻元素重复步骤1和2,直到数组的最后一个元素,这时最大的数就“冒泡”到了数组的最后位置。

4.因为最大的数已经在正确的位置了,所以可以忽略它,对数组的剩余部分重复步骤1到3的过程。

重复上述过程,每次遍历时忽略已确定位置的元素,直到没有任何一对数字需要交换,排序就完成了。

以下是对上述数组进行冒泡排序的过程:

初始数组: [5, 2, 9, 1, 5]

  • 第一趟冒泡:[2, 5, 1, 5, 9](最大的数9已到达最终位置)
  • 第二趟冒泡:[2, 1, 5, 5, 9](较大数5进行了移动)
  • 第三趟冒泡:[1, 2, 5, 5, 9](较小的数1移到了开头)
  • 第四趟冒泡:[1, 2, 5, 5, 9](数列已经排序完成,没有任何交换)

虽然冒泡排序在理解和实现上非常简单,但它通常不适合大规模数据的排序,因为其平均情况和最坏情况的时间复杂度都是O(n^2),其中n是数组的大小。因此,在需要高效排序的应用中,通常会采用更高效的算法,如快速排序、归并排序或堆排序

二、实战练习

现在我们对下面的数组冒泡排序:

arr = [64, 34, 25, 12, 22, 11, 90]

下面是详细步骤,希望同学们可以先自己练习:

初始数组状态:

[64, 34, 25, 12, 22, 11, 90]
  • 第1趟冒泡:
(64, 34) 比较,需要交换 -> [34, 64, 25, 12, 22, 11, 90]
(64, 25) 比较,需要交换 -> [34, 25, 64, 12, 22, 11, 90]
(64, 12) 比较,需要交换 -> [34, 25, 12, 64, 22, 11, 90]
(64, 22) 比较,需要交换 -> [34, 25, 12, 22, 64, 11, 90]
(64, 11) 比较,需要交换 -> [34, 25, 12, 22, 11, 64, 90]
(64, 90) 比较,不需交换 -> [34, 25, 12, 22, 11, 64, 90]
  • 第2趟冒泡:
(34, 25) 比较,需要交换 -> [25, 34, 12, 22, 11, 64, 90]
(34, 12) 比较,需要交换 -> [25, 12, 34, 22, 11, 64, 90]
(34, 22) 比较,需要交换 -> [25, 12, 22, 34, 11, 64, 90]
(34, 11) 比较,需要交换 -> [25, 12, 22, 11, 34, 64, 90]
(34, 64) 比较,不需交换 -> [25, 12, 22, 11, 34, 64, 90]
(64, 90) 比较,不需交换 -> [25, 12, 22, 11, 34, 64, 90]
  • 第3趟冒泡:
(25, 12) 比较,需要交换 -> [12, 25, 22, 11, 34, 64, 90]
(25, 22) 比较,需要交换 -> [12, 22, 25, 11, 34, 64, 90]
(25, 11) 比较,需要交换 -> [12, 22, 11, 25, 34, 64, 90]
(25, 34) 比较,不需交换 -> [12, 22, 11, 25, 34, 64, 90]
(34, 64) 比较,不需交换 -> [12, 22, 11, 25, 34, 64, 90]
(64, 90) 比较,不需交换 -> [12, 22, 11, 25, 34, 64, 90]
  • 第4趟冒泡:
(12, 22) 比较,不需交换 -> [12, 22, 11, 25, 34, 64, 90]
(22, 11) 比较,需要交换 -> [12, 11, 22, 25, 34, 64, 90]
(22, 25) 比较,不需交换 -> [12, 11, 22, 25, 34, 64, 90]
(25, 34) 比较,不需交换 -> [12, 11, 22, 25, 34, 64, 90]
(34, 64) 比较,不需交换 -> [12, 11, 22, 25, 34, 64, 90]
(64, 90) 比较,不需交换 -> [12, 11, 22, 25, 34, 64, 90]
  • 第5趟冒泡:
(12, 11) 比较,需要交换 -> [11, 12, 22, 25, 34, 64, 90]
(12, 22) 比较,不需交换 -> [11, 12, 22, 25, 34, 64, 90]
(22, 25) 比较,不需交换 -> [11, 12, 22, 25, 34, 64, 90]
(25, 34) 比较,不需交换 -> [11, 12, 22, 25, 34, 64, 90]
(34, 64) 比较,不需交换 -> [11, 12, 22, 25, 34, 64, 90]
(64, 90) 比较,不需交换 -> [11, 12, 22, 25, 34, 64, 90]

此时,数组已经排序完成,没有发生任何交换。排序过程到此结束。

最终排序好的数组为:

[11, 12, 22, 25, 34, 64, 90]

这个例子通过每一趟冒泡的详细步骤,展示了冒泡排序如何一步一步将无序数组变为有序。同学们可以检查一下自己做的有没有问题。

三、时间空间复杂度

  • 冒泡排序的时间复杂度取决于数组的初始排序状态以及数组中元素的数量。
  • 最坏情况时间复杂度(Worst-case time complexity):是O(n^2),这发生在数组完全反序时,每次比较都需要进行交换。
  • 平均时间复杂度(Average time complexity):也是O(n^2),因为平均情况下,列表可能是随机排序的,所以排序仍然可能要进行大量的比较和交换。
  • 最佳情况时间复杂度(Best-case time complexity):是O(n),这发生在数组已经是完全排序的状态。冒泡排序可以通过增加一个标志位来检测某次遍历中是否发生了交换;如果没有发生交换,表示数组已经有序,直接结束排序过程。
  • 冒泡排序的空间复杂度是O(1),也就是说,它在进行排序时只需要常数级别的额外空间。这个额外空间通常用于存储临时变量,用于在交换过程中暂时存储一个元素的值。

由于冒泡排序是在原地进行比较和交换的,没有需要额外存储结构,所以其额外的内存需求并不随着排序的元素数量增加,因此被视为常量空间复杂度。在实际实现时,不管你要排序多少数据,所需的额外空间都保持不变。这就是为什么冒泡排序被认为是一种空间复杂度很低的排序算法。

四、冒泡排序优缺点

冒泡排序的优缺点如下:

  • 优点:
    1.简单易懂:冒泡排序的算法非常直观和容易实现,对于理解排序算法的基本概念很有帮助。
    2.原地排序:冒泡排序是一种原地排序算法,不需要额外的存储空间,空间复杂度为O(1)。
    3.稳定排序:在排序过程中不会改变相同元素的初始相对顺序,因此是稳定的排序算法。
    4.检测到有序:冒泡排序可以提前停止,在数组已经排序的情况下效率较高,因为它可以在没有必要的时候提前结束,
  • 缺点:
    1.低效率:冒泡排序在最坏情况和平均情况下的时间复杂度都是O(n^2),这使得在处理大量数据时效率十分低下。
    2.过多的交换操作:冒泡排序可能涉及许多不必要的交换操作,尤其是在数组初始状态近乎有序的情况下。

实际应用中的注意事项:

  • 数据规模:由于其较高的时间复杂度,在数据量较大时不推荐使用冒泡排序。
  • 实用性:对于小型数据集或教学演示来说,冒泡排序是很合适的,但在实际应用中通常会选择更有效的排序算法。
  • 算法优化:可以通过设置一个标志位来标记某一趟排序过程中是否有数据交换,如果没有则提前终止排序,可以提升一定的效率。

如何适当使用冒泡排序:

  • 当数据量小且不要求高性能的时候,可以使用冒泡排序。
  • 在不关心算法效率,而是要演示排序过程时,使用冒泡排序是一个不错的选择,因为它的原理清晰易懂。
  • 如果需要一个不占用额外内存空间的排序算法,冒泡排序是一个选项。
  • 如果数据几乎已经排好序,冒泡排序可能会比其他O(n^2)时间复杂度的排序算法表现得更好,因为可以提前终止。

总体来说,冒泡排序由于算法效率较低,在实用的软件开发中较少使用,更多的是作为入门级别理解排序算法的工具,或者在数据量不大时简单使用。

五、经典面试题

面试题:“在不使用额外的数组或集合类的情况下,用Java写一个程序来移除一个有序整数数组中的重复元素,并返回新数组的长度。要求空间复杂度为O(1)。”

这个面试题要求面试者在原地进行操作,需要对数组进行修改,同时不增加额外的存储空间,以下是完成这个任务的一种方法。

面试回答(包括代码解释):

public class RemoveDuplicatesFromSortedArray {
    // 函数用来移除有序数组中的重复元素
    public static int removeDuplicates(int[] nums) {
        // 如果数组为空或只有一个元素,则不存在重复项需要移除
        if (nums.length == 0 || nums.length == 1) {
            return nums.length;
        }
        
        // 指针i表示不重复部分的最后一个位置
        int i = 0;
        // 遍历数组
        for (int j = 1; j < nums.length; j++) {
            // 如果相邻的元素不相等,则将j指向的元素复制到i+1的位置
            if (nums[j] != nums[i]) {
                i++;
                nums[i] = nums[j];
            }
            // 如果相邻元素相等,则j继续前移,直到找到下一个不同的元素
        }
        // 返回新的数组长度,因为i是索引值,真正的长度应该是i+1
        return i + 1;
    }
    // 主函数用来测试上面的函数
    public static void main(String[] args) {
        // 示例数组
        int[] sortedArray = {1, 1, 2, 2, 3, 4, 4, 5, 5, 5};
        // 移除重复元素
        int newLength = removeDuplicates(sortedArray);
        // 打印新数组长度和新数组内容
        System.out.println("New length: " + newLength);
        for (int i = 0; i < newLength; i++) {
            System.out.print(sortedArray[i] + " ");
        }
    }
}

在这段代码中:

  1. 我们有一个removeDuplicates函数,该函数接收一个有序整数数组作为参数。
  2. 我们检查数组的长度,快速返回空或单元素数组的情况。
  3. 我们使用两个指针iji表示无重复部分的末尾,而j用于遍历数组。
  4. 如果nums[j]nums[i]不同,这意味着我们发现了一个新的独特元素。因此,我们递增i指针,然后将nums[j]的值复制到nums[i],这样在前i+1个元素中就没有重复项。
  5. 最后,函数返回无重复元素的新长度,这是i+1,因为数组索引是从0开始的。

主函数中,我们创建了一个示例数组,并使用removeDuplicates函数来移除重复项并打印新数组的长度和元素。这个问题非常实用,因为它处理了原地数组修改,这是在进行内存优化时常常必需的。这个方法是对双指针技术的一个很好的展示,也显示了如何在不增加额外空间的情况下有效地解决问题。


总结

以上是对冒泡排序算法总结,整体看来,冒泡排序还是比较简单的,学起来也比较容易,希望同学们可以多加练习。后面我将依次给大家介绍排序算法,不论是初学者,还是考研,准备面试的同学都可可以来看看。能力有限,希望可以给大家带来帮助。

感谢大家抽出宝贵的时间来阅读博主的博客,新人博主,感谢大家关注点赞,祝大家未来的学习工作生活一帆风顺,加油!!!

目录
相关文章
|
6天前
|
大数据 UED 开发者
实战演练:利用Python的Trie树优化搜索算法,性能飙升不是梦!
在数据密集型应用中,高效搜索算法至关重要。Trie树(前缀树/字典树)通过优化字符串处理和搜索效率成为理想选择。本文通过Python实战演示Trie树构建与应用,显著提升搜索性能。Trie树利用公共前缀减少查询时间,支持快速插入、删除和搜索。以下为简单示例代码,展示如何构建及使用Trie树进行搜索与前缀匹配,适用于自动补全、拼写检查等场景,助力提升应用性能与用户体验。
21 2
|
11天前
|
算法 搜索推荐 开发者
别再让复杂度拖你后腿!Python 算法设计与分析实战,教你如何精准评估与优化!
在 Python 编程中,算法的性能至关重要。本文将带您深入了解算法复杂度的概念,包括时间复杂度和空间复杂度。通过具体的例子,如冒泡排序算法 (`O(n^2)` 时间复杂度,`O(1)` 空间复杂度),我们将展示如何评估算法的性能。同时,我们还会介绍如何优化算法,例如使用 Python 的内置函数 `max` 来提高查找最大值的效率,或利用哈希表将查找时间从 `O(n)` 降至 `O(1)`。此外,还将介绍使用 `timeit` 模块等工具来评估算法性能的方法。通过不断实践,您将能更高效地优化 Python 程序。
27 4
|
22天前
|
存储 人工智能 C语言
数据结构基础详解(C语言): 栈的括号匹配(实战)与栈的表达式求值&&特殊矩阵的压缩存储
本文首先介绍了栈的应用之一——括号匹配,利用栈的特性实现左右括号的匹配检测。接着详细描述了南京理工大学的一道编程题,要求判断输入字符串中的括号是否正确匹配,并给出了完整的代码示例。此外,还探讨了栈在表达式求值中的应用,包括中缀、后缀和前缀表达式的转换与计算方法。最后,文章介绍了矩阵的压缩存储技术,涵盖对称矩阵、三角矩阵及稀疏矩阵的不同压缩存储策略,提高存储效率。
|
2月前
|
算法 安全 数据安全/隐私保护
Android经典实战之常见的移动端加密算法和用kotlin进行AES-256加密和解密
本文介绍了移动端开发中常用的数据加密算法,包括对称加密(如 AES 和 DES)、非对称加密(如 RSA)、散列算法(如 SHA-256 和 MD5)及消息认证码(如 HMAC)。重点讲解了如何使用 Kotlin 实现 AES-256 的加密和解密,并提供了详细的代码示例。通过生成密钥、加密和解密数据等步骤,展示了如何在 Kotlin 项目中实现数据的安全加密。
58 1
|
2月前
|
机器学习/深度学习 存储 算法
强化学习实战:基于 PyTorch 的环境搭建与算法实现
【8月更文第29天】强化学习是机器学习的一个重要分支,它让智能体通过与环境交互来学习策略,以最大化长期奖励。本文将介绍如何使用PyTorch实现两种经典的强化学习算法——Deep Q-Network (DQN) 和 Actor-Critic Algorithm with Asynchronous Advantage (A3C)。我们将从环境搭建开始,逐步实现算法的核心部分,并给出完整的代码示例。
87 1
|
2月前
|
算法 安全 数据安全/隐私保护
Android经典实战之常见的移动端加密算法和用kotlin进行AES-256加密和解密
本文介绍了移动端开发中常用的数据加密算法,包括对称加密(如 AES 和 DES)、非对称加密(如 RSA)、散列算法(如 SHA-256 和 MD5)及消息认证码(如 HMAC)。重点展示了如何使用 Kotlin 实现 AES-256 的加密和解密,提供了详细的代码示例。
39 2
|
2月前
|
机器学习/深度学习 算法 数据挖掘
【白话机器学习】算法理论+实战之决策树
【白话机器学习】算法理论+实战之决策树
|
2月前
|
算法 搜索推荐 Java
算法实战:手写归并排序,让复杂排序变简单!
归并排序是一种基于“分治法”的经典算法,通过递归分割和合并数组,实现O(n log n)的高效排序。本文将通过Java手写代码,详细讲解归并排序的原理及实现,帮助你快速掌握这一实用算法。
38 0
|
2月前
|
存储 算法 Java
"解锁Java对象数据结构的奥秘:从基础到实战,与热点技术共舞,让你的编程之路更激情四溢!"
【8月更文挑战第21天】Java以对象为核心,它是程序的基本单元与数据处理的基础。对象源自类,拥有属性(字段)和方法。对象在内存中分为对象头(含哈希码、GC信息等)和实例数据区(存储属性值)。例如,`Student`类定义了姓名、年龄等属性及相应的方法。通过`new`关键字实例化对象并调用其方法进行数据操作,是Java编程的关键技能。
29 0
|
2月前
|
数据采集 搜索推荐 算法
【高手进阶】Java排序算法:从零到精通——揭秘冒泡、快速、归并排序的原理与实战应用,让你的代码效率飙升!
【8月更文挑战第21天】Java排序算法是编程基础的重要部分,在算法设计与分析及实际开发中不可或缺。本文介绍内部排序算法,包括简单的冒泡排序及其逐步优化至高效的快速排序和稳定的归并排序,并提供了每种算法的Java实现示例。此外,还探讨了排序算法在电子商务、搜索引擎和数据分析等领域的广泛应用,帮助读者更好地理解和应用这些算法。
24 0
下一篇
无影云桌面