Python学习笔记11-算法:排序算法

排序算法用于将一组数据按某种顺序排列。排序是计算机科学中一个基本的操作,广泛应用于各种应用场景。下面是一些常见的排序算法,包括它们的基本描述、时间复杂度和空间复杂度。

1. 冒泡排序(Bubble Sort)

描述:冒泡排序通过重复交换相邻的未排序元素,将最大(或最小)的元素“冒泡”到序列的一端。

时间复杂度

  • 最坏情况:O(n^2)
  • 平均情况:O(n^2)
  • 最好情况:O(n), 当数组已经排序时(优化版)

空间复杂度O(1)

代码示例

def bubble_sort(arr):
    n = len(arr)
    for i in range(n):
        for j in range(0, n-i-1):
            if arr[j] > arr[j+1]:
                arr[j], arr[j+1] = arr[j+1], arr[j]
    return arr

2. 选择排序(Selection Sort)

描述:选择排序通过不断选择未排序部分中的最小(或最大)元素并放到已排序部分的末尾。

时间复杂度

  • 最坏情况:O(n^2)
  • 平均情况:O(n^2)
  • 最好情况:O(n^2)

空间复杂度O(1)

代码示例

def selection_sort(arr):
    n = len(arr)
    for i in range(n):
        min_idx = i
        for j in range(i+1, n):
            if arr[j] < arr[min_idx]:
                min_idx = j
        arr[i], arr[min_idx] = arr[min_idx], arr[i]
    return arr

3. 插入排序(Insertion Sort)

描述:插入排序通过将每个元素插入到前面已排序的部分中,逐步构建有序序列。

时间复杂度

  • 最坏情况:O(n^2)
  • 平均情况:O(n^2)
  • 最好情况:O(n), 当数组已经排序时

空间复杂度O(1)

代码示例

def insertion_sort(arr):
    for i in range(1, len(arr)):
        key = arr[i]
        j = i - 1
        while j >= 0 and key < arr[j]:
            arr[j + 1] = arr[j]
            j -= 1
        arr[j + 1] = key
    return arr

4. 合并排序(Merge Sort)

描述:合并排序是一个分治算法,递归地将数组分成两半,分别排序后合并。

时间复杂度

  • 最坏情况:O(n log n)
  • 平均情况:O(n log n)
  • 最好情况:O(n log n)

空间复杂度O(n)

代码示例

def merge_sort(arr):
    if len(arr) > 1:
        mid = len(arr) // 2
        L = arr[:mid]
        R = arr[mid:]

        merge_sort(L)
        merge_sort(R)

        i = j = k = 0
        while i < len(L) and j < len(R):
            if L[i] < R[j]:
                arr[k] = L[i]
                i += 1
            else:
                arr[k] = R[j]
                j += 1
            k += 1

        while i < len(L):
            arr[k] = L[i]
            i += 1
            k += 1

        while j < len(R):
            arr[k] = R[j]
            j += 1
            k += 1
    return arr

5. 快速排序(Quick Sort)

描述:快速排序使用分治策略,选择一个“基准”元素,将数组分成两部分,使得一部分小于基准,另一部分大于基准,然后递归地排序这两部分。

时间复杂度

  • 最坏情况:O(n^2),当每次选择的基准是最小或最大元素时
  • 平均情况:O(n log n)
  • 最好情况:O(n log n)

空间复杂度O(log n)(递归调用栈)

代码示例

def quick_sort(arr):
    if len(arr) <= 1:
        return arr
    pivot = arr[len(arr) // 2]
    left = [x for x in arr if x < pivot]
    middle = [x for x in arr if x == pivot]
    right = [x for x in arr if x > pivot]
    return quick_sort(left) + middle + quick_sort(right)

6. 堆排序(Heap Sort)

描述:堆排序使用堆数据结构,通过构建最大堆或最小堆来排序数组。

时间复杂度

  • 最坏情况:O(n log n)
  • 平均情况:O(n log n)
  • 最好情况:O(n log n)

空间复杂度O(1)

代码示例

def heapify(arr, n, i):
    largest = i
    l = 2 * i + 1
    r = 2 * i + 2

    if l < n and arr[l] > arr[largest]:
        largest = l

    if r < n and arr[r] > arr[largest]:
        largest = r

    if largest != i:
        arr[i], arr[largest] = arr[largest], arr[i]
        heapify(arr, n, largest)

def heap_sort(arr):
    n = len(arr)
    for i in range(n // 2 - 1, -1, -1):
        heapify(arr, n, i)

    for i in range(n-1, 0, -1):
        arr[i], arr[0] = arr[0], arr[i]
        heapify(arr, i, 0)
    return arr

7. 基数排序(Radix Sort)

描述:基数排序是一种非比较排序算法,通过对每一位数字进行排序来实现。

时间复杂度

  • 最坏情况:O(n * k),其中k是数字的位数
  • 平均情况:O(n * k)
  • 最好情况:O(n * k)

空间复杂度O(n + k)

代码示例

def counting_sort(arr, exp):
    n = len(arr)
    output = [0] * n
    count = [0] * 10

    for i in range(n):
        index = arr[i] // exp
        count[index % 10] += 1

    for i in range(1, 10):
        count[i] += count[i - 1]

    i = n - 1
    while i >= 0:
        index = arr[i] // exp
        output[count[index % 10] - 1] = arr[i]
        count[index % 10] -= 1
        i -= 1

    for i in range(n):
        arr[i] = output[i]

def radix_sort(arr):
    max_num = max(arr)
    exp = 1
    while max_num // exp > 0:
        counting_sort(arr, exp)
        exp *= 10
    return arr

总结

  • 简单排序(如冒泡、选择、插入排序)适用于小规模数据或教学目的。
  • 分治排序(如合并排序、快速排序)适用于中到大规模数据。
  • 堆排序基数排序适用于特定场景,基数排序通常用于处理整数数据。

不同的排序算法有不同的优缺点,选择合适的排序算法可以提高程序的效率和性能。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值