蓝桥之手撕排序算法——冒泡、选择、插入、快排、归并(Python版)

news2024/11/16 5:46:29

目录

1. 排序引言

2. 冒泡排序

2.1 算法思想

2.2 代码实现

 2.3 时空复杂度分析

3. 选择排序

3.1 算法思想

3.2 代码实现

 3.3 时空复杂度分析

4. 插入排序

4.1 算法思想

4.3 代码实现

4.4 时空复杂度分析

5. 快速排序

5.1 算法思想

5.2 代码实现

5.3 时空复杂度分析

6. 归并排序

6.1 算法思想

6.2 代码实现

6.3 时空复杂度分析


1. 排序引言

排序算法是算法竞赛中的第一入门必会的算法,可能在语言里面内置好sort排序函数,但是在排序算法中的很多思想是值得我们去学习的,比如从快速排序里面学会如何进行分治以及递归的实现。

2. 冒泡排序

冒泡排序是学习语言和算法中必会的一种算法,下面就由我来进行冒泡排序的分析与代码实现:

2.1 算法思想

对于一个无序数组,我们从索引0开始往右对比,如果当前数字比后一个数字大,就进行交换

这样每次就可以将最大的放在最右边, 上一次对比的最右边的就不再参与下一次排序

因为有N个数,每一次可以将一个最大数排好序,最后一个数也就定好了,因此只需要N-1次,就能排好完整的序。

我们可以看看以下的图:

其实到这里,冒泡排序算法就已经很明确了,每次冒泡都能求出当前最大的数,并将其放在最右边。

2.2 代码实现

a = [6, 5, 4, 1, 3, 2]
n = len(a)
for i in range(n - 1):
    for j in range(n - i - 1):
        if a[j] > a[j + 1]:
            a[j], a[j + 1] = a[j + 1], a[j]
print(a)

 2.3 时空复杂度分析

时间复杂度:

        每次需要比较进行n - i - 1次,也就是n - 1 、 n - 2 、 n - 3.....1次

        一共要执行n - 1次, 大概估算也就是O(n²)

空间复杂度:

        在原数组上面进行的操作,并没有开辟新的空间,所以为:O(1)

3. 选择排序

3.1 算法思想

每次从左往右开始找,找到最小的,然后与当前的索引的数进行交换,并索引加一

这样就能保证,每次都将最小的数排在最前面了。

3.2 代码实现

a = [6, 5, 4, 1, 3, 2]
n = len(a)
for i in range(n - 1):
    minn = a[i]
    index = i
    for j in range(i + 1, n):
        if a[j] < minn:
            minn = min(minn, a[j])
            index = j

    a[i], a[index] = a[index], a[i]
print(a)

 3.3 时空复杂度分析

时间复杂度:

        每一次都要从左往右开始比较,从n - 1 次到1次,也就是n(n - 1) / 2次

        一共要进行n - 1次,所以时间复杂度为:O(n²)

空间复杂度:

        没有开辟额外空间,为:O(1)

4. 插入排序

4.1 算法思想

还是从左往右开始进行排序,当前这个数与前面的每一个数进行比较,如果当前的数比前一个数小,那么就一直往左边走,直到那个数比当前的数大为止。

到当前这个数的时候,前面的数其实已经排序好了,只需要找个合适的位置插入进行就好了。

4.3 代码实现

a = [6, 5, 4, 1, 3, 2 , 10]
n = len(a)
for i in range(1 , n):
    now = a[i]
    index = i
    for j in range(i - 1 , -1 , -1):
        if a[j] > now:
            index = j
            a[j + 1] = a[j]
        else:
            break
    a[index] = now
print(a)

4.4 时空复杂度分析

时间复杂度:

        插入排序比选择排序更加优化一点,但是最坏情况都是O(n²)

        但是最好的情况下(已经有序),只需要O(n)就行了

空间复杂度:

        没有开辟额外的数组,O(1)

5. 快速排序

5.1 算法思想

快速排序是基于分治算法实现的

分治:将一个大问题分解为多个小问题,分别解决这些小问题,然后将它们的解合并起来,从而得到大问题的解。通常,分治算法包含三个步骤:分解(Divide)、解决(Conquer)、合并(Combine)。

 要想理解分治,首先得理解什么是递归?

递归:递归是指在解决问题的过程中调用自身的过程。在编程中,递归是一种常见的编程技巧,它通过将问题分解成更小的、类似的子问题来解决复杂的问题。

 这是一个简单的递归函数:

def factorial(n):
    # 基本情况
    if n == 0:
        return 1
    # 递归情况
    return n * factorial(n - 1)

不难发现,其实这就是求解阶乘的函数,f(n) = n *  fn(n - 1),直到计算到最底层f(0) = 1 ,也就是0的阶乘,然后再不停地返回值,最终得到n的阶乘

当然,上面不理解的话,我们先可以看一下他的实现逻辑:

 先进行分解,算到最底层之后,又从下面往上面推,最终算出f(4)的结果为24

了解什么是分治和递归之后,我们就可以开始愉快的快速排序啦~

快速排序基本步骤:

  • 在数组中找一个基准值x, 一般是中间那个值
  • 将数组分成两个部分:1. 小于等于x的那部分, 2. 大于x的那部分
  • 对两边递归使用该策略

最重要的步骤其实是将数组分成两个部分:

  • 设置基准值l
  • 存放小于等于基准值的下标为:idx = l + 1
  • 从l + 1到r 遍历
    • 如果当前的a[i]<=l , a[i] , a[idx]互换,并且idx += 1
  • 最后就交换idx - 1和 l (idx是刚好大于l的,所以要-1,因为前面执行过一次idx += 1),就能保证l的左边是小于等于基准值的 , 右边是大于基准值的

5.2 代码实现

a = [6, 5, 4, 1, 3, 2, 10]
n = len(a)


def fn(a, l, r):
    # 基准值为:l
    idx = l + 1   # 右边的索引
    for i in range(l + 1, r + 1):
        # 将小于基准值的方在左边 ,大于基准值的放在右边
        if a[i] <= a[l]:
            a[i], a[idx] = a[idx], a[i]
            idx += 1
    # 将基准值放在中间
    a[idx - 1], a[l] = a[l], a[idx - 1]
    # 返回基准值的位置
    return idx - 1


def quick_sort(a, l, r):
    if l > r:
        return
    mid = fn(a, l, r)  # 分基准值为l,分成两部分,左边<=mid , 右边>mid
    quick_sort(a, l, mid - 1)   # 对左边处理
    quick_sort(a, mid + 1, r)   # 对右边处理


quick_sort(a, 0, n - 1)
print(a)

5.3 时空复杂度分析

时间复杂度:

        在一般情况下,我们每次需要遍历分成两个部分,需要执行n次,每次都分成两个部分,相比线性时间,每次排序的都少了一半,于是就是Logn次

        总时间复杂度大概在O(n * logn)

空间复杂度:

        每次递归都是一次递归二叉树,消费的栈空间大概在O(logn)

6. 归并排序

6.1 算法思想

归并排序也是基于分治算法来的

只是归并排序是先递归,再进行合并

算法步骤:

  • 先分成两个部分
  • 每部分都处理成有序的
  • 再将两个数组合并起来

6.2 代码实现

a = [6, 5, 4, 1, 3, 2, 10]
n = len(a)


def merge(a,b):
    res = []
    while len(a) != 0 and len(b)!=0:
        if a[0] <= b[0]:    # 将小的值先放入res
            res.append(a.pop(0))
        else:
            res.append(b.pop(0))
    # 将a,b剩下的值放进来
    res.extend(a)
    res.extend(b)
    return res


def merge_sort(a):
    if len(a) < 2:
        return a
    mid  = len(a) // 2  # 每次分为两个部分

    left = merge_sort(a[:mid])   # 对左边处理
    right = merge_sort(a[mid:])   # 对右边处理
    return merge(left , right)   # 合并两部分
 

a = merge_sort(a)
print(a)

6.3 时空复杂度分析

时间复杂度:

        归并排序与快速排序是类似的,都是O(n * logn)

空间复杂度:

        归并排序每次都需要开辟一个新空间,所以为O(n)

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1526849.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

upload-labs 0.1 靶机详解

下载地址https://github.com/c0ny1/upload-labs/releases Pass-01 他让我们上传一张图片&#xff0c;我们先尝试上传一个php文件 发现他只允许上传图片格式的文件&#xff0c;我们来看看源码 我们可以看到它使用js来限制我们可以上传的内容 但是我们的浏览器是可以关闭js功能的…

【开发】SpringBoot 整合 Redis

目录 前言 1. Redis 的下载及安装 1.1 Redis 的下载 1.2 安装 Redis 1.3 启动 Redis 2. 创建 SpringBoot 项目整合 Redis 2.1 环境要求 2.2 SpringBoot项目构建 2.2.1 方式一 2.2.2 方式二 2.3 在 pom.xml 文件中导入依赖坐标 2.4 在 application.properties 中加…

解释器模式(Interpreter Pattern)

解释器模式 说明 解释器模式&#xff08;Interpreter Pattern&#xff09;属于行为型模式&#xff0c;是指给定一门语言&#xff0c;定义它的语法&#xff08;文法&#xff09;的一种表示&#xff0c;并定义一个解释器&#xff0c;该解释器使用该表示来解释语言中的句子。是一…

CVX安装新版本Mosek求解器

在使用连续凸近似&#xff08;SCA&#xff09;求解优化问题时遇到了报错 Problem status : ILL_POSED Solution status : PRIMAL_ILLPOSED_CER并且最后给出的结果为NaN。 在CVX论坛中找到一条回答 具体链接如下&#xff1a; The status is failed 因为我使用的是CVX自带的…

批量查询快递信息,固乔助手助您高效处理

在物流、供应链等行业&#xff0c;每天都需要处理大量的快递信息。无论是物流公司还是供应链企业&#xff0c;都需要实时掌握每一个包裹的状态和位置。然而&#xff0c;当面对成千上万的快递单号时&#xff0c;如何高效地查询这些信息成为了一个亟待解决的问题。 传统的查询方式…

IDEA直接打包Docker镜像

以下为使用IDEA打包Docker镜像并推送到远程仓库&#xff08;使用Windows打包Docker镜像并推送到远程仓库&#xff09;教程 1 安装Docker Desktop 下载地址&#xff1a;https://www.docker.com/products/docker-desktop/ 安装成功后&#xff0c;可在cmd查看版本号 2 启动Do…

Machine Learning ---- Feature Scaling

目录 一、What is feature scaling:&#xff1a; 二、Why do we need to perform feature scaling? 三、How to perform feature scaling: 1、Normalization: 2、Mean normalization: 3、Standardization (data needs to follow a normal distribution): 一、What is featur…

膨胀 卷积

1.作用 Dilated convolution、Atrous convolution 增大感受野保持原输入大小 2.膨胀因子 描述的是相邻元素之间的距离 r 2 3.gridding effect 不合理的多个膨胀卷积之前&#xff0c;设计的膨胀因子不合理导致&#xff0c;在增大感受野的同时丢失了细节信息。 丢失&…

【SpringCloud】使用Seata实现分布式事务

目录 一、Seata 框架的需求背景二、Seata 事务模式与架构2.1 Seata 组成2.2 Seata 事务模式 三、Seata 实战演示3.1 部署 Seata Server3.1.1 下载 Seata Server3.1.2 更改 Seata Server 配置3.1.3 创建 Seata Server 所需的数据库、数据库表3.1.4 启动 Seata Server 3.2 Seata …

判断闰年(C语言)

一、运行结果&#xff1b; 二、源代码&#xff1b; # define _CRT_SECURE_NO_WARNINGS # include <stdio.h>int main() {//初始化变量值&#xff1b;int year 2000;//执行循环判断&#xff1b;while (year < 2010){//执行流程&#xff1b;//判断能否整除4&#xff1…

十二、CyclicBarrier

CyclicBarrier 栅栏 什么时候满了开始发车 CyclicBarrier barrier new CyclicBarrier(20, () -> System.out.println("满人"));满20人开始发车每一个线程到达 barrier.await();都等着当 barrier.await();到达20人就开始往下执行 &#xff0c;发车 public…

struts2 CVE-2021-31805-struts2 s2-061 ONGL远程代码执行复现

复现&#xff1a; 切换到vulhub开启并且查看靶场的端口 访问页面 我们可以输入下面的命令来测试一下&#xff0c;执行6*6&#xff0c;查看源代码发现可以成功运行 接下来我们可以注入下面的payload来进行代码执行&#xff0c;执行id来查看当前用户 POST / HTTP/1.1 Host: x.x.…

探索Spring中的属性注入:@Value注解解析与应用

探索Spring中的属性注入&#xff1a;Value注解解析与应用 探索Spring中的属性注入&#xff1a;Value注解解析与应用摘要引言正文作用代码准备示例注入字符串注入属性注入Bean及其属性 其他属性注入优先级问题对Value属性注入的扩展Spring Boot对Value类型转换的扩展 代码案例演…

【GameFramework框架内置模块】8、文件系统(File System)

推荐阅读 CSDN主页GitHub开源地址Unity3D插件分享简书地址 大家好&#xff0c;我是佛系工程师☆恬静的小魔龙☆&#xff0c;不定时更新Unity开发技巧&#xff0c;觉得有用记得一键三连哦。 一、前言 【GameFramework框架】系列教程目录&#xff1a; https://blog.csdn.net/q7…

代码随想录算法训练营第二十七天(第二十六天休息)|40.组合总和II

40.组合总和II 题目 给定一个数组 candidates 和一个目标数 target &#xff0c;找出 candidates 中所有可以使数字和为 target 的组合。 candidates 中的每个数字在每个组合中只能使用一次。 说明&#xff1a; 所有数字&#xff08;包括目标数&#xff09;都是正整数。解集…

Android 开发环境搭建(Android Studio 安装图文详细教程)

Android Studio 下载 https://developer.android.google.cn/studio?hlzh-cn Android Studio 安装 检查电脑是否启用虚拟化 如果没有开启虚拟化&#xff0c;则需要进入电脑的 BIOS 中开启 直接 next选择安装的组件&#xff0c;Android Studio 和 Android 虚拟设备&#xff…

使用蜂鸟地图完成楼层自定义、房间着色、热力图、添加图片覆盖物、添加dom覆盖物、定位到固定区域的中心点

项目里有用到蜂鸟地图的地方&#xff0c;虽然有跟她们对接&#xff0c;但看他们文档也挺费劲的&#xff0c;要自己慢慢研究好久&#xff0c;有些实在研究不出来让他们帮忙看代码发现一些问题&#xff0c;所以把我发现的需要注意的一些点发上来&#xff0c;希望可以帮助到部分有…

深入探讨ChatGPT:技术突破与应用前景

目录 一、ChatGPT究竟是什么&#xff1f; 二、ChatGPT的发展脉络 三、ChatGPT的突出优势 强大的语言生成能力 多场景适应性 多语言处理能力 广泛的应用范围 数据敏感性的重视 四、结语&#xff1a;ChatGPT的未来与挑战 Tips&#xff1a;国内的ChatGPT ⭐ 点击进入Chat…

【GIS系列】GeoTools简介及工具类分享

本文将对GeoTools相关概念进行介绍&#xff0c;同时会给大家分享我工作中用到的工具类及使用方法。 作者&#xff1a;后端小肥肠 目录 1.前言 2. GeoTools简介 3. Geotools使用示例 3.1. 开发环境搭建 3.1.1. 所需版本和工具 3.1.2. pom依赖​​​​​​​ 4. 工具类介绍…

为什么不用 index 做 key 引出的 Diff 算法

文章目录 问题分析 问题 大家耳熟能详的最常见的问题就是 为什么不用 index 做 key &#xff0c;在刚开始学习的时候&#xff0c;只是知道在 v-for 做循环遍历的时候需要加上唯一标识 key&#xff0c;但好像都是这么写的 v-for"(item,index) in dictList" :key"…