Python编程实现各类排序法:插入排序、交换排序、选择排序、归并排序、基数排序

本文详细介绍了几种常见的IT排序算法,包括直接插入排序、折半插入排序、希尔排序、冒泡排序、快速排序、简单选择排序、堆排序、归并排序和基数排序,分析了它们的时间复杂度和空间复杂度,并提供了相应的代码实现。
摘要由CSDN通过智能技术生成

快希选堆不稳定

一、插入排序

1.直接插入排序

是将待排序序列分为已排序区间和未排序区间,每次从未排序区间取出一个元素,在已排序区间中找到合适的位置插入,使得已排序区间仍然保持有序

时间复杂度:O(n)、O(n²)、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

2.折半插入排序

将待排序数组分为已排序区间和未排序区间,每次从未排序区间取出一个元素,在已排序区间中使用二分查找定位其插入位置,并将其插入到相应位置,最终使整个数组排序完成

时间复杂度:O(nlog2n)、O(n²)
空间复杂度:O(1)
稳定

def binary_insertion_sort(arr):
    n = len(arr)
    for i in range(1, n):
        left, right = 0, i - 1
        while left <= right:
            mid = (left + right) // 2
            if arr[i] < arr[mid]:
                right = mid - 1
            else:
                left = mid + 1
        for j in range(i - 1, left - 1, -1):
            arr[j + 1] = arr[j]
        arr[left] = arr[i]
    return arr

二分查找

# 二分查找
def binary_search(arr, target):
    left, right = 0, len(arr) - 1
    while left <= right:
        mid = (left + right) // 2

        if arr[mid] == target:
            return mid
        elif arr[mid] < target:
            left = mid + 1
        else:
            right = mid - 1

    return -1

3.希尔排序

先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行一次直接插入排序


具体步骤如下:
选择一个增量序列t1,t2,…,tk,其中ti>tj,tk=1;
按增量序列个数k,对序列进行k趟排序;
每趟排序,根据对应的增量ti,将待排序列分割成若干长度为m的子序列,分别对各子表进行直接插入排序。仅在增量因子为1时,整个序列作为一个表来处理,表长度即为整个序列的长度。

空间复杂度:O(1)
不稳定

def shell_sort(arr):
    n = len(arr)
    d = n // 2   # 间隔
    while d >0:
        for i in range(d, n):
            temp =arr[i]
            j = i
            while j>= d and arr[j-d] > temp:
                arr[j] = arr[j-d]
                j -= d
            arr[j] = temp
        d //=2
    return arr

二、交换排序

1.冒泡排序

从后往前两两比较相邻元素的值,若为逆序,则交换它们,直至序列比较完。

时间复杂度:O(n)、O(n²)、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.快速排序

通过一趟排序将待排序的数据分割成独立的两部分,其中一部分的所有数据都要比另一部分的所有数据小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列

时间复杂度:O(nlog2n)、O(nlog2n)、O(n²)
空间复杂度:O(log2n)
不稳定

def partition(arr, low, high):
    pivot = arr[low]  # 基准元素
    while low < high:
        while low < high and arr[high] >= pivot:
            high -= 1
        arr[low] = arr[high]
        while low < high and arr[low] <= pivot:
            low += 1
        arr[high] = arr[low]
    arr[low] = pivot
    return low


def quick_sort(arr, low, high):
    if low < high:
        pivot_i = partition(arr, low, high)
        quick_sort(arr, low, pivot_i - 1)
        quick_sort(arr, pivot_i + 1, high)
    return arr

三、选择排序

1.简单选择排序

是每一次从待排序的数据元素种选出最小(/最大)的一个元素,存放在序列的起始位置,然后再从剩余未排序的元素中继续寻找最小(/最大)的元素,以此类推,直至所有元素排序完成

时间复杂度:O(n²)
空间复杂度:O(1)
不稳定

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

2.堆排序

将待排序的元素构建成一个大顶堆(或小顶堆),然后每次将堆顶元素与堆尾元素交换,并调整堆使之满足堆的性质,重复这个过程直到整个数组有序

时间复杂度:O(nlog2n)
空间复杂度:O(1)
不稳定

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)


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[0], arr[i] = arr[i], arr[0]
        heapify(arr, i, 0)

    return arr

四、归并排序

将待排序数组分成两个子数组分别对这两个子数组进行排序,最后将已排序的子数组合并为一个有序的数组

时间复杂度:O(nlog2n)
空间复杂度:O(n)
稳定


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

        merge_sort(left_arr)
        merge_sort(right_arr)

        # 合并
        i = j = k = 0
        while i < len(left_arr) and j < len(right_arr):
            if left_arr[i] < right_arr[j]:
                arr[k] = left_arr[i]
                i += 1
            else:
                arr[k] = right_arr[j]
                j += 1
            k += 1

        while i < len(left_arr):
            arr[k] = left_arr[i]
            i += 1
            k += 1
        while j < len(right_arr):
            arr[k] = right_arr[j]
            j += 1
            k += 1

    return arr

五、基数排序

是一种非比较型的排序算法,它将整数按位数切割成不同的数字,然后按每个位数分别比较。基数排序有两种方法:最低位优先LSD(Least Significant Digit first)和最高位优先MSD(Most Significant Digit first)。在实现过程中,LSD 的基数排序可以使用计数排序作为子排序。


具体步骤如下:
从最低位开始,依次对每一位上的数字进行稳定排序(通常使用计数排序)。
对于每一位上的排序完成后,移动到下一位,直至最高位排序完成。

时间复杂度:O(d(n+r))
空间复杂度:O(r )
稳定

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
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Taverry

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值