数据结构与算法之排序

9.1 排序的概念

1. 排序的定义
  • 定义:排序是将表中的记录按关键字递增(或递减)有序排列的过程。
  • 说明:数据中可以存在相同关键字的记录。本章主要考虑递增排序。
  • 扩展:排序是数据处理中的基本操作之一,广泛应用于数据库管理、信息检索等领域。排序可以提高数据的可读性和可操作性,便于后续的查找、统计等操作。
2. 内排序和外排序
  • 内排序:整个表都在内存中处理,不涉及数据的内外存交换。
  • 外排序:排序过程中需要进行数据的内外存交换。
  • 扩展:内排序适用于数据量较小的情况,因为内存访问速度快,效率较高。外排序适用于数据量较大的情况,通常需要将数据分块处理,然后合并排序结果。
3. 内排序的分类
  • 插入排序:通过将元素插入到已排序部分的适当位置来实现排序。
  • 交换排序:通过交换元素的位置来实现排序,如冒泡排序。
  • 选择排序:通过选择未排序部分的最小(或最大)元素与当前元素交换来实现排序。
  • 归并排序:将数据分成多个小部分进行排序,然后将排序好的部分合并。
  • 基于比较的排序算法:如插入排序、交换排序、选择排序、归并排序等。
  • 不基于比较的排序算法:如基数排序。
  • 扩展:不同的排序算法适用于不同的场景,选择合适的排序算法可以提高程序的效率。例如,插入排序适用于部分有序的数据,而归并排序适用于大规模数据的排序.
4.小结
  • 排序的概念定义递增或递减排列
      • 允许相同关键字
    • 内排序 vs 外排序内排序:内存中处理
      • 外排序:内外存交换
    • 内排序分类插入排序
      • 交换排序
      • 选择排序
      • 归并排序
      • 基数排序

9.2插入排序

9.2.1 直接插入排序
基本思路
  • 有序区和无序区:初始时,有序区只有一个元素(通常是第一个元素),无序区包含其余所有元素。
  • 排序过程:每次从未排序区取出一个元素,插入到有序区的适当位置,使得有序区仍然保持有序。
  • 步骤将待插入元素与有序区的元素从后向前比较。
    • 如果待插入元素小于当前比较的元素,则将当前元素后移一位。
    • 重复上述步骤,直到找到待插入元素的正确位置。
    • 将待插入元素插入到该位置。
Python实现

def insert_sort(arr):for i in range(1, len(arr)):
        key = arr[i]
        j = i - 1# 将arr[i]插入到已排序序列arr[0...i-1]中while j >= 0 and key < arr[j]:
            arr[j + 1] = arr[j]
            j -= 1
        arr[j + 1] = keyreturn arr# 示例
arr = [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
print("原始数组:", arr)
insert_sort(arr)
print("排序后的数组:", arr)

算法分析
  • 时间复杂度最好情况:输入序列已经是正序的,时间复杂度为 O(n)。
    • 最坏情况:输入序列是反序的,时间复杂度为 O(n2)。
    • 平均情况:时间复杂度为 O(n2)。
  • 空间复杂度O(1),因为只需要一个额外的变量来存储待插入的元素。
  • 稳定性:稳定排序算法,因为相同元素的相对顺序不会改变。

eg设待排序的表有10个元素,其关键字分别为(9,8,7,6,5,4,3,2,1,0)

9.2.2 折半插入排序

基本思路
  • 折半查找:在有序区中使用折半查找方法来确定待插入元素的位置,从而减少比较次数。
  • 步骤将待插入元素保存在一个临时变量中。
    • 使用折半查找在有序区中找到待插入元素的正确位置。
    • 将有序区中从插入位置开始的所有元素后移一位,为待插入元素腾出空间。
    • 将待插入元素插入到找到的位置。
Python实现

def binary_search(arr, key, low, high):while low <= high:
        mid = (low + high) // 2if arr[mid] < key:
            low = mid + 1else:
            high = mid - 1return lowdef binary_insert_sort(arr):for i in range(1, len(arr)):
        key = arr[i]# 使用折半查找找到插入位置
        pos = binary_search(arr, key, 0, i - 1)# 将元素后移for j in range(i, pos, -1):
            arr[j] = arr[j - 1]# 插入元素
        arr[pos] = keyreturn arr# 示例
arr = [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
print("原始数组:", arr)
binary_insert_sort(arr)
print("排序后的数组:", arr)

算法分析
  • 时间复杂度比较次数:由于使用了折半查找,比较次数为 O(logn)。
    • 移动次数:移动次数仍为 O(n),因为需要将元素后移。
    • 总时间复杂度O(n2),虽然比较次数减少,但移动次数仍然较高。
  • 空间复杂度O(1),只需要一个额外的变量来存储待插入的元素。
  • 稳定性:稳定排序算法,因为相同元素的相对顺序不会改变.

9.2.3 希尔排序

基本思路
  • 分组插入:希尔排序是一种基于插入排序的改进算法,通过将待排序序列分成若干个子序列,对每个子序列进行直接插入排序。
  • 增量序列:选择一个增量序列 d1,d2,,dkd1 ,d2 ,,dk ,其中 d1>d2>>dk=1d1 >d2 >>dk =1。增量 dd 通常从 n/2n/2 开始,每次减半,直到增量为1。
  • 步骤选择一个增量 dd,将待排序序列分成 dd 个子序列。
    • 对每个子序列进行直接插入排序。
    • 减小增量 dd,重复上述步骤,直到增量为1。
Python实现

def shell_sort(arr):
    n = len(arr)
    gap = n // 2  # 初始增量while gap > 0:for i in range(gap, n):
            temp = arr[i]
            j = i# 对每个子序列进行插入排序while j >= gap and arr[j - gap] > temp:
                arr[j] = arr[j - gap]
                j -= gap
            arr[j] = temp
        gap //= 2  # 减小增量return arr# 示例
arr = [9, 8, 7, 6, 5, 4, 3, 2, 1, 0]
print("原始数组:", arr)
shell_sort(arr)
print("排序后的数组:", arr)

算法分析
  • 时间复杂度最好情况O(nlogn)O(nlogn),当增量序列选择得当且数据接近有序时。
    • 最坏情况O(n2)O(n2),但通常比直接插入排序要好。
    • 平均情况:通常为 O(n1.3)O(n1.3) O(n1.5)O(n1.5),具体取决于增量序列的选择。
  • 空间复杂度O(1)O(1),因为只需要一个额外的变量来存储待插入的元素。
  • 稳定性:不稳定排序算法,因为相同元素的相对顺序可能会改变.

希尔排序过程解释

  1. 初始序列9, 8, 7, 6, 5, 4, 3, 2, 1, 0
  2. 第一次排序(d=5)
    1. 增量 d 被设置为数组长度的一半,即 5
    2. 将数组分为 5 组,每组包含相隔 5 个位置的元素:{9, 4}, {8, 3}, {7, 2}, {6, 1}, {5, 0}
    3. 对每组进行直接插入排序。例如,第一组 9, 4 排序后变为 4, 9
    4. 数组变为4938271605
  3. 第二次排序(d=2)
    1. 增量 d 减半,变为 2
    2. 将数组分为 2 组,每组包含相隔 2 个位置的元素:{4, 3, 2, 1}, {9, 8, 7, 6}, {5, 0}
    3. 对每组进行直接插入排序。例如,第一组 4, 3, 2, 1 排序后变为 1, 2, 3, 4
    4. 数组变为1234678905
  4. 第三次排序(d=1)
    1. 增量 d 再次减半,变为 1因为整一个数组基本有序,最后进行一次直接插入排序时间复杂度就约等于O(n),在这里除了0和5其它元素都是直接放入有序区。
    2. 此时,整个数组作为一个组进行直接插入排序。
    3. 由于前两次排序已经将数组中的元素大致排列好了,这次排序将它们排列成完全有序的序列:0, 1, 2, 3, 4, 5, 6, 7, 8, 9

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

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

相关文章

《C++11》各种初始化方式的详细列举与对比

在 C 中&#xff0c;初始化对象的方式多种多样。随着 C 标准的演进&#xff0c;特别是 C11 的引入&#xff0c;初始化方式得到了显著的扩展和改进。本文将详细列举 C 中的各种初始化方式&#xff0c;并对它们进行对比&#xff0c;帮助开发者更好地理解和应用这些特性。 1. C98…

基于 Python Django 的西西家居全屋定制系统(源码+部署+文档)

博主介绍&#xff1a;✌程序员徐师兄、7年大厂程序员经历。全网粉丝12w、csdn博客专家、掘金/华为云/阿里云/InfoQ等平台优质作者、专注于Java技术领域和毕业项目实战✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精彩专栏推荐订阅&#x1f447;…

25考研|重邮软件工程复试攻略!

与计算机一样&#xff0c;重邮复试不合格也很有可能被淘汰&#xff01;快快认真准备起来&#xff01; 一、复试内容 1、笔试&#xff1a;分值100 2、综合面试&#xff1a;满分100 主要考核考生的综合素质和业务能力&#xff0c;由各招生学院具体组织实施&#xff0c;综合面试…

如何制作重识别数据集及如何解决all query identities do not appear in gallery的问题

如何制作重识别数据集 数据集制作链接 注意点&#xff1a; 按照上述方式制作完成数据集之后&#xff0c;分别建立3个文件夹&#xff0c;分别为train&#xff0c;test&#xff0c;query&#xff0c; 值得注意的是&#xff0c;query文件里的相机编号要进行修改&#xff0c;修改…

链地址法(哈希桶)

链地址法&#xff08;哈希桶&#xff09; 解决冲突的思路 开放定址法中所有的元素都放到哈希表⾥&#xff0c;链地址法中所有的数据不再直接存储在哈希表中&#xff0c;哈希表 中存储⼀个指针&#xff0c;没有数据映射这个位置时&#xff0c;这个指针为空&#xff0c;有多个数…

【C语言】可移植性陷阱与缺陷(七): 除法运算时发生的截断

在C语言编程中&#xff0c;除法运算可能会引发一些与可移植性相关的问题&#xff0c;特别是当涉及到整数除法时发生的截断&#xff08;truncation&#xff09;。不同平台对于整数除法的行为和处理方式可能会有所不同&#xff0c;这可能导致代码在不同编译器或硬件平台上的行为不…

了解RabbitMQ的工作原理

RabbitMQ是一个开源的消息代理系统&#xff0c;实现了高级消息队列协议&#xff08;AMQP&#xff09;。在现代分布式系统中&#xff0c;特别是在微服务架构中&#xff0c;RabbitMQ有广泛的应用。本文将详细介绍RabbitMQ的工作原理&#xff0c;并通过实践案例帮助读者理解和应用…

分布式搜索引擎之elasticsearch基本使用3

分布式搜索引擎之elasticsearch基本使用3 1.部署单点es 1.1.创建网络 因为我们还需要部署kibana容器&#xff0c;因此需要让es和kibana容器互联。这里先创建一个网络&#xff1a; docker network create es-net1.2.加载镜像 这里我们采用elasticsearch的7.12.1版本的镜像&…

【FlutterDart】 拖动改变 widget 的窗口尺寸大小GestureDetector~简单实现(10 /100)

上效果 预期的是通过拖动一条边界线改变窗口大小&#xff0c;类似vscode里拖动效果。这个是简单的拖动实现 上代码&#xff1a; import package:flutter/material.dart;class MyDraggableViewDemo extends StatelessWidget {const MyDraggableViewDemo({super.key});override…

使用Dinky快速提交Flink operator任务

官网地址&#xff1a;K8s集成 | Dinky 1.目前使用版本 Dinky1.2.0、Flink1.18.1、Flink operator0.10.0 2.制作镜像 2.1创建DockerFile ARG FLINK_VERSION1.18.1 FROM flink:${FLINK_VERSION}-scala_2.12 RUN mkdir -p /opt/flink/usrlib COPY commons-cli-1.3.1.jar …

查找路由器的管理后台ip【通用找IP】

需求&#xff1a; 刚刚搞了个【小米】路由器&#xff0c;我想进路由的管理后台&#xff0c;提示&#xff1a;安装xx的路由管家&#xff0c;我不想安装 但是无法找到这个管理后台。 而且我是用这个路由作为中继&#xff0c;那么这个路由的ip就会经常更换 尝试通过网上搜索引擎来…

【大数据】(选修)实验4 安装熟悉HBase数据库并实践

实验4 安装熟悉HBase数据库并实践 1、实验目的 (1)理解HBase在Hadoop体系结构中的角色; (2)熟练使用HBase操作常用的Shell命令; (3)熟悉HBase操作常用的Java API。 2、实验平台 操作系统:Linux Hadoop版本:2.6.0或以上版本 HBase版本:1.1.2或以上版本 JDK版…

【通识安全】煤气中毒急救的处置

1.煤气中毒的主要症状与体征一氧化碳中毒&#xff0c;其中毒症状一般分为轻、中、重三种。 (1)轻度&#xff1a;仅有头晕、头痛、眼花、心慌、胸闷、恶心等症状。如迅速打开门窗&#xff0c;或将病人移出中毒环境&#xff0c;使之吸入新鲜空气和休息&#xff0c;给些热饮料&am…

【UI自动化测试】selenium八种定位方式

&#x1f3e1;个人主页&#xff1a;謬熙&#xff0c;欢迎各位大佬到访❤️❤️❤️~ &#x1f472;个人简介&#xff1a;本人编程小白&#xff0c;正在学习互联网求职知识…… 如果您觉得本文对您有帮助的话&#xff0c;记得点赞&#x1f44d;、收藏⭐️、评论&#x1f4ac;&am…

redis各种数据类型介绍

Redis 是一种高性能的键值存储数据库&#xff0c;它支持多种数据类型&#xff0c;使得开发者可以灵活地存储和操作数据。以下是 Redis 支持的主要数据类型及其介绍&#xff1a; 1. 字符串&#xff08;String&#xff09; 字符串是 Redis 中最基本的数据类型&#xff0c;它可以存…

【Linux】Linux命令

目录 ​编辑 系统维护命令 man man&#xff1a;查看 man 手册 sudo passwd 用户名&#xff1a;修改用户密码 su&#xff1a;切换用户 echo ”输出内容“&#xff1a;向终端输出内容&#xff0c;默认换行 date查看当前系统的日期 clear&#xff1a;清屏 df -Th /df -h&…

关机重启后,GitLab服务异常

整理机房,关闭了所有主机重新上架。 上架后开机,所有主机硬件启动正常。 其中一台GitLab服务器启动正常,使用gitlab-ctl status查看服务业正常。 但使用web登陆却失败,如下图: 反复测试,发现无论使用正确密码还是错误密码都是同样的提示。很大可能是数据库的问题。 使…

【嵌入式硬件】直流电机驱动相关

项目场景&#xff1a; 驱动履带车&#xff08;双直流电机&#xff09;前进、后退、转弯 问题描述 电机驱动MOS管烧毁 电机驱动采用IR2104STRH1R403NL的H桥方案&#xff08;这是修改之后的图&#xff09; 原因分析&#xff1a; 1.主要原因是4路PWM没有限幅&#xff0c;修改…

Python编程实例-特征向量与特征值编程实现

特征向量与特征值编程实现 文章目录 特征向量与特征值编程实现1、什么是特征向量2、特征向量背后的直觉3、为什么特征向量很重要?4、如何计算特征向量?4、特征向量Python实现5、可视化特征向量6、总结线性代数是许多高级数学概念的基石,广泛应用于数据科学、机器学习、计算机…

基于Java的免税商品优选购物商城设计与实现源码(springboot+mybatis+mysql)

风定落花生&#xff0c;歌声逐流水&#xff0c;大家好我是风歌&#xff0c;混迹在java圈的辛苦码农。今天要和大家聊的是一款基于Java的免税商品优选购物商城设计与实现。项目源码以及部署相关请联系风歌&#xff0c;文末附上联系信息 。 项目简介&#xff1a; 基于Java的免税…