Java数据结构和算法之冒泡,选择和插入排序算法

Java数据结构和算法之冒泡、选择和插入排序算法

冒泡排序算法

算法思路

冒泡排序是一种基础的排序算法,它通过比较相邻元素的大小并交换位置,将最大(或最小)的元素逐步“冒泡”到序列的最后,从而完成排序。

具体地,冒泡排序的过程如下:

  1. 从序列的第一个元素开始,依次比较相邻的两个元素,如果前面的元素大于后面的元素,则交换它们的位置。
  2. 继续依次比较相邻的元素,直到序列的倒数第二个元素为止。
  3. 重复执行步骤 1、2,直到序列全部排序完成。

示例说明

下面是一组示例数据:

int[] arr = {4, 2, 8, 3, 1};

使用冒泡排序算法对其进行排序,可得到如下过程:

// 第 1 轮
arr[0] 和 arr[1] 比较,arr[0] < arr[1],不交换位置
arr[1] 和 arr[2] 比较,arr[1] > arr[2],交换位置,arr 变成 {4, 8, 2, 3, 1}
arr[2] 和 arr[3] 比较,arr[2] < arr[3],不交换位置
arr[3] 和 arr[4] 比较,arr[3] > arr[4],交换位置,arr 变成 {4, 8, 2, 1, 3}

// 第 2 轮
arr[0] 和 arr[1] 比较,arr[0] < arr[1],不交换位置
arr[1] 和 arr[2] 比较,arr[1] < arr[2],不交换位置
arr[2] 和 arr[3] 比较,arr[2] > arr[3],交换位置,arr 变成 {4, 2, 1, 8, 3}
arr[3] 和 arr[4] 比较,arr[3] < arr[4],不交换位置

// 第 3 轮
arr[0] 和 arr[1] 比较,arr[0] > arr[1],交换位置,arr 变成 {2, 4, 1, 8, 3}
arr[1] 和 arr[2] 比较,arr[1] < arr[2],不交换位置
arr[2] 和 arr[3] 比较,arr[2] > arr[3],交换位置,arr 变成 {2, 1, 4, 8, 3}
arr[3] 和 arr[4] 比较,arr[3] > arr[4],交换位置,arr 变成 {2, 1, 4, 3, 8}

// 第 4 轮
arr[0] 和 arr[1] 比较,arr[0] > arr[1],交换位置,arr 变成 {1, 2, 4, 3, 8}
arr[1] 和 arr[2] 比较,arr[1] < arr[2],不交换位置
arr[2] 和 arr[3] 比较,arr[2] > arr[3],交换位置,arr 变成 {1, 2, 3, 4, 8}

// 第 5 轮
arr[0] 和 arr[1] 比较,arr[0] < arr[1],不交换位置
arr[1] 和 arr[2] 比较,arr[1] < arr[2],不交换位置
arr[2] 和 arr[3] 比较,arr[2] < arr[3],不交换位置
arr[3] 和 arr[4] 比较,arr[3] < arr[4],不交换位置

可见,经过 5 轮排序,序列被正确排序。在最坏情况下,即原序列为逆序排列时,冒泡排序算法的时间复杂度为 O(n^2)。

选择排序算法

算法思路

选择排序算法也是一种基础的排序算法,它通过和冒泡排序不同的思路进行排序。选择排序过程中,依次遍历整个序列,每次找到未排序部分中的最小值(或最大值),并将其放置在已排序部分的末尾。

具体地,选择排序的过程如下:

  1. 设置一个变量 minIndex,初始值和第一个未排序元素的下标相同。
  2. 依次遍历未排序部分的每个元素,将其与 minIndex 指向的元素进行比较,如果找到一个更小(或更大)的元素,则将 minIndex 更新为该元素的下标。
  3. 遍历到序列末尾后,将找到的最小值(或最大值)直接与未排序部分的第一个元素进行交换,从而将其放置在已排序部分的末尾。
  4. 重复执行步骤 2、3,直到整个序列全部排序完成。

示例说明

下面是一组示例数据:

int[] arr = {4, 2, 8, 3, 1};

使用选择排序算法对其进行排序,可得到如下过程:

// 第 1 轮
从 arr[0] 开始遍历,找到 arr[4] 最小,将 arr[0] 和 arr[4] 交换,arr 变成 {1, 2, 8, 3, 4}

// 第 2 轮
从 arr[1] 开始遍历,找到 arr[3] 最小,将 arr[1] 和 arr[3] 交换,arr 变成 {1, 2, 8, 3, 4}

// 第 3 轮
从 arr[2] 开始遍历,找到 arr[3] 最小,将 arr[2] 和 arr[3] 交换,arr 变成 {1, 2, 3, 8, 4}

// 第 4 轮
从 arr[3] 开始遍历,找到 arr[4] 最小,将 arr[3] 和 arr[4] 交换,arr 变成 {1, 2, 3, 4, 8}

// 第 5 轮
遍历完成,整个序列已全部排序完成。

可见,经过 5 轮排序,序列被正确排序。与冒泡排序算法相同,选择排序算法的时间复杂度也为 O(n^2)。

插入排序算法

算法思路

插入排序算法是一种较为高效的排序算法,尤其适用于对有序或基本有序的数据进行排序。插入排序算法的基本思路是将未排序部分中的元素逐个插入到已排序部分中相应的位置。

具体地,插入排序的过程如下:

  1. 将序列分为已排序部分和未排序部分,初始时已排序部分只包含第一个元素,未排序部分包含剩余所有元素。
  2. 遍历未排序部分的每个元素,将其依次插入到已排序部分中相应的位置。具体地,从序列的第二个元素开始,将其与已排序部分的元素依次比较,直到找到第一个比其大(或小)的元素,然后将该元素插入其前面,从而保证已排序部分仍然有序。
  3. 重复执行步骤 2,直到未排序部分全部加入已排序部分为止。

示例说明

下面是一组示例数据:

int[] arr = {4, 2, 8, 3, 1};

使用插入排序算法对其进行排序,可得到如下过程:

// 第 1 轮
已排序部分只包含 arr[0],未排序部分包含 arr[1] 到 arr[4]。取出 arr[1],将其与 arr[0] 比较,发现 arr[1] 较小,将其插入 arr[0] 前面,此时已排序部分为 {2, 4},未排序部分为 {8, 3, 1}。
取出 arr[2],将其依次与已排序部分的元素比较,发现它应该插入到 arr[1] 后面,此时已排序部分为 {2, 4, 8},未排序部分为 {3, 1}。
取出 arr[3],将其依次与已排序部分的元素比较,发现它应该插入到 arr[1] 前面,此时已排序部分为 {2, 3, 4, 8},未排序部分为 {1}。
取出 arr[4],将其依次与已排序部分的元素比较,发现它应该插入到 arr[0] 前面,此时已排序部分为 {1, 2, 3, 4, 8},未排序部分为空。

// 第 2 轮
整个序列已全部排序完成。

可见,经过 2 轮排序,序列被正确排序。相比冒泡排序和选择排序,插入排序的时间复杂度较低,最好情况下为 O(n),平均情况下为 O(n^2)。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:Java数据结构和算法之冒泡,选择和插入排序算法 - Python技术站

(0)
上一篇 2023年6月27日
下一篇 2023年6月27日

相关文章

  • Android使用android-wheel实现省市县三级联动

    Android使用android-wheel实现省市县三级联动攻略 1. 引入android-wheel库 首先,你需要在你的Android项目中引入android-wheel库。你可以通过在项目的build.gradle文件中添加以下依赖来实现: dependencies { implementation ‘com.github.lantouzi.whee…

    other 2023年9月6日
    00
  • 可以实现反复重启的批处理

    实现反复重启的批处理攻略 背景 在某些需要定时执行任务的环境下,我们有可能需要编写一个能够反复重启的批处理程序。这样做可以保证任务在出现异常情况时仍能及时重新运行,确保任务正常完成。 实现方法 我们可以使用简单的批处理脚本来实现该功能。以下是具体实现步骤: Step 1: 编写循环语句 首先,我们需要使用一个循环语句,例如for或者while,让程序可以反复…

    other 2023年6月27日
    00
  • clannad什么意思

    Clannad 是一款由 KEY 公司开发的视觉小说游戏,其中包含了许多关于家庭、友情和爱情的故事,整体情感非常温暖并能引人入胜。 在游戏中,主角冈崎朋也所在的学校里有许多少女角色,每个角色都有着自己的故事和人生经历,玩家需要通过选择正确的对话选项,以此获得不同角色的好感度并最终赢得她们的心。 下面给出两个示例,帮助玩家更好地理解 Clannad。 获得春原…

    其他 2023年4月16日
    00
  • SpringBoot整合RocketMQ的方法详解

    下面我将为您详细讲解“SpringBoot整合RocketMQ的方法详解”的完整攻略。 简介 首先,让我们来了解一下 SpringBoot 和 RocketMQ。SpringBoot 是一个快速开发的框架,通过提供开发者友好的接口,使开发者可以轻松地构建 Web 应用,并且可以集成多种开源框架。RocketMQ 是阿里巴巴开源的消息中间件,可以实现高可靠、高…

    other 2023年6月27日
    00
  • 详解C++作用域与生命周期

    详解C++作用域与生命周期 作用域是指程序中变量、函数、类等实体可被访问的范围,而生命周期则是指程序中变量、函数、类等实体存在的时长。C++中的作用域和生命周期是非常重要的概念,理解它们可以帮助我们更好地设计和编写程序。 变量的作用域和生命周期 在C++中,变量的作用域和生命周期是紧密关联的。变量的作用域指的是变量在程序中可见的范围,而变量的生命周期则是指变…

    other 2023年6月27日
    00
  • Java设计模式中的七大原则详细讲解

    Java设计模式中的七大原则详细讲解 1. 单一职责原则 单一职责原则(Single Responsibility Principle,SRP)指的是一个类或者模块只负责完成一个职责或功能。如果一个类职责过多可能导致其难以维护,因此需要将其拆分成多个类。 例如,我们有一个 User 类,其职责包括用户登录和注册,查看用户信息等。如果我们将用户登录和注册另外封…

    other 2023年6月27日
    00
  • c#chart控件教程

    C# Chart控件教程 介绍 C# Chart控件是.NET Framework中的一个可视化控件,可以用于绘制各种类型的图表,如折线图、柱状图、饼图等。在数据分析和可视化方面,Chart控件是一个非常强大的工具,使用它可以快速直观地展现数据结论。 本篇教程将为你带来Chart控件的基本使用方法,从创建控件到绘制图表,一步步指导你实现各种图表的绘制。 创建…

    其他 2023年3月28日
    00
  • Page.ClientScript.RegisterStartupScript

    下面是关于Page.ClientScript.RegisterStartupScript的完整攻略,包括基本概念、使用流程和两个示例等方面。 Page.ClientScript.RegisterStartupScript的基本概念 Page.ClientScript.RegisterStartupScript是ASP.NET Web Forms中的一个方法,…

    other 2023年5月6日
    00
合作推广
合作推广
分享本页
返回顶部