首页 > 编程语言 >【基础算法】排序算法

【基础算法】排序算法

时间:2023-10-04 17:22:06浏览次数:40  
标签:arr 复杂度 基础 算法 冒泡 有序 排序

一、排序算法简介

排序是对批量数据按照一定的顺序进行排列的操作。

1.1 学习排序算法的要点

算法原理、代码实现、评价算法优劣。

1.2 评价排序算法的优劣

排序算法的优劣可以从以下 3 个方面进行评价:

  • 时间性能:最好、最坏、平均时间复杂度;

  • 内存占用:是否原地排序,原地排序算法,特指空间复杂度是 O(1) 的排序算法;

  • 稳定性:相等的数据,排序前后顺序是否有变化,顺序不变是稳定排序算法。

 

排序算法 时间复杂度 空间复杂度 稳定性 算法核心
冒泡排序 O(n2) O(1) 稳定 比较交换
选择排序 O(n2) O(1) 不稳定 比较交换
插入排序 O(n2) O(1) 稳定 插入排序
希尔排序 O(n1.3) O(1) 不稳定 插入排序
归并排序 O(nlog2n) O(n) 稳定 比较合并
快速排序 O(nlog2n) O(log2n) 不稳定 比较交换
桶排序 O(n) O(n) 稳定 非比较
计数排序 O(n) O(n) 稳定 非比较
基数排序 O(n) O(n) 稳定 非比较

 

1.3 有序度与逆序度

有序度是数组中具有有序关系的元素对的个数。有序元素对用数学表达式表示如下:

有序元素对:对于数组 arr,如果下标 i < j,那么 arr[i] <= arr[j]。

根据定义可知,数组 [4,5,6,3,2,1]  的有序度为 3,因为其有序元素对为 3 个,分别是:(4,5) (4,6) (5,6)。

倒序排列的数组,有序度为 0;完全有序的数组,有序度为 n(n-1)/2,比如,数组 [1,2,3,4,5,6]  的有序度为 15,这种完全有序数组的有序度叫做满有序度

 

逆序度与有序度正好相反。用数学表达式表示如下:

逆序元素对:对于数组 arr,如果下标 i < j,那么 arr[i] > arr[j]。

数组 [4,5,6,3,2,1]  的逆序度为 12,因为其逆序元素对为 12 个,分别是:(4,3)(4,2)(4,1)(5,3)(5,2)(5,1)(6,3)(6,2)(6,1)(3,2)(3,1)(2,1)。

 

根据有序度、逆序度、满有序度的概念,可以得到一个公式:逆序度 = 满有序度 - 有序度

数组排序的实质,就是增加有序度,减少逆序度的过程,最后达到满有序度,排序完成。

 

二、常见排序算法

2.1 冒泡排序

2.1.1 算法原理

冒泡排序只会操作相邻的两个数据。每次冒泡操作都会对相邻的两个元素进行比较,如果不满足大小关系要求,就进行交换。一次冒泡会让至少一个元素移动到它应该在的位置,重复 n 次,就完成了 n 个数据的排序。

示例:对数组 arr = [4,5,6,3,2,1] 从小到大进行冒泡排序。

第1次冒泡:

第2次冒泡:

第3次冒泡:

第4次冒泡:

第5次冒泡:

第6次冒泡:

 

冒泡过程回顾

 

冒泡排序算法优化

思路:当某次冒泡操作没有数据交换时,说明数组已经完全有序,不用再进行后续的冒泡操作。

示例:对数组 arr = [3,5,4,1,2,6] 从小到大进行冒泡排序。

第1次冒泡:

第2次冒泡:

第3次冒泡:

第4次冒泡:

第4次冒泡操作无数据交换,说明数组已经完全有序,不用再进行后续的冒泡操作。

 

2.1.2 代码实现

/**
* 冒泡排序:时间复杂度 O(n^2),空间复杂度 O(1),稳定
*
* @param arr 待排序数组
*/
public static void bubbleSort(int[] arr) {
    if (arr == null || arr.length < 2) {
        return;
    }

    boolean isSwap = false;
    for (int i = 0, len = arr.length; i < len - 1; i++) { // 冒泡操作的次数
        for (int j = 0; j < len - 1 - i; j++) { // 每次冒泡比较的元素
            if (arr[j] > arr[j + 1]) {
                swap(arr, j, j + 1);
                isSwap = true;
            }
        }
        // 优化:没有交换代表数组已经完全有序
        if (!isSwap) {
            return;
        }
    }
}

private static void swap(int[] arr, int i, int j) {
    if (i == j) {
        return;
    }
    arr[i] = arr[i] ^ arr[j];
    arr[j] = arr[i] ^ arr[j];
    arr[i] = arr[i] ^ arr[j];
}

 

2.1.3 算法评价

时间复杂度

最好时间复杂度:O(n)

最好情况下,要排序的数组已经是有序的,只需要进行一次冒泡操作,就可以结束了,所以最好情况时间复杂度是 O(n)。

最坏时间复杂度:O(n2)

最坏情况下,要排序的数组刚好是倒序排列的,需要进行 n 次冒泡操作,所以最坏情况时间复杂度为 O(n2)。

平均时间复杂度:O(n2)

平均时间复杂度就是加权平均期望时间复杂度,分析的时候要结合概率论的知识。对于包含 n 个数据的数组,这 n 个数据就有 n! 种排列方式。不同的排列方式,冒泡排序执行的时间肯定是不同的。比如我们前面举的那两个例子,其中一个要进行 6 次冒泡,而另一个只需要 4 次。如果用概率论方法定量分析平均时间复杂度,涉及的数学推理和计算会很复杂。这里我们通过“有序度”和“逆序度”来进行分析。

冒泡排序包含两个操作原子:比较交换。每交换一次,有序度就加 1。不管算法怎么改进,交换的总次数是确定的,即为逆序度,也就是 n*(n-1)/2 - 初始有序度。第1个示例中的数组就是 15 – 3 = 12,要进行 12 次交换操作。

对于包含 n 个数据的数组进行冒泡排序,平均交换次数是多少呢?最坏情况下,初始状态的有序度是 0,所以要进行 n*(n-1)/2 次交换。最好情况下,初始状态的有序度是 n*(n-1)/2,就不需要进行交换。我们可以取个中间值 n*(n-1)/4,来表示初始有序度既不是很高也不是很低的平均情况。换句话说,平均情况下,需要 n*(n-1)/4 次交换操作,比较操作肯定要比交换操作多,而复杂度的上限是 O(n2),所以平均情况下的时间复杂度就是 O(n2)。这个平均时间复杂度推导过程并不严谨,但是很实用,毕竟概率论的定量分析太复杂,不太好理解。

 

空间复杂度

冒泡过程只涉及相邻元素的比较和交换操作,只需要常量级的临时空间,所以它的空间复杂度为 O(1),是一个原地排序算法。

 

稳定性

冒泡排序中,只有交换才会改变两个元素的前后顺序。当相邻的两个元素大小相等时,我们不做交换,所以相同大小的数据在排序前后不会改变顺序,这样就可以保证冒泡排序是稳定的排序算法。

标签:arr,复杂度,基础,算法,冒泡,有序,排序
From: https://www.cnblogs.com/luwei0424/p/17742153.html

相关文章

  • 2023-2024-1 20231314许城铭 《计算机基础与程序设计》第一周学习总结
    2023-2024-120231314许城铭《计算机基础与程序设计》第一周学习总结作业信息这个作业属于哪个课程(2022-2023-1-计算机基础与程序设计)这个作业要求在哪里(2022-2023-1计算机基础与程序设计第一周作业)这个作业的目标<简单浏览《计算机科学概论》,并尝试提出问题以......
  • TypeScript入门到精通——TypeScript类型系统基础——字面量类型
    字面量类型 TypeScript支持将字面量作为类型使用,我们称之为字面量类型。每一个字面量类型都只有一个可能的值,即字面量本身。1、boolean字面量类型 boolean字面量类型只有以下两种:true字面量类型false字面量类型 原始类型boolean等同于由true字面量类型......
  • 动态规划基础
    动态规划方案数问题例:P1002[NOIP2002普及组]过河卒解题思路参考代码#include<cstdio>typedeflonglongLL;constintN=25;intdx[8]={-2,-2,-1,-1,1,1,2,2};intdy[8]={-1,1,-2,2,-2,2,-1,1};boolcontrol[N][N];LLdp[N][N];intm......
  • 2023-2024-1 20231319《计算机基础与程序设计》第1周学习总结
    《计算机基础与程序设计》第1周学习总结说明班级:2023-2024-1-计算机基础与程序设计作业要求:2023-2024-1《计算机基础与程序设计》教学进程作业目标:快速浏览一遍教材,并提出问题问题第一章1.信息隐藏是如何通过抽象实现的?2.云计算是如何脱离硬件而实现的,真的能完全脱离硬件......
  • eslint airbnb React18+typescript 依赖循环、import自动排序分组
    eslint终极规范爱彼迎eslint-config-airbnb请先阅读完下以下链接在来配置代码规范之什么是eslint,为什么要使用eslinteslint的配置项过多,针对js、ts、vue、jsx、tsx等等不同的规则,小公司或者个人项目可以使用成熟的eslint社区规范,如airbnb、standard、goole等。这里我们介绍......
  • 两种方法获取电话区号,检验我们对Excel基础知识储备的反应能力!
    1职场实例小伙伴们大家好,今天我们专门拿出一个篇幅讲解一下如何在Excel中提取座机电话的区号。如下图所示:是一张各个单位的联系信息,其中的B列为座机电话号码,座机电话号码有一个特点:就是有一个间隔符“-”将一串数字分成了左右两段,左段数字为区号,右段数字为号码。现在我们需要在C列......
  • C/C++学习 -- 分组加密算法(DES算法)
    数据加密标准(DataEncryptionStandard,DES)是一种对称密钥加密算法,是信息安全领域的经典之作。本文将深入探讨DES算法的概述、特点、原理,以及提供C语言和C++语言实现DES算法的代码案例。一、DES算法概述DES算法是一种对称密钥加密算法,由IBM于1977年开发并于1977年被美国国家标准局(NI......
  • 2023-2024-1学年 学号20231317 《计算机基础与程序设计》第二周学习总结
    学期(如2023-2024-1)学号(如:20231317)《计算机基础与程序设计》第二周学习总结作业信息这个作业属于哪个课程<班级的链接>(如2023-2024-1-计算机基础与程序设计)这个作业要求在哪里<作业要求的链接>(如2023-2024-1计算机基础与程序设计第二周作业)这个作业的目标<分别......
  • 安装Linux操作系统,学习Linux基础
    安装Linux操作系统安装Linux操作系统实践学习“别出心裁的Linux命令学习法”1、ls命令2、man命令3、cheat命令实践学习“Linux基础入门(新版)”......
  • python基础操作练习题
    使用版本:python3.6.8IDE:pycharm前言这些练习题是在神经网络与深度学习课程上老师提供的,原因是有些同学没学过python,作为简单的练手习题。题目都很简单,加上python本身也比较简单,有些题目的作答可以一行代码实现(虽然可读性就下降了)。练习题2.1数位之和编写程序,输入一个正......