NB三人组(堆排序,归并排序,快速排序)(数据结构课设篇2,python版)(排序综合)

news2024/12/23 1:55:19

本篇博客主要详细讲解一下NB三人组排序,为什么叫NB三人组呢?因为他们的时间复杂度都为O(n log n)。第一篇博客讲解的是LowB三人组(冒泡排序,插入排序,选择排序),第三篇博客会讲解其他排序(基数排序,希尔排序和桶排序)

random和time库的用法在第一篇冒泡排序里讲解过。数据结构课设实验内容也在第一篇博客中。

概念:

堆排序是一种利用堆这种数据结构来进行排序的算法,它的时间复杂度为O(n log n),具有很好的性能。它的主要特点是不稳定排序,且不适合小数据集。

归并排序是一种分治算法,它将待排序的序列分成若干个子序列,分别进行排序,然后将已排序的子序列合并成一个有序序列。它的时间复杂度也为O(n log n),具有稳定性和适用于大数据集的特点。

快速排序是一种分治算法,它通过选取一个基准元素,将序列分成两部分,分别对两部分进行排序,然后递归地对子序列进行排序。它的时间复杂度为O(n log n),具有不稳定性和适用于大数据集的特点。

堆排序:

首先讲解一下堆排序的过程,这里是构造大根堆,首先对数组进行建堆操作,建好堆以后对堆进行堆排序,之后再建堆,再排序 往复操作直到所有排序完成。

堆排序比较复杂,难度在于理解上。
这里就不详细讲解建堆过程,步骤过多。
如图:
在这里插入图片描述

代码及详细注释:

import random
import time
def sift(li, low, high):
    '''
    堆调整函数
    :param li: 列表
    :param low: 堆的根节点位置
    :param high: 堆的最后一个元素的位置
    :return:
    '''
    i = low  # i最开始指向根节点
    j = 2*i + 1  # j开始时左孩子 因为这里的下标实际是数组的下标所以左孩子不是2*i,
    tmp = li[low]  # 把堆顶存起来
    while j <= high:  # 只要j位置有数
        if j + 1 <= high and li[j+1] > li[j]:  # 如果有右孩子并且右孩子比左孩子大
            j = j + 1  # j指向右孩子
        if li[j] > tmp:
            li[i] = li[j]
            i = j      # 往下看一层
            j = i*2 + 1
        else:          # tmp更大,把tmp放到i的位置上
            li[i] = tmp   # 把tmp放在某一级领导位置上
            break
    else:
        li[i] = tmp     # 把tmp放在叶子节点上

def heap_sort(li):
    n = len(li)
    for i in range((n-2)//2, -1, -1):
        # i表示建堆的时候调整的部分的根的小标
        sift(li, i, n-1)
    # 建堆完成了
    for i in range(n-1, -1, -1):
        # i 指向当前堆的最后一个元素
        li[0], li[i] = li[i], li[0]
        sift(li, 0, i-1)  # i-1是新的high


li = [random.randint(1, 100000000) for i in range(10000)]
start = time.time()
print(li)
heap_sort(li)
print(li)
end = time.time()
print('运行时间:%s Seconds'%(end-start))

运行结果:在这里插入图片描述

归并排序:

归并排序用的是分治法,把一个大问题化解为k个中问题,每个中问题再化解为k个小问题,直至问题化为最小可解的问题。对这些问题求解,再不断地合并结果,直至合并完毕。
如图:
在这里插入图片描述

代码及详细注释:

import random
import time
def merge(li, low, mid, high):
    '''
    归并函数,用来合并两个有序序列
    :param li: 列表
    :param low: 左边有序序列的起始位置
    :param mid: 左边有序序列的结束位置
    :param high: 右边有序序列的结束位置
    :return:
    '''
    i = low
    j = mid + 1
    itmp = []
    while i <= mid and j <= high:  # 只要左右两边都有数
        if li[i] < li[j]:
            itmp.append(li[i])
            i += 1
        else:
            itmp.append(li[j])
            j += 1
    # while执行完,肯定有一部分没数了
    while i <= mid:
        itmp.append(li[i])
        i += 1
    while j <= high:
        itmp.append(li[j])
        j += 1
    li[low:high + 1] = itmp  # 将合并后的有序序列放回原列表

def merge_sort(li, low, high):
    '''
    归并排序函数
    :param li: 列表
    :param low: 起始位置
    :param high: 结束位置
    :return:
    '''
    if low < high:
        mid = (low + high) // 2  # 至少有两个元素,递归
        merge_sort(li, low, mid)  # 对左半部分进行归并排序
        merge_sort(li, mid + 1, high)  # 对右半部分进行归并排序
        merge(li, low, mid, high)  # 合并两个有序序列

li = [random.randint(1, 100000000) for i in range(10000)]
start = time.time()
print(li)
merge_sort(li, 0, len(li) - 1)
print(li)
end = time.time()
print('运行时间:%s Seconds'%(end-start))

归并排序比较好写但不好理解,这里跟大家讲一下具体理解,
def merge()里代码的含义是一次归并的过程,比如 [2,4,5,7,1,3,6,8] 该数组从mid(索引3)开始左右两边有序,现在合并成一个有序数组,i 指向元素2,j指向元素1,两者比较,小的数(1)进新数组,然后指针j 后移一位,继续跟i指针指向的元素比较,小的进数组,一直重复,直到一边无数可比为止,然后把另一边的剩余未比较的数组全部入新数组。
def merge_sort()函数作用是递归分解原数组,分解到只剩一个元素,最后再调用def merge()函数进行合并

运行结果:

在这里插入图片描述

快速排序:

快速排序是一种基于分治思想的排序算法,其过程可以描述如下:

  1. 选择一个基准元素(通常是数组中的第一个元素)。
  2. 将数组中小于基准元素的元素移动到基准元素的左边,大于基准元素的元素移动到右边,基准元素则位于最终排序位置。
  3. 对基准元素左右两边的子数组分别进行快速排序,直到子数组长度为1或0。
    递归地重复步骤2和步骤3,直到整个数组有序。

如图:
在这里插入图片描述
在这里插入图片描述

代码及详细注释:

import random
import time
def partition(li, left, right):
    '''
    划分函数,用于将列表分成两部分并返回中间位置
    :param li: 列表
    :param left: 左边界
    :param right: 右边界
    :return: 中间位置
    '''
    tmp = li[left]
    while left < right:
        while left < right and li[right] >= tmp:  # 从右面找比tmp小的数
            right -= 1                            # 往左走一步
        else:
            li[left] = li[right]                  # 把右边的值写到左边空位上
        while left < right and li[left] <= tmp:   # 从左边找比tmp大的数
            left += 1
        else:
            li[right] = li[left]                  # 把左边的值写到右边空位上
    li[left] = tmp                                # 把tmp归位
    return left

def quick_sort(li, left, right):
    '''
    快速排序函数
    :param li: 列表
    :param left: 起始位置
    :param right: 结束位置
    :return:
    '''
    if left < right:  # 至少两个元素
        mid = partition(li, left, right)  # 划分并获取中间位置
        quick_sort(li, left, mid - 1)  # 对左半部分进行快速排序
        quick_sort(li, mid + 1, right)  # 对右半部分进行快速排序

li = [random.randint(1, 100000000) for i in range(10000)]
start = time.time()
print(li)
quick_sort(li, 0, len(li) - 1)
print(li)
end = time.time()
print('运行时间:%s Seconds'%(end-start))

快排要用双指针法,两个指针来遍历数组进行比较,直到指针相遇。递归调用的思想跟归并差不多

运行结果:

在这里插入图片描述

总结:

之前的LowB三人组是看代码里的注释就可以理解,没有必要讲。而NB三人组的每趟排序的详细过程步骤篇幅太长,不太好讲,也不好找图片,只能粗略带大家过一遍。

通过运行时间可以明显看出NB三人组的运行效率比LowB三人组快很多,不过NB三人组的算法思想稍微有点难理解,如果理解了代码还是较容易实现,我认为难点在递归调用的理解上面,每一趟的排序实现还是容易写出来的。排序综合还剩下最后一篇其他排序的讲解就结束了。

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

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

相关文章

Jenkins分布式实现: 构建弹性和可扩展的CI/CD环境!

Jenkins是一个流行的开源持续集成&#xff08;Continuous Integration&#xff0c;CI&#xff09;和持续交付&#xff08;Continuous Delivery&#xff0c;CD&#xff09;工具&#xff0c;它通过自动化构建、测试和部署过程&#xff0c;帮助开发团队更高效地交付软件。Jenkins的…

Linux——系统安全及应用

一、基本安全措施 1、系统账号清理 常见的非登录用户账号包括bin、daemon、 adm、lp、mail等。为了确保系统安全&#xff0c;这些用户账号的登录Shell通常是/ sbin/nologin&#xff0c;表示禁止终端登录&#xff0c;应确保不被人为改动。 //将非登陆用户的Shell设为/sbin/nolo…

STM32G030C8T6:USART串口通信(中断)

本专栏记录STM32开发各个功能的详细过程&#xff0c;方便自己后续查看&#xff0c;当然也供正在入门STM32单片机的兄弟们参考&#xff1b; 本小节的目标是&#xff0c;系统主频64 MHZ,采用高速外部晶振&#xff0c;通过芯片PB6,PB7 的USART1 口&#xff0c;实现串口通信。 原理…

Oracle数据恢复记录一 表数据的恢复

当我们误删/修改数据之后&#xff0c;要进行数据恢复&#xff0c;需要有数据库管理员权限才能实现&#xff0c;所以奉劝各位修改数据要好好确认&#xff0c;搞出异常来就很麻烦了。下面是一个数据恢复简单的例子&#xff1a; DML Sql 这里展示了修改的sql UPDATE XX_MES_PROC…

MySQL基础笔记(4)DQL数据查询语句

DQL用于查找数据库中存放的记录~ 目录 一.语法 二.基础查询 1.查询多个字段 2.设置别名 3.去除重复记录 三.条件查询 1.基础语法 2.常见条件 四.分组查询 1.聚合函数 2.语法 五.排序查询 六.分页查询 附注&#xff1a;DQL执行顺序 1.编写顺序 2.执行顺序 ​​​…

Reids原理及简单命令

目录 1.关系数据库与非关系型数据库 关系型数据库 非关系型数据库 关系型数据库和非关系型数据库区别 数据存储方式不同 扩展方式不同 对事务性的支持不同 总结&#xff1a; 2. Redis简介 什么是reids reids优点 reids使用场景&#xff1a; reids快的原因 Redis数…

RFID标签在汽车监管方面的应用与实施方案

RFID技术在汽车工业领域得到了广泛应用&#xff0c;主要体现在汽车资质证书远程监管系统的普及化&#xff0c;系统包括OBD接口监视器、车证监管箱、超高频读写设备、应用系统软件以及大数据采集与处理等组成部分。 在汽车物流监管方面&#xff0c;系统利用OBD接口监控车辆并实时…

无心剑汉英双语诗《一亩三分地》

一亩三分地 My Small World 二十四年世事变幻 拨号上网曾争分夺秒 如今不限流量肆意冲浪 大数据&#xff0c;云计算&#xff0c;人工智能 洗刷着世间各行各业 周围人&#xff0c;生活不断升级 房子&#xff0c;车子&#xff0c;妻子…… 换了一茬又一茬 洋溢着自豪的表情 而我…

乔布斯2005年在斯坦福大学的演讲稿

文章目录 乔布斯2005年在斯坦福大学的演讲稿英语原文译文 乔布斯2005年在斯坦福大学的演讲稿 英语原文 Stay Hungry. Stay Foolish. I am honored to be with you today at your commencement from one of the finest universities in the world. Truth be told, I never gradu…

修改安卓apk设置为安卓主屏幕(launcher)

修改安卓apk 将apk可以设置安卓主屏幕 原理&#xff1a; 将打包好的apk文件进行拆包增加配置文件在重新编译回apk包 需要得相关文件下载 解包 apktool :https://pan.baidu.com/s/1oyCIYak_MHDJCvDbHj_qEA?pwd5j2xdex2jar&#xff1a;https://pan.baidu.com/s/1Nc-0vppVd0G…

Unity真机Log工具 SRDebugger使用记录,GM布局管理

SRDebugger 官方文档安装及初始化常用设置选项布局选项快捷键选项高级设置 使用GM工具案例常用特性GM分组排序GM固定页签 官方文档 文档&#xff1a; https://www.stompyrobot.uk/tools/srdebugger/documentation/ 插件地址&#xff1a; https://assetstore.unity.com/package…

Python基础知识总结1-Python基础概念搞定这一篇就够了

时隔多年不用忘却了很多&#xff0c;再次进行python的汇总总结。好记性不如烂笔头&#xff01; PYTHON基础 Python简介python是什么&#xff1f;Python特点Python应用场景Python版本和兼容问题解决方案python程序基本格式 Python程序的构成代码的组织和缩进使用\行连接符 对象…

【深度学习每日小知识】数据增强

数据增强是通过对原始数据进行各种转换和修改来人工生成附加数据的过程&#xff0c;旨在增加机器学习模型中训练数据的大小和多样性。这对于计算机视觉领域尤为重要&#xff0c;因为图像经常被用作输入数据。 计算机视觉中的数据增强 数据增强的主要目标是解决过拟合问题&…

春招冲刺第一天:Excel入门

春招冲刺第一天 前言&#xff1a; 转行换方向了家人们&#xff0c;准备往数据分析那转了&#xff0c;实习我现在也找不到&#xff0c;打算先猛学两周技术&#xff0c;过完年再投简历了。 时间确实非常紧张&#xff0c;目前一天计划学8小时以上&#xff0c;主要参考视频——&g…

使用IDEA官方docker插件构建镜像

此方法同样适用于jetbrains系列的其他开发软件 在IDEA中&#xff0c;如果是maven项目&#xff0c;可以使用插件 <plugin><groupId>com.spotify</groupId><artifactId>docker-maven-plugin</artifactId><version>1.2.2</version> &…

格密码基础:对偶格(超全面)

目录 一. 对偶格的格点 1.1 基本定义 1.2 对偶格的例子 1.3 对偶格的图形理解 二. 对偶格的格基 2.1 基本定义 2.2 对偶格的格基证明 三. 对偶格的行列式 3.1 满秩格 3.2 非满秩格 四. 重复对偶格 五. 对偶格的转移定理&#xff08;transference theorem&#xff…

图像分割实战-系列教程11:U2NET显著性检测实战3

&#x1f341;&#x1f341;&#x1f341;图像分割实战-系列教程 总目录 有任何问题欢迎在下面留言 本篇文章的代码运行界面均在Pycharm中进行 本篇文章配套的代码资源已经上传 U2NET显著性检测实战1 U2NET显著性检测实战2 U2NET显著性检测实战3 6、上采样操作与REBNCONV def…

基于Java SSM框架实现智能仓储管理系统项目【项目源码+论文说明】

基于java的SSM框架实现仓库管理系统演示 摘要 随着科学技术的飞速发展&#xff0c;社会的方方面面、各行各业都在努力与现代的先进技术接轨&#xff0c;通过科技手段来提高自身的优势&#xff0c;智能仓储系统当然也不能排除在外。智能仓储系统是以实际运用为开发背景&#xf…

国科大图像处理2024速通期末——汇总2017-2019、2023回忆

国科大2023.12.28图像处理0854期末重点 图像处理 王伟强 作业 课件 资料 一、填空 一个阴极射线管它的输入与输出满足 s r 2 sr^{2} sr2&#xff0c;这将使得显示系统产生比希望的效果更暗的图像&#xff0c;此时伽马校正通常在信号进入显示器前被进行预处理&#xff0c;令p…

[NSSRound#3 Team]This1sMysql

[NSSRound#3 Team]This1sMysql 源码 <?php show_source(__FILE__); include("class.php"); $conn new mysqli();if(isset($_POST[config]) && is_array($_POST[config])){foreach($_POST[config] as $key > $val){$value is_numeric($var)?(int)$…