返回

经典排序算法解惑:以清晰解析迎接编程挑战

见解分享

前言

排序算法,作为计算机科学的基石,在各个领域都有着广泛的应用,从日常生活中常用的数据整理,到科学研究中庞大数据集的分析,再到人工智能领域的机器学习算法,排序算法无处不在。正因如此,学习和掌握经典排序算法对于每一位对算法和数据结构感兴趣的代码人来说都是必不可少的。

本文将为您呈现经典排序算法的盛宴,从耳熟能详的冒泡排序、插入排序和选择排序,到快速排序、归并排序和堆排序,我们一一剖析它们的实现原理、优缺点以及应用场景。此外,文章的末尾还附带了几道习题,方便您巩固所学。

经典排序算法一览

冒泡排序

冒泡排序,顾名思义,就像是把气泡从水中一点点冒出来一样,通过不断比较相邻元素,将较大的元素“冒”到数组的末尾。它的实现非常简单,朴实无华,但时间复杂度却高达O(n^2),因此在实际应用中并不常见。

def bubble_sort(arr):
    """
    冒泡排序算法

    参数:
    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

插入排序

插入排序,就像是在整理扑克牌一样,将一张张牌按照顺序插入到已经排好序的牌堆中。它的实现也相对简单,但时间复杂度为O(n^2),同样不适用于大型数据集。

def insertion_sort(arr):
    """
    插入排序算法

    参数:
    arr: 要排序的数组

    返回:
    已排序的数组
    """

    n = len(arr)
    for i in range(1, n):
        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

选择排序

选择排序,就像是在一堆杂乱无章的物品中,不断挑选出最小的一个,然后将其放到正确的位置。它的实现也很简单,时间复杂度为O(n^2),同样不适合处理大型数据集。

def selection_sort(arr):
    """
    选择排序算法

    参数:
    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

快速排序

快速排序,又称分治排序,它是所有排序算法中最著名的之一,也是实际应用中最常用的之一。它的时间复杂度为O(n log n),在平均情况下表现优异,但在最坏情况下退化到O(n^2)。

def quick_sort(arr):
    """
    快速排序算法

    参数:
    arr: 要排序的数组

    返回:
    已排序的数组
    """

    n = len(arr)
    if n <= 1:
        return arr
    pivot = arr[n//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)

归并排序

归并排序,顾名思义,就是将一个数组分成两半,然后分别对这两半进行排序,最后再将两半合并成一个有序的数组。它的时间复杂度为O(n log n),在所有排序算法中属于性能最优的之一。

def merge_sort(arr):
    """
    归并排序算法

    参数:
    arr: 要排序的数组

    返回:
    已排序的数组
    """

    n = len(arr)
    if n <= 1:
        return arr
    mid = n // 2
    left = merge_sort(arr[:mid])
    right = merge_sort(arr[mid:])
    return merge(left, right)

def merge(left, right):
    """
    合并两个有序数组

    参数:
    left: 第一个有序数组
    right: 第二个有序数组

    返回:
    合并后的有序数组
    """

    i = 0
    j = 0
    merged = []
    while i < len(left) and j < len(right):
        if left[i] < right[j]:
            merged.append(left[i])
            i += 1
        else:
            merged.append(right[j])
            j += 1
    while i < len(left):
        merged.append(left[i])
        i += 1
    while j < len(right):
        merged.append(right[j])
        j += 1
    return merged

堆排序

堆排序,又称树排序,它是利用堆的数据结构来实现排序的算法。堆排序的时间复杂度为O(n log n),在所有排序算法中属于性能最优的之一。

def heap_sort(arr):
    """
    堆排序算法

    参数:
    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

def heapify(arr, n, i):
    """
    构建最大堆

    参数:
    arr: 要构建堆的数组
    n: 堆的大小
    i: 当前节点的索引
    """

    largest = i
    left = 2 * i + 1
    right = 2 * i + 2

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

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

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

结语

以上就是经典排序算法的简要介绍,希望对您有所帮助。