冒泡排序和快速排序的分析与比较

2023-11-05

冒泡排序,就是相邻的两个元素相互比较并根据比较结果决定是否交换位置。如从小到大排序,相邻两个元素两两比较,将值更大的元素交换到右侧,如此到最后一个元素,就能确定最大的一个值,一轮排序结束。若某一轮排序交换位置的次数为0,则排序结束。

冒泡排序基于简单交换的思想,冒泡排序每趟不断将记录两两比较,并按“前小后大”的规则交换。

冒泡排序的基本思想是:

①从数组的头部开始,比较相邻两个数,如果第1个数比第2个数大,就交换他们两个。也就是让较大的数逐渐往后移动,直到数组的末尾,经过第一轮的比较,就可以找到最大的元素,并将它移动到最后一个位置。

②第一轮结束后,继续第二轮,仍然从数组的头部开始比较,直到数组的倒数第2个元素为止,经过第2轮比较,就可以找到次大的元素,并将它放到倒数第二个位置。

③以此类推,经过n-1轮“冒泡”后,就可以将所有的元素都排列好。

冒泡排序的实例(升序):

初始:  21  25  49  25  16  08  n=6

第一趟:位置0,1进行比较--判断21<25--不交换--结果:21  25  49  25  16  08

       位置1,2进行比较--判断25<49--不交换--结果:21  25  49  25  16  08

       位置2,3进行比较--判断49>25--交换--结果:21  25  25  49  16  08

       位置3,4进行比较--判断49>16--交换--结果:21  25  25  16  49  08

       位置4,5进行比较--判断49>08--交换--结果:21  25  25  16  08  49

       第一趟比较了5次,确定了最大的数字49

第二趟:位置0,1进行比较--判断21<25--不交换--结果:21  25  25  16  08  49

       位置1,2进行比较--判断25=25--不交换--结果:21  25  25  16  08  49

       位置2,3进行比较--判断25>16--交换--结果:21  25  16  25  08  49

       位置3,4进行比较--判断25>08--交换--结果:21  25  16  08  25  49

       第二趟比较了4次,确定了第二大数字25

第三趟:位置0,1进行比较--判断21<25--不交换--结果:21  25  16  08  25  49

        位置1,2进行比较--判断25>16--交换--结果:21  16  25  08  25  49

       位置2,3进行比较--判断25>08--交换--结果:21  16  08  25  25  49

       第三趟比较了3次,确定了第三大数字25

第四趟:位置0,1进行比较--判断21>16--交换--结果:16  21  08  25  25  49

        位置1,2进行比较--判断21>08--交换--结果:16  08  21  25  25  49

       第四趟比较了2次,确定了第四大数字21

第五趟:位置0,1进行比较--判断21>08--交换--结果:08  16  21  25  25  49

       第五趟比较了1次,确定了第五大数字16和最小的数字08

可以得出结论,n个记录的话,总共需要n-1趟,第x趟需要比较n-x次。

冒泡排序总共排的次数为:1+2+3+…+n-1,共 n(n-1)/2,时间复杂度为O(n2)。

快速排序是改进的交换排序。从本质上来看,快速排序是一种递归分治法。首先任意选取一个数据(通常选用数组的第一个数)作为枢轴,然后将所有比它小的数都放到它前面,所有比它大的数都放到它后面,形成左右两个子表,这个过程称为一趟快速排序,然后对各子表重新选择中心元素并依此规则调整,直到每个子表的元素只剩下一个。通过一趟排序,将待排序记录分割成独立的两部分,其中一部分记录的关键字均比另一部分记录的关键字小,则可分别对这两部分进行排序,以达到整个序列有序。值得注意的是,快速排序不是一种稳定的排序算法,也就是说,多个相同的值的相对位置也许会在算法结束时产生变动。

快速排序的思路:

(1)从数列中挑出一个元素,称为 “基准”(pivot);

(2)将元素分而治之,小的置于基准值左侧,大的置于基准值右侧;

(3)基准值两侧作为两个子数列,再分别找一个基准值,重复步骤(1)。

快速排序的实现步骤:

两个指针left,right分别指向列表的第一个元素和最后一个元素,然后取一个参考值,默认为第一个列表的第一个元素list[0],称为K

然后left指向的值先和参考值K进行比较,若list[left]小于或等于K值,left就一直向右移动,left+1,直到移动到大于K值的地方,停住

right指向的值和参考值K进行比较,若list[right]大于K值,right就一直向左移动,right-1,直到移动到小于K值的地方,停住

此时,left和right若还没有相遇,即left还小于right,则二者指向的值互换

若已经相遇则说明,第一次排序已经完成,将list[right]与list[0]的值进行互换,进行之后的递归。

 下面是用python实现的冒泡排序和快速排序:

def bubble_super(arr):
    """冒泡排序"""
    loop = len(arr) - 1
    flag = 1
    if loop > 0:
        print('初始flag=',flag)
        for x in range(loop):    # 总共需要 loop 趟
            if flag ==1:
                print('第',x+1,'趟:flag=',flag)
                flag = 0
                for i in range(loop - x):   # 第x趟需要比较 loop-x 次
                    if arr[i] > arr[i + 1]:  #若发生逆序 
                        flag = 1
                        arr[i], arr[i + 1] = arr[i + 1], arr[i]   # 则交换位置
                        print('        第',i+1,'次:flag=',flag,'结果为:',arr)
                    else:
                        print('        第',i+1,'次:flag=',flag,'结果为:',arr)
            else:
                print('第',x+1,'趟:flag=',flag)
    return arr
num = [8,21,21,16,49,25]
print('最终结果:',bubble_super(num))
def split_array(nums, left, right):  # 返回调整后基准数的位置
    key = nums[left]  # nums[left]就是第一个基准点
    while left < right:
        # right下标位置开始,向左边遍历,查找不大于基准数的元素
        while left < right and nums[right] >= key:
            right -= 1
        if left < right:  # 找到小于准基数key的元素,然后交换nums[left],nums[right]
            nums[left], nums[right] = nums[right], nums[left]
        else:  # left〉=right 跳出循环
            break
        # left下标位置开始,向右边遍历,查找不小于基准数的元素
        while left < right and nums[left] < key:
            left += 1
        if left < right:  # 找到比基准数大的元素,然后交换nums[left],nums[right]
            nums[right], nums[left] = nums[left], nums[right]  
        else:  # left〉=right 跳出循环
            break
    nums[left] = key
    print('基准点',key,'的排序结果是:',nums)
    return left  # 此时left==right 所以返回right也是可以的

def quick_sort(nums, left, right):
    if left < right:
        key_index = split_array(nums, left, right)
        quick_sort(nums, left, key_index - 1)
        quick_sort(nums, key_index + 1, right)

if __name__ == "__main__":
    nums = [6,1,2,7,9,3,4,5,10,8]
    quick_sort(nums, 0, len(nums) - 1)
    print('最后的结果是:',nums)

 冒泡排序的运行结果为:

快速排序的运行结果为:

结果分析

两种算法的复杂度及稳定性比较:

排序算法

时间复杂度(平均)

时间复杂度(最坏)

时间复杂度(最好)

空间复杂度

稳定性

冒泡排序

O(n2)

O(n2)

O(n)

O(1)

稳定

快速排序

O(nlog2n)

O(n2)

O(nlog2n)

O(log2n)

不稳定

快速排序不是原地排序,需要递归调用栈的支持,而栈的长度取决于递归调用的深度(即使不用递归,也要用到用户栈)。在平均情况下,需要用到O(log2n)的栈空间,最坏情况下,栈空间可以达到O(n)

快速排序不适合对原本有序或者基本有序的记录序列进行排序。划分元素的选取是影响时间性能的关键,输入次序越混乱,所选划分元素值的随机性就越好,排序速度就越快,快速排序不是自然排序方法。

冒泡排序是从最底层元素开始比较,(与其上的元素比较)小于就往上再比,大于就交换,再用较小的往上比较,直到最高层,第一次把最大的放到最上层,第二次把第二大的放到第二层,以次类推;快速排序是先找到一个轴值,比较时把所有比轴值小的放到轴值的左边,比轴值大的放到右边,再在两边各自选取轴值再按前面排序,直到完成。

当数据量增大时,冒泡排序所用时间如下图所示:

 

快速排序所用时间如下图所示:

很明显,数据量增大时,快速排序比冒泡排序效率高出很多。如果数字只有几个的话两者比较不是很明显。快速排序是所有内部排序算法中平均性能最优的排序算法。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

冒泡排序和快速排序的分析与比较 的相关文章

  • Python动态导入脚本,需要有其__name__ == "__main__"代码才能被调用

    当从另一个脚本导入 python 脚本时 我想要受经典保护的脚本代码 if name main 要运行 我怎样才能运行该代码 我想做的是从 python 脚本动态更改模块 然后导入现有脚本 该脚本应该看到所做的更改并运行其 main 像Py
  • Python 将列表中的字符串转换为数字

    我遇到了以下错误消息 以 10 为基数的 int 的文字无效 2 2 外部用单引号括起来 内部用双引号括起来 该数据位于primes列出使用print primes 0 样本数据在primes list 2 3 5 7 The primes
  • 计算温度的偏导数(温度的水平平流)

    我想知道哪种方法计算x和y方向温度的偏导数 温度的水平平流 最正确 第二个代码使用温度 纬向风和经向风的数据矩阵 提取温度 T 纬向风分量 u 和经向风分量 v 的数据 import matplotlib pyplot as plt imp
  • 如何在 Linux 中显示进程状态(阻塞、非阻塞)

    有没有办法查询 Linux 进程表中进程的状态 以便能够演示执行查询时进程是正在运行还是被阻止 我的目标是从进程或程序的 外部 执行此操作 因为我希望从操作系统进程的角度来理解这一点 但欢迎任何想法 这是Python代码阻塞的过程 impo
  • 在 python + Flask + Gunicorn + nginx + Compute Engine 应用程序中从 Google Cloud Storage 读取文件失败

    在 python Flask Gunicorn nginx Compute Engine 应用程序中读取从 Google Cloud Storage 下载的文件失败 代码链接 https github com samuq CE test h
  • Python 可以使用单独的媒体播放器打开 mp3 文件吗? [关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 是否可以开一个mp3Python 中的文件 可以使用Popen 我并不是要在程序中运行它 我的意思是作为媒体播放器中的一个单独窗口或其
  • Pygame 玩家精灵没有出现

    我一直在为学校计算机课做这个项目 但无法让玩家精灵出现 有人可以帮忙吗 当我运行主游戏循环时 除了玩家精灵之外 所有内容都正确显示 它应该由于箭头输入而在屏幕上移动并受到重力的影响 当我删除图像并仅使用对象类和矩形时 该代码也有效 impo
  • 确定Python模块中的函数是否可用

    我正在研究一些使用Python套接字的代码socket fromfd http docs python org library socket html socket fromfd功能 但是 此方法并非在所有平台上都可用 因此我正在编写一些后
  • 肥皂服务的良好框架是什么?

    我正在寻找一个用于肥皂的好框架service 我更喜欢使用Pythonic框架 但是在查看了soaplib rpclib 太不稳定 SOAPy 不适用于2 7 和ZSI 太 令人困惑 之后 我不确定这是否可能 我对使用另一种语言感到满意 尽
  • Python MySQL 模块

    我正在开发一个需要与 MySQL 数据库交互的 Web 应用程序 但我似乎找不到任何真正适合 Python 的模块 我特别寻找快速模块 能够处理数十万个连接 和查询 所有这些都在短时间内完成 而不会对速度产生重大影响 我想我的答案将是游戏领
  • Cython:为什么 size_t 比 int 快?

    更改某些 Cython 变量的类型int输入size t可以显着减少某些功能的时间 30 但我不明白为什么 例如 cimport numpy as cnp import numpy as np def sum int cnp int64 t
  • 监控单个文件

    我需要监控 使用watchdog http pythonhosted org watchdog index html 单个文件 而不是整个目录 避免监视整个目录的最佳方法是什么 我想this http pythonhosted org wa
  • 如何替换被测模块的文件访问引用

    pyfakefs https code google com p pyfakefs 听起来非常有用 它 最初是作为核心 Python 模块的一个适度的假实现来开发的 以支持中等复杂的文件系统交互 并于 2006 年 9 月在 Google
  • Python unittest - 与assertRaises相反?

    我想编写一个测试来确定在给定情况下不会引发异常 测试是否有异常很简单is上调 sInvalidPath AlwaysSuppliesAnInvalidPath self assertRaises PathIsNotAValidOne MyO
  • 在Python中引用不带换行符的长字符串

    我正在尝试在 Python 中编写一个长字符串 该字符串显示为 OptParser 选项的帮助项 在我的源代码 py 文件中 我想放置换行符 以便我的代码不会花费新行 但是 我不希望这些换行符影响代码运行时该字符串的显示方式 例如 我想写
  • Python 类方法的示例用例是什么?

    我读了Python 中的类方法有什么用 https stackoverflow com questions 38238 what are class methods in python for但那篇文章中的例子很复杂 我正在寻找 Pytho
  • 安排 Asyncio 任务每 X 秒执行一次?

    我正在尝试创建一个 python 不和谐机器人 它将每隔 X 秒检查一次活跃会员 并根据会员的在线时间奖励积分 我正在使用 asyncio 来处理聊天命令 这一切都正常 我的问题是找到一种方法来安排每隔 X 秒异步检查一次活动成员 我已经阅
  • 连接运算符 + 或 ,

    var1 abc var2 xyz print literal var1 var2 literalabcxyz print literal var1 var2 literal abc xyz 除了带有 的自动空格之外 两者有什么区别 哪个通
  • Python列表问题

    我在使用 python 列表时遇到问题 简化版本是 mylist1 some items in a list mylist2 mylist1 mylist1 pop i mylist insert i item print mylist1
  • Python pip 安装错误 [SSL: CERTIFICATE_VERIFY_FAILED]

    我已经尝试解决这个问题有一段时间了 由于某种原因 我陷入了 ssl 问题 并且不知道发生了什么 问题 我已经安装了 python2 7 和 easy install2 7 但是当尝试使用 easy install2 7 安装 pip 时 出

随机推荐

  • 机器学习西瓜书吃瓜笔记之(一)深入理解线性模型与logistics回归

    入门概念 机器学习两大基本问题 预期的输出是离散还是连续 回归问题 用多个变量拟合出一个连续值 分类问题 用多个变量拟合出一个离散值 机器学习三大理论 确定研究手段 传统监督学习 血糖预测 有无糖尿病预测 深度学习 自然语言处理 计算机视觉
  • hosts文件的作用以及hosts中多个ip映射一个域名地址的解析顺序

    hosts的作用 当我们访问网站时 要首先通过DNS服务器把网络域名 www xx com 解析成IP地址 我们的计算机才能访问 如果对于每个域名请求我们都要等待域名服务器解析后返回IP信息 这样访问网络的效率就会降低 而Hosts文件就能
  • 什么是copyonwrite容器

    开发十年 就只剩下这套Java开发体系了 gt gt gt CopyOnWrite容器即写时复制的容器 通俗的理解是当往一个容器添加元素的时候 不直接往当前容器添加 而是先将当前容器进行Copy 复制出一个新的容器 然后新的容器里添加元素
  • STK的2D二维采用的投影方式及osgEarth实现

    Spherical or Equirectangular projection 等距圆柱投影 球面投影 The equirectangular projection also called the equidistant cylindric
  • 【tkinter学习笔记 - 2】:Entry的使用、Button按钮的使用

    目录 一 Entry单行文本框 代码演示 Button按钮的使用 代码演示 一 Entry单行文本框 Entry用来接收一行字符串的控件 如果用户输入的文字长度长于 Entry 控件的宽度时 文字会自动向后滚动 如果想输入多行文本 需要使用
  • linux系统centos7使用 locate命令 查找文件

    百度找到都是whereis find这种 有时候搜不出来 发现locate非常好用
  • uni-app 设置APP应用跳转到系统设置页

    打开蓝牙设置 var main plus android runtimeMainActivity var Intent plus android importClass android content Intent var mIntent
  • Springboot整合Shiro实现登录认证

    一 概述 Shiro 是一个功能强大且易于使用的轻量级Java安全框架 包括身份验证 授权 加密及会话管理 使用Shiro易于理解的API 可以轻松地保护任何应用程序 二 Shiro主要组成 1 首先主要包括三大实体 Subject Rea
  • 优秀的测试工程师应该具备哪些素质

    人是测试工作中最有价值也是最重要的资源 只有保证测试工程师良好的素质 才能保证测试 产品的质量 然而 在有些公司让那些没有应聘上开发职位的人来做测试 这绝对是错误的 最终会损害企业 为高质高效地完成测试任务 软件测试工程师应具有很好的素质和
  • echarts设置y轴值间隔

    在标签yAxis 中 设置min max splitNumber 例如 min 0 max 1 splitNumber 10 呈现
  • 暴力破解漏洞

    0x01 漏洞描述 暴力破解漏洞 暴力破解的产生是由于服务器端没有做合理的限制 导致攻击者可以通过暴力的手段破解所需信息 如用户名 密码 验证码等 暴力破解的关键在于字典的大小 暴力破解需要一个庞大的字典 如4位数字的验证码 那么暴力破解的
  • MDK软件不能模拟仿真STM32F407的问题解决方法

    以下转载文章有点多 如有侵权请联系我删除哦 https blog csdn net weixin 49093913 article details 125362111 关于Keil MDK 5 仿真STM32F4报错no read perm
  • extjs html 指向网页,extjs-mvc结构实践(二):基本页面

    接着来 上一篇搭建了基本的项目骨架 到最后 其实啥也没看见 书接上回 开始写UI效果 目标 全屏显示 左侧导航菜单 右侧标签页切换操作内容区域 包含header和footer 导航菜单动态ajax产生 点击对应菜单可以动态加载js资源或者数
  • 基于小程序+SpringBoot制作一个音乐播放器

    此文主要实现在小程序内音乐播放功能 使用Java作为后端语言进行支持 界面友好 开发简单 一 小程序 1 1 项目创建 1 2 首页 轮播图 热门歌曲 iconfont图标引入 1 3 热门歌单 歌单首页 歌单详情 歌曲详情 1 4 个人中
  • 一些会导致Bundle安装失败的原因

    Bundle RequiredExecutionEnvironment中的值和可用的执行环境不符 缺少Bundle SymbolicName 重复的导入同一个package 导出或导入java 导出的package中必须的属性未定义 安装一
  • 几种前端h264播放器记录

    近期做了点工作记录一下 主要是将H264流在html5上进行播放 众所周知 大多数的 video组件都是支持FLV或者MP4以及m3u8格式的 而如果是WebRTC是直接集成好了 本次要求的环境主要是通过Websocket方式进行流传输 不
  • pandas 生成excel 和 csv

    import pandas as pd a a b c b 1 2 3 dit char a num b file path r output xlsx writer pd ExcelWriter file path df pd DataF
  • leaflet常用插件库

    1 常用地图切换加载 osm google baidu gaode tianditu etc https github com htoooth Leaflet ChineseTmsProviders 2 切片地图加载 wmts 支持矢量切片
  • 如何获取节点的方法,动态计算节点高度

    监听节点偏移量 onScroll e const scrollTop e detail 根据组件的高度 计算当前的区间在哪个位置 this data scrollIntoview this data activeKey this getAc
  • 冒泡排序和快速排序的分析与比较

    冒泡排序 就是相邻的两个元素相互比较并根据比较结果决定是否交换位置 如从小到大排序 相邻两个元素两两比较 将值更大的元素交换到右侧 如此到最后一个元素 就能确定最大的一个值 一轮排序结束 若某一轮排序交换位置的次数为0 则排序结束 冒泡排序