返回

码农如何轻松玩转排序算法?十大排序复习(上)

Android

排序算法:计算机世界中的排序魔法师

在计算机科学中,排序算法扮演着整理和组织数据的关键角色。无论是在数据库管理、数据挖掘还是人工智能中,排序算法都是不可或缺的工具。让我们一起探索十种经典的排序算法,了解它们的原理、优缺点以及在不同场景下的应用。

冒泡排序:简单粗暴的泡沫狂欢

冒泡排序是一种直观且容易理解的算法。它就像一串不断翻滚的泡沫,较小的泡沫会不断浮到顶部。算法的核心是比较相邻元素,将较小的元素移到前面。虽然简单,但冒泡排序效率较低,时间复杂度为 O(n²),这意味着随着数据量的增加,其运行时间会急剧增长。

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

选择排序:每次选出最小值

选择排序也是一种简单算法,它会找到序列中最小值,然后将其与序列开头元素交换。这个过程重复进行,直到整个序列有序。与冒泡排序类似,选择排序的效率也不高,时间复杂度同样为 O(n²)。

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

插入排序:有序序列中的逐个插入

插入排序将待排序元素逐个插入到一个已经有序的序列中。这个过程就像在一个装满球的盒子中插入一个新球,需要找到一个合适的空隙来安置新球。插入排序的时间复杂度为 O(n²),但当序列接近有序时,其效率会大大提高。

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

希尔排序:插入排序的升级版

希尔排序是对插入排序的改进版本。它将待排序序列分割成多个子序列,然后对每个子序列进行插入排序。最后再将所有子序列合并成一个有序序列。希尔排序的时间复杂度为 O(n¹³),比插入排序要快得多。

def shell_sort(arr):
    gap = len(arr) // 2
    while gap > 0:
        for i in range(gap, len(arr)):
            current_element = arr[i]
            j = i
            while j >= gap and current_element < arr[j - gap]:
                arr[j] = arr[j - gap]
                j -= gap
            arr[j] = current_element
        gap //= 2

归并排序:分而治之的排序之王

归并排序是一种分而治之的算法,将待排序序列分割成更小的子序列,对子序列分别进行排序,然后合并子序列得到最终有序序列。归并排序的时间复杂度为 O(n log n),是所有排序算法中最快的算法之一。

def merge_sort(arr):
    if len(arr) <= 1:
        return arr
    mid = len(arr) // 2
    left_half = merge_sort(arr[:mid])
    right_half = merge_sort(arr[mid:])
    return merge(left_half, right_half)

def merge(left, right):
    merged = []
    left_index = right_index = 0
    while left_index < len(left) and right_index < len(right):
        if left[left_index] <= right[right_index]:
            merged.append(left[left_index])
            left_index += 1
        else:
            merged.append(right[right_index])
            right_index += 1
    merged.extend(left[left_index:])
    merged.extend(right[right_index:])
    return merged

快速排序:速度惊人的分治算法

快速排序也是一种分而治之算法,它选择一个基准元素,将序列分割成两个子序列,一个子序列包含所有小于基准元素的元素,另一个子序列包含所有大于基准元素的元素。然后分别对两个子序列进行快速排序,最后合并两个子序列。快速排序的时间复杂度同样为 O(n 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)

堆排序:基于堆数据结构的排序

堆排序使用堆数据结构对序列进行排序。堆是一种特殊的树形结构,其中每个节点都比其子节点大。堆排序通过不断将堆顶元素与序列最后一个元素交换,然后重新构建堆,从而得到一个有序序列。堆排序的时间复杂度为 O(n log n)。

def heap_sort(arr):
    def heapify(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)
    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)

计数排序:适用于范围较小的整数

计数排序是一种非比较排序算法,适用于元素范围较小的整数序列。它通过计算每个元素出现的次数,然后根据这些计数来生成一个有序序列。计数排序的时间复杂度为 O(n + k),其中 k 是元素的范围。

def counting_sort(arr, max_value):
    n = len(arr)
    output = [0] * n
    count = [0] * (max_value + 1)
    for i in range(n):
        count[arr[i]] += 1
    for i in range(1, max_value + 1):
        count[i] += count[i - 1]
    i = n - 1
    while i >= 0:
        output[count[arr[i]] - 1] = arr[i]
        count[arr[i]] -= 1
        i -= 1
    for i in range(n):
        arr[i] = output[i]

桶排序:适用于元素范围较小的非整数

桶排序也是一种非比较排序算法,适用于元素范围较小的非整数序列。它将待排序序列分割成多个桶,然后对每个桶中的元素进行排序,最后合并所有桶中的元素得到有序序列。桶排序的时间复杂度为 O(n + k),其中 k 是元素的范围。

def bucket_sort(arr, n, max_value):
    bucket_size = max_value / n
    buckets = [[] for _ in range(n)]
    for i in range(n):
        idx = int(arr[i] / bucket_size)
        buckets[idx].append(arr[i])
    for bucket in buckets:
        bucket.sort()
    i = 0
    for bucket in buckets:
        for value in bucket:
            arr[i] = value
            i += 1

基数排序:快速排序大整数

基数排序是一种非比较排序算法,适用于大整数序列。它将元素按位进行排序,从最低位到最高位逐次进行。基数排序的时间复杂度为