踏踏实实地打好算法基础(1)— 冒泡排序和选择排序算法

357 阅读3分钟

排序算法是其他算法基础,很多算法都是基于排好序的数组进行的。在现实生活中很多情况下将一些数据从小到大或者从大到小的顺序进行排列。对于排序好的序列来说,查找最大值、最小值、遍历、计算和求解等各种操作十分方便

排序基本概念

排序

将一组数据按照一定规则来进行排列,基本的排序对象是整数,而基本排序规则包括从小到大排序和从大到小排序。

最基本排序的算法

  • 交换排序算法
  • 选择排序算法
  • 插入排序算法
  • 合并排序算法
  • 多路归并排序算法

这里多路归并排序算法将文件划分为几个能够读入内存的小部分,然后分别读入进行排序,经过多次处理即完成大文件的排序。

截屏2021-09-09上午6.50.39.png

排序算法效率

算法名称平均速度最慢速度
冒泡排序O(n2)O(n^2)O(n2)O(n^2)
快速排序O(nlogn)O(n \log n)O(n2)O(n^2)
选择排序O(n2)O(n^2)O(n2)O(n^2)
堆排序O(nlogn)O(n \log n)O(nlogn)O(n \log n)
插入排序O(n2)O(n^2)O(n2)O(n^2)
shell 排序O(n3/2)O(n^{3/2})O(n2)O(n^2)
合并排序O(nlogn)O(n \log n)O(nlogn)O(n \log n)

选择排序(selection sort)

排序算法比较容易理解,即使没有接触过算法,如果让你给出一个排序的方案,其实你给出的方案可能就是今天第一个要介绍的选择排序

选择排序(Selection sort)是一种简单直观的排序算法。 工作原理是

  • 第一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置
  • 然后再从剩余的未排序元素中寻找到最小(大)元素,然后放到已排序的序列的末尾
  • 以此类推,直到全部待排序的数据元素的个数为零

截屏2021-09-08下午2.06.02.png

  • 首先在初始化 i 和 j 为 0,这是当前最小值为 5
  • 将当前值指针指向下一个位置然后对比当前值和当前最小值,因为 2 小于 5(当前最小值)
  • 然后继续向前移动当前值指针到下一个位置 3 ,对比当前值和当前最小值 因为 3 大于 2(当前最小值)这是并不会将当前最小值指针向前移动

截屏2021-09-08下午2.06.14.png

  • 当当前值继续向前移动到最后一个位置 1
  • 对比当前值 1 和当前最小值 2 并将当前最小值的指针移动到 1 位置
  • 由于当前值已经来到了数组末尾,这是将第一个位置值和当前最小值进行交换(step 6)

截屏2021-09-08下午2.06.24.png

  • 上一次外层的迭代完成将数组第一个值替换为最小值,接下来进入下一次迭代
  • 在这次迭代就是将第二个替换为剩余 n - 1(n 数组长度)的最小值
  • 重复上面步骤知道迭代至最后一个值
class Solution:
    def selectionSortArray(self, nums:List[int]) -> List[int]:
        n = len(nums) - 1
        for i in range(n):
            min_index = i
            for j in range(i + 1, n):
                if (nums[j] <= nums[min_index]):
                    min_index = j
                temp = nums[i]
                nums[i] = nums[min_index]
                nums[min_index] = temp
        return nums
  • 数组序号是从 0 开始到 n - 1 一共 n 元素
  • 第一层循环从 0 到 n - 1 每一个元素,每一次循环
  • 第二层循环是重当前已经排好序位置

有关时间复杂度

当 i = 0 时候 j 循环 n - 1,当 i = 1 时候 j 需要循环 n - 1 - 1, 当 i = n - 2 时,j = 1

i=0n1=12(n2n)\sum_{i=0}^{n-1} = \frac{1}{2}(n^2 - n)

冒泡排序(bubble sort)

冒泡排序是所有排序算法中最基础,最简单排序算法,随着这个算法效率比较低,但是可以快速编写,在排序元素比较少时比较管用。

冒泡排序算法流程

  • 对数组中的各数据,依次比较相邻的两个元素的大小
  • 如果前面的数据大于后面的数据,就交换这两个数据。经过第一轮的多次比较排序后,便可将最小的数据排好
  • 再用同样的方法把剩下的数据逐个进行比较,最后便可按照从小到大的顺序排好数组各数据

截屏2021-09-08下午2.25.15.png

这里有 4 个元素分别是 5, 2, 3, 1 我们想把这些从小到大排列出来,首先我们看第一对数 5 和 2 因为排序从小到大所以,现在排序不正确,所以需要将 5 和 2 调换位置,接下来继续向前移动,5 和 3 进行对比,他们之间关系也是不正确,需要调换位置,接下里继续向前移动并对比两个相邻元素,根据需要调整位置,直到移动到数组末尾,就完成一次迭代,在这一次迭代过程中 5 一直向前移动到数组的末尾。如果将数组旋转 90 就感觉 5 像水中气泡一直向上升的感觉,这也是冒泡排序名字的由来。

class Solution:
    def bubbleSortArray(self, nums):
        n = len(nums)
        for i in range(n):
            for j in range(0, n-i-1):
                if nums[j] > nums[j+1]:
                    nums[j],nums[j+1] = nums[j+1],nums[j]
        return nums