数据结构与算法-Python实现(四)排序算法

在这里插入图片描述

一、前言

  • 今天介绍常见的几种排序算法使用 Python 实现和复杂度f分析:冒泡排序、选择排序、插入排序、谢尔排序、归并排序。

二、冒泡排序

  1. 排序思路:算法思路在于对无序表进行多趟比较交换,每趟包括了多次相邻元素的两两比较,并将逆序的数据互换位置,最终能将本趟最大项就位。每趟的过程像 “气泡” 在水中不断上浮到水面的过程,所以叫冒泡排序。

  2. 代码实现
    在这里插入图片描述

  3. 算法过程
    第一趟比较交换时,会进行 n-1 次相邻数据的比较,一旦经过最大项,则最大项会被一路交换到最后一项,依次类推。

  4. 算法分析
    无序表对初始数据项的排列状况对冒泡排序没有影响 算法总过程需要 n-1 趟,随着趟数的增加每趟数组中的最大项就位,比对次数逐步从 n-1 减少到 1 并包括可能发生的数据项的交换。比对次数是 1~n-1 的累加。对比的时间复杂度为 O(n^2) 交换次数时间复杂度也为 O(n^2) 最好的情况是数组已经排好序,交换次数为 0 最差的情况每次对比都需要交换,交换的次数等于对比的次数,平均情况就是最差情况的一半。

  5. 算法总结:冒泡排序是一个时间效率比较差的排序算法,原因是每个数据项在找到对应的位置之前,必须要经过多次对比和交换,其中大部分操作都是无效的。优势的地方在于不需要其它额外的存储空间开销。

三、选择排序

  1. 排序思路:选择排序对冒泡排序进行了改进,保留了其基本的多趟对比的思路,每趟对比都使最大项就位。但选择排序对交换的过程进行了优化,相比冒泡排序的对次交换,选择排序每一趟对比只需要一次交换,只会记录最大项所在的位置,最后再跟本趟的最后一项交换。
  2. 代码实现
    在这里插入图片描述
  3. 算法分析
    相比于冒泡排序对比次数不变,时间复杂度依然为 O(n^2),交换次数时间复杂度减少为 O(n)
  4. 算法总结
    选择排序相比于冒泡排序对数据项交换的环节进行了优化,选择排序稍优于冒泡排序

四、插入排序

  1. 排序思路:插入排序维持一个已经有序的子列表,其位置始终在列表前部,然后逐步扩大这个子列表直到全表。像是在整理扑克牌。
  2. 代码实现
    在这里插入图片描述
  3. 算法过程
    第一趟排序,子列表仅包含第一数据项,将第二个数据项作为 “新项” 进行对比然后插入到子列表合适到位置中,此时已经排好序到列表就包含了两个数据项,第二趟排序,子列表包含两个数据项,将第三个数据和第二个数据进行插入对比,第三个数项也 “加入” 子列表。经过 n-1 次对比插入,子列表扩展到全表,排序完成。
  4. 算法分析
    插入排序的比较主要来寻找 “新项”插入位置 最差的情况是每趟都与子列表中所有项进行对比,总比对次数与冒泡排序相同,数量级为 O(n^2) 最好情况列表已经排好序的时候,每趟仅需 1 次对比,总次数为 O(n)
  5. 算法总结:
    无序表的初始数据项的排列状况对插入排序有一定影响 列表越接近有序,插入排序的次数越少,相比于冒泡和选择排序,插入排序的性能相对会好一些。

五、谢尔排序

  1. 排序思路:谢尔排序以插入排序为基础,对无序表进行 “间隔” 划分子列表,每个子列表都执行插入排序,随着子列表的数量越来越少,无序表的整体越来越接近有序,从而减少整体排序的对比次数。
  2. 代码实现
    在这里插入图片描述
  3. 算法过程
    按间隔划分子列表,当间隔为 1 时就是一个标准的插入排序,但由于前面几趟已经将列表处理为接近有序的状态,最后一趟所以只需要几次移动即可完成排序。
  4. 算法分析
    谢尔排序是以插入排序为基础,每趟都使得列表更加有序,过程会减少很多原先需要的 “无效” 比对,谢尔排序的复杂度介于O(n)O(n^2) 之间,具体约为O(n^3/2)
  5. 算法总结
    谢尔排序是以插入排序为基础,可能并不会比插入排序好,但是可以减少许多无效的对比。

猜你喜欢

转载自blog.csdn.net/qq_42768234/article/details/106280285