三傻排序的比较(选择,冒泡,插入)

embedded/2025/2/5 3:43:34/

在学习排序算法时,选择排序、冒泡排序和插入排序是最常见的基础排序算法。但是,尽管这些算法看起来非常相似,它们在实际应用中的效率和性能却有所不同。本文将详细比较这三种排序算法的时间复杂度、空间复杂度。

比较总结

排序算法时间复杂度(最坏/平均/最好)空间复杂度稳定性总结
选择排序O(n^2) / O(n^2) / O(n^2)O(1)不稳定选择排序就像每次去找最小的苹果,把它拿过来放到最前面。比较次数多,但并不保证相同值的苹果顺序不变。
冒泡排序O(n^2) / O(n^2) / O(n)O(1)稳定冒泡排序就像水中泡泡,每次拿两个相邻的元素交换位置,把最大的“泡泡”挤到最后面。对已经排序的部分有点帮助。
插入排序O(n^2) / O(n^2) / O(n)O(1)稳定插入排序像扑克牌,每次从剩下的牌中选一张,插入到已经排好序的部分。只要原本部分已经排得差不多,插入排序就很快。
解释:
  • 选择排序:就像在一堆乱七八糟的苹果里,每次都找最小的一个放到最前面,直到找完所有苹果。这样做效率低,因为每次都要扫描整个数组。并且,交换位置时会改变相同数值元素的顺序,所以它是不稳定的。

  • 冒泡排序:它的工作方式像水中的气泡,每次把最小(或者最大)的一泡气泡“冒泡”到水面。这样做最差的情况就像是给每个气泡都挤出来一次,效率比较差。不过,如果数据本来就已经有点有序了,冒泡排序会比选择排序好,因为它可以提前结束。冒泡排序是稳定的,也就是说,相同的数值会保持原来的顺序。

  • 插入排序:插入排序就像你在玩扑克牌,已经排好的一部分牌,就像一个顺序的队列,后面的牌从后面插进这个顺序队列。如果已经排得差不多了,那么插入排序就能非常快速地完成任务,效率提升很多。它也是稳定的,意思是相同的数字不会改变顺序。

总结:
  • 选择排序:非常简单,但因为每次都要比较整个数组,所以它的效率较差,尤其是大数据时。它是不稳定的,不适合用在需要保留相等元素顺序的场景。
  • 冒泡排序:虽然每次“冒泡”都能把大的数挤到最后,但它效率也不高,尤其是需要进行多轮比较时。它是稳定的,如果数据部分有序,它比选择排序要好一些。
  • 插入排序:适合数据已经有序或者部分有序的情况,可以非常高效。它也是稳定的,是一个非常实用的排序算法,尤其是数据量不大时。

分别分析:

1. 选择排序(Selection Sort)

选择排序是一种简单的排序算法,它的基本思想是:

  • 每次从待排序的数组中选择最小的元素,然后将其与未排序部分的第一个元素交换。
  • 重复这个过程,直到所有元素都被排序。
选择排序的工作原理:
  1. 找到数组中最小的元素。
  2. 将其与数组的第一个元素交换。
  3. 然后对剩下的元素继续执行相同操作,直到整个数组有序。

选择排序的Java代码实现:

java">public class SelectionSort {public static void selectionSort(int[] arr) {int n = arr.length;// 遍历数组for (int i = 0; i < n - 1; i++) {// 假设当前元素是最小的int minIndex = i;// 查找剩余部分的最小元素for (int j = i + 1; j < n; j++) {if (arr[j] < arr[minIndex]) {minIndex = j;}}// 交换最小元素与当前位置的元素int temp = arr[i];arr[i] = arr[minIndex];arr[minIndex] = temp;}}public static void printArray(int[] arr) {for (int num : arr) {System.out.print(num + " ");}System.out.println();}public static void main(String[] args) {int[] arr = {64, 25, 12, 22, 11};System.out.println("Original Array:");printArray(arr);selectionSort(arr);System.out.println("Sorted Array:");printArray(arr);}
}
选择排序的时间和空间复杂度:
  • 时间复杂度:O(n^2),在每次选择最小值时需要遍历剩余部分,因此时间复杂度为 O(n^2)。
  • 空间复杂度:O(1),选择排序是原地排序算法,仅使用常数级别的额外空间。

2. 冒泡排序(Bubble Sort)

冒泡排序的基本思想是:

  • 通过多次比较相邻的元素,若顺序错误则交换它们。
  • 每一轮遍历将当前未排序部分中的最大元素“冒泡”到数组的末尾。
  • 重复这个过程,直到整个数组有序。
冒泡排序的工作原理:
  1. 从数组的第一个元素开始,比较相邻的两个元素,如果顺序错误就交换它们。
  2. 每一轮遍历后,最大的元素被交换到末尾。
  3. 重复遍历,直到所有元素都已排序。

冒泡排序的Java代码实现:

java">public class BubbleSort {public static void bubbleSort(int[] arr) {int n = arr.length;// 外层循环,控制比较的轮数for (int i = 0; i < n - 1; i++) {// 内层循环,进行相邻元素的比较和交换for (int j = 0; j < n - 1 - i; j++) {if (arr[j] > arr[j + 1]) {// 交换相邻元素int temp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = temp;}}}}public static void printArray(int[] arr) {for (int num : arr) {System.out.print(num + " ");}System.out.println();}public static void main(String[] args) {int[] arr = {64, 25, 12, 22, 11};System.out.println("Original Array:");printArray(arr);bubbleSort(arr);System.out.println("Sorted Array:");printArray(arr);}
}
冒泡排序的时间和空间复杂度:
  • 时间复杂度:O(n^2),在最坏和最常见的情况下,需要两层嵌套循环,因此时间复杂度是 O(n^2)。
  • 空间复杂度:O(1),冒泡排序是原地排序算法,不需要额外的存储空间。

3. 插入排序(Insertion Sort)

插入排序的基本思想是:

  • 从第二个元素开始,将每个元素插入到已经排好序的部分中。
  • 每次插入时,先与已经排序的元素进行比较,找到合适的位置插入。
插入排序的工作原理:
  1. 从数组的第二个元素开始,将其插入到前面已排序部分的合适位置。
  2. 每次插入时,从右向左移动元素,直到找到合适的位置。
  3. 重复这一过程,直到整个数组有序。
插入排序的Java代码实现:
java">public class InsertionSort {public static void insertionSort(int[] arr) {int n = arr.length;// 从第二个元素开始插入for (int i = 1; i < n; i++) {int key = arr[i];int j = i - 1;// 移动比key大的元素while (j >= 0 && arr[j] > key) {arr[j + 1] = arr[j];j = j - 1;}// 插入key元素arr[j + 1] = key;}}public static void printArray(int[] arr) {for (int num : arr) {System.out.print(num + " ");}System.out.println();}public static void main(String[] args) {int[] arr = {64, 25, 12, 22, 11};System.out.println("Original Array:");printArray(arr);insertionSort(arr);System.out.println("Sorted Array:");printArray(arr);}
}
插入排序的时间和空间复杂度:
  • 时间复杂度:O(n^2),在最坏情况下(当数组是倒序时),需要两层循环,因此时间复杂度为 O(n^2)。但在部分有序的数组中,插入排序的表现比选择排序和冒泡排序更优。
  • 空间复杂度:O(1),插入排序是原地排序算法,只需要常数级别的额外空间。

http://www.ppmy.cn/embedded/159647.html

相关文章

如何在5步内使用 Spring AI 和 OpenAI 的 DALL-E 3 生成图像

将 Spring AI 与 OpenAI 的 DALL-E 3 集成&#xff0c;以生成图像。轻松设置 Spring Boot、配置 API 集成并自定义设置。 大家好&#xff01;这是关于 Spring AI 系列介绍文章的第一篇。今天&#xff0c;我们将了解如何通过文本提示轻松生成图片。为此&#xff0c;我们将利用 …

Go优雅实现redis分布式锁

前言 系统为了保证高可用&#xff0c;通常会部署多实例&#xff0c;并且会存在同时对共享资源并发读写&#xff0c;这时候为了保证读写的安全&#xff0c;常规手段是会引入分布式锁&#xff0c;本文将介绍如何使用redis设计一个优雅的Go分布式锁。 设计 redis分布式锁是借助…

Golang —协程池(panjf2000/ants/v2)

Golang —协程池&#xff08;panjf2000/ants/v2&#xff09; 1 ants1.1 基本信息1.2 ants 是如何运行的&#xff08;流程图&#xff09; 1 ants 1.1 基本信息 代码地址&#xff1a;github.com/panjf2000/ants/v2 介绍&#xff1a;ants是一个高性能的 goroutine 池&#xff0c…

YOLOV11-1:YoloV11-安装和CLI方式训练模型

YoloV11-安装和CLI方式训练模型 1.安装和运行1.1安装的基础环境1.2安装yolo相关组件1.3命令行方式使用1.3.1 训练1.3.2 预测 本文介绍yoloV11的安装和命令行接口 1.安装和运行 1.1安装的基础环境 GPU环境&#xff0c;其中CUDA是12.4版本 1.2安装yolo相关组件 # 克隆github…

深度解析近期爆火的 DeepSeek

最近&#xff0c;AI 领域有个名字频繁出现在大众视野 ——DeepSeek&#xff0c;它的火爆程度就像一颗投入平静湖面的巨石&#xff0c;激起千层浪。今天&#xff0c;咱们就来深入了解一下这个 “AI 新星”。 官网&#xff1a;DeepSeek - 探索未至之境 DeepSeek 是什么 DeepSeek…

C++并发编程指南04

文章目录 共享数据的问题3.1.1 条件竞争双链表的例子条件竞争示例恶性条件竞争的特点 3.1.2 避免恶性条件竞争1. 使用互斥量保护共享数据结构2. 无锁编程3. 软件事务内存&#xff08;STM&#xff09; 总结互斥量与共享数据保护3.2.1 互斥量使用互斥量保护共享数据示例代码&…

JavaScript语言的面向对象编程

JavaScript语言的面向对象编程 引言 面向对象编程&#xff08;OOP&#xff09;是一种以对象为中心的程序设计思想&#xff0c;旨在通过将数据和操作数据的行为组合在一起&#xff0c;提高代码的可重用性、可维护性和可扩展性。而JavaScript作为一种强大的脚本语言&#xff0c…

go-zero学习笔记(二)

利用goctl生成api服务 编写api文件 //版本信息&#xff0c; import中的版本信息必须与被import的api版本信息一样 syntax"v1"// 支持引入其他api文件 // 这在多接口下非常有用 // 如果不可以引入&#xff0c;对于多接口情况&#xff0c;所有的接口写在同一个文件&…