【Python】用Python实现几种简单的排序

本章节实现的算法功能主要借鉴参考于
微信公众号:裸睡的猪
微信号:IT–Pig
感兴趣的朋友可以关注…(我也是他的小粉丝…)

首先用一张图了解下各排序方法的时间复杂度、空间复杂度及其稳定性:
在这里插入图片描述

一、冒泡排序

冒泡排序(Bubble Sort)的原理是通过依次比较两个相邻的元素,将较大的值向后移动,最终完成排序。

1. 过程图解

在这里插入图片描述

2. 算法思想

  1. 首先第一个元素和第二个元素开始比较,如果第一个元素比第二个大,则交换位置,以此类推…
  2. 经过一轮比较,最大的元素将排在最后一个位置,重复1中的操作,第二大的元素会排在倒数第二的位置,第三大的元素则会排在倒数第三个位置
  3. 以此类推,我们只要重复n-1同样的操作即可完成排序。

3. 代码实现

def bubble_sort(arr):
    """冒泡排序"""
    # 第一层表示循环层数
    for i in range(len(arr) - 1):
        # 第二层表示具体比较那两个元素
        for j in range(len(arr) - 1 - i):
            if arr[j] > arr[j + 1]:
                # 如果前面的大于后面的,则交换位置
                arr[j], arr[j + 1] = arr[j + 1], arr[j]
    return arr

二、选择排序

选择排序(Selection sort)的原理是每一次从需要排序的数据中选出最小或最大的元素,并将它放在序列的第一个位置。

1. 过程图解

在这里插入图片描述

2. 算法思想

  1. 首先我们将第一个元素设置为需要比较的元素,然后依次将后面的元素与它进行比较,如果比较的所有元素有比它小的元素,则交换位置。
  2. 重复1中的操作,第二位置应该放第二小的元素,我们找到第二小的元素与第二个位置的元素进行位置交换,以此类推,找出每个位置的最小元素,完成排序。

3. 代码实现

def selection_sort(arr):
    """选择排序"""
    # 第一层表示循环的次数
    for i in range(len(arr) - 1):
        # 将起始元素设为最小值
        min_index = i
        # 第二层表示最小元素和后面的元素逐个比较
        for j in range(i + 1, len(arr)):
            if arr[j] < arr[min_index]:
                # 如果当前元素比最小值小,则把当前元素下标设置为最小值下标
                min_index = j
        # 查找一遍后,将最小值与初始元素交换位置
        arr[min_index], arr[i] = arr[i], arr[min_index]
    return arr

三、插入排序

插入排序(Insertion-Sort)原理是构建有序序列,对于未排序的序列,在已排好的序列中从后向前扫描,找到相应位置并插入,以此完成排序。

1. 过程图解

在这里插入图片描述

2. 算法思想

  1. 从所要比较的第二个元素开始和前面的元素进行比较,如果前面的元素比它大,则当前元素前移,直至找到比它小或等于它的元素停止前移
  2. 依次选择到最后一个元素,完成所有排序

3. 代码实现

def insertion_sort(arr):
    """插入排序"""
    # 第一层表示循环插入的次数
    for i in range(1, len(arr)):
        # 设置当前需要插入的元素
        element = arr[i]
        # 与当前元素进行比较的比较元素
        pre_index = i - 1
        while pre_index >= 0 and arr[pre_index] > element:
            # 当比较元素大于当前元素,交换位置,后移比较元素
            arr[pre_index + 1] = arr[pre_index]
            # 向前选择下一个比较元素
            pre_index -= 1
        # 当比较元素小于当前元素,则将当前元素插在其后面
        arr[pre_index + 1] = element
    return arr

四、希尔排序

希尔排序(Shell’s Sort)是插入排序的一种,是直接插入排序算法的一种更高效的改进版本,它与插入排序的不同之处在于,它会优先比较距离较远的元素。

1. 过程图解

在这里插入图片描述

2. 算法思想

  1. 设置一个增量(间隔)值
  2. 对元素进行和增量元素(这两个元素在一个纵列)作比较,例如增量值为7,那么就对0,7,14…位置上的元素进行比较排序
  3. 当第一组比较完后,比较第二组,即1,8,15…
  4. 所有元素排完序后,缩小增量(间隔)值(缩小为原增量值的一半),重复上述操作
  5. 当增量值为1时,数列基本排好序,最后一遍普通插入即可

       已知的最增量式是由 Sedgewick 提出的 (1, 5, 19, 41, 109,…), 该步长的项来自 9 4^i - 9 2^i +1 和 4^i - 3 2^i + 1
这两个算式。这项研究也表明比较在希尔排序中是最主要的操作,而不是交换。 用这样增量式的希尔排序插入排序堆排序都要快,甚至在小数组中比快速排序还快,但是在涉及大量数据时希尔排序还是比快速排序慢。

3. 代码实现

def shell_sort(arr):
    """希尔排序"""
    # 取整计算增量(间隔)值
    gap = len(arr) // 2
    while gap > 0:
        # 从增量值开始遍历比较
        for i in range(gap, len(arr)):
            j = i
            element = arr[i]
            # 元素与其他同列的前面每个元素比较,如果比前面小则互换
            while j - gap > 0 and element < arr[j - gap]:
                arr[j] = arr[j - gap]
                arr[j - gap] = element
            #     j -= gap
            # arr[j] = element
        # 缩小增量(间隔)值
        gap //= 2
    return arr

五、归并排序

归并排序(MERGE-SORT)主要采用分治法(Divide and Conquer),归并排序适用于子序列有序的数据排序。

1. 过程图解

在这里插入图片描述

2. 算法思想

分治法(Divide-and-Conquer):将原问题划分成 n 个规模较小而结构与原问题相似的子问题;递归地解决这些问题,然后再合并其结果,就得到原问题的解。

  1. 使用递归将原数列采用二分法分成多个子数列
  2. 将两个子序列合并并返回
  3. 将所有子序列按2步骤合并并完成排序

3. 代码实现

def merge_sort(arr):
    """归并排序"""
    if len(arr) == 1:
        return arr
    # 使用二分法将数列分为两个
    mid = len(arr) // 2
    left = arr[:mid]
    right = arr[mid:]
    # 使用递归运算
    return marge(merge_sort(left), merge_sort(right))


def marge(left, right):
    """排序合并两个数列"""
    result = []
    # 两个数列都有值
    while len(left) > 0 and len(right) > 0:
        # 左右两个数列第一个最小放前面
        if left[0] < right[0]:
            result.append(left.pop(0))
        else:
            result.append(right.pop(0))
    # 只有一个数列中还有值,直接添加
    result += left
    result += right
    return result

六、快速排序

快排的实现方式多种多样,最简单易懂的是分治+迭代

1. 过程图解

在这里插入图片描述
一行代码实现快排:

quick_sort = lambda array: array if len(array) <= 1 else quick_sort([item for item in array[1:] if item <= array[0]]) + [array[0]] + quick_sort([item for item in array[1:] if item > array[0]])

2. 算法思想

  1. 在数列之中,选择一个元素作为”基准”(pivot),或者叫比较值。
  2. 数列中所有元素都和这个基准值进行比较,如果比基准值小就移到基准值的左边,如果比基准值大就移到基准值的右边
  3. 以基准值左右两边的子列作为新数列,不断重复第一步和第二步,直到所有子集只剩下一个元素为止。

      举个例子,假设我现在有一个数列需要使用快排来排序:{3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48},我们来看看使用快排的详细步骤:

  1. 选取中间的26作为基准值(基准值可以随便选)
  2. 数列从第一个元素3开始和基准值26进行比较,小于基准值,那么将它放入左边的分区中,第二个元素44比基准值26大,把它放入右边的分区中,依次类推就得到下图中的第二列。
  3. 然后依次对左右两个分区进行再分区,得到下图中的第三列,依次往下,直到最后只有一个元素
  4. 分解完成再一层一层返回,返回规则是:左边分区+基准值+右边分区

3. 代码实现

def quick_sort(arr):
    """快速排序"""
    if len(arr) < 2:
        return arr
    # 选取基准,任意挑选,这里选择中间的数
    mid = arr[len(arr) // 2]
    # 定义基准左右两侧数列
    left, right = [], []
    # 从原始数据中移除基准数值
    arr.remove(mid)
    for element in arr:
        # 大于等于基准值放右边,小于放左边
        if element >= mid:
            right.append(element)
        else:
            left.append(element)
    # 采用迭代的方式进行比较
    return quick_sort(left) + [mid] + quick_sort(right)

      最后大家如果感兴趣,想了解具体文章、代码和各个排序算法的性能比较可以关注
      微信公众号:裸睡的猪
      他的公众号文章链接:排序汇总

      也可以移步我的GitHub
      MangoloD

  • 6
    点赞
  • 27
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值