基于python实现十大排序算法(保证能看懂)

一. 冒泡排序(Bubble Sort)

def bubble_sort(arr):
    for i in range(len(arr)-1):         # 循环第 i 趟
        for j in range(len(arr)-i-1):   # j 为下标
            if arr[j] > arr[j+1]:       # 如果这个数大于后面的数就交换两者的位置
                arr[j], arr[j+1] = arr[j+1], arr[j]
        print(arr)                      # 每一趟比较完了就打印一次


arr = [3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48]
bubble_sort(arr)

二、选择排序(Selection Sort)

def selection_sort(arr):
    for i in range(len(arr)-1):          # 循环第 i 趟
        min_index = i                    # 记录最小数的下标
        for j in range(i+1, len(arr)):   # j 为下标
            if arr[j] < arr[min_index]:  # 如果这个数小于记录的最小数,则更新最小数的下标
                min_index = j
        arr[i], arr[min_index] = arr[min_index], arr[i]  # 将 i 位置的数(已排序序列的末尾的数)和最小数进行交换
        print(arr)                       # 每一趟比较完了就打印一次


arr = [3, 44, 38, 5, 47, 15, 36, 26, 27, 2, 46, 4, 19, 50, 48]
selection_sort(arr)

三、插入排序(Insertion Sort)

def insertion_sort(arr):
    for i in range(1, len(arr)):    # 将 i 看做摸到的牌的下标
        tmp = arr[i]                # 将摸到的牌储存到 tmp
        j = i-1                     # 将 j 看做手里的牌的下标
        while j >= 0 and arr[j] > tmp:  # 如果手里的牌大于摸到的牌
            arr[j+1] = arr[j]       # 将手里的牌往右移一个位置(将手里的牌赋值给下一个位置)
            j -= 1                  # 将手里的牌的下标减 1,再次准备与摸到的牌进行比较
        arr[j+1] = tmp              # 将摸到的牌插入到 j+1 位置
        print(arr)                  # 每一趟比较完了就打印一次


arr = [0, 9, 8, 7, 1, 2, 3, 4, 5, 6]
insertion_sort(arr)

四、希尔排序(Shell Sort)

##第一种
def insertion_sort_gap(arr, gap):     # 将 gap 看做隔 gap 个距离摸一张牌,而不是依次按照顺序摸牌
    for i in range(gap, len(arr)):    # 将 i 看做摸到的牌的下标
        tmp = arr[i]                  # 将摸到的牌储存到 tmp
        j = i-gap                     # 将 j 看做手里的牌的下标
        while j >= 0 and arr[j] > tmp:  # 如果手里的牌大于摸到的牌
            arr[j+gap] = arr[j]         # 将手里的牌往右移一个位置(将手里的牌赋值给下一个位置)
            j -= gap                    # 将手里的牌的下标减 gap,再次准备与摸到的牌进行比较
        arr[j+gap] = tmp                # 将摸到的牌插入到 j+gap 位置


def shell_sort(arr):
    d = len(arr) // 2                   # 第一次分组
    while d >= 1:
        insertion_sort_gap(arr, d)      # 调用插入排序
        print(arr)                      # 每一轮排序后打印一次
        d //= 2                         # 整除 2 后再次分组


arr = [5, 7, 4, 6, 3, 1, 2, 9, 8]
shell_sort(arr)
#第二种
def shell_sort(arr):
    d = len(arr) // 2                   # 第一次分组
    while d >= 1:                       # 将 d 看做隔 d 个距离摸一张牌,而不是依次按照顺序摸牌
        for i in range(d, len(arr)):    # 将 i 看做摸到的牌的下标
            tmp = arr[i]                # 将摸到的牌储存到 tmp
            j = i - d                   # 将 j 看做手里的牌的下标
            while j >= 0 and arr[j] > tmp:   # 如果手里的牌大于摸到的牌
                arr[j + d] = arr[j]          # 将手里的牌往右移一个位置(将手里的牌赋值给下一个位置)
                j -= d                       # 将手里的牌的下标减 d,再次准备与摸到的牌进行比较
            arr[j + d] = tmp                 # 将摸到的牌插入到 j+d 位置
        print(arr)                           # 每一轮排序后打印一次
        d //= 2                              # 整除 2 后再次分组


arr = [5, 7, 4, 6, 3, 1, 2, 9, 8]
shell_sort(arr)

五、归并排序(Merge Sort)

def merge(arr, low, mid, high):
    # low 和 high 为整个数组的第一个和最后一个位置索引,mid 为中间位置索引
    # i 和 j 为指针,最初位置分别为两个有序序列的起始位置
    # ltmp 用来存放合并后的序列
    i = low
    j = mid+1
    ltmp = []
    while i <= mid and j <= high:  # 只要左右两边都有数
        if arr[i] < arr[j]:        # 当左边的数小于右边的数
            ltmp.append(arr[i])    # 将左边的数存入 ltmp
            i += 1                 # 左边的指针往右移一位
        else:                      # 当右边的数小于左边的数
            ltmp.append(arr[j])    # 将右边的数存入 ltmp
            j += 1                 # 右边的指针往右移一位
    # 上面的 while 语句执行完后,左边或者右边没有数了
    while i <= mid:                # 当左边还有数的时候
        ltmp.append(arr[i])        # 将左边剩下的数全部存入 ltmp
        i += 1
    while j <= high:               # 当右边还有数的时候
        ltmp.append(arr[j])        # 将右边剩下的数全部存入 ltmp
        j += 1
    arr[low:high+1] = ltmp         # 将排序后的数组写回原数组


def merge_sort(arr, low, high):       # low 和 high 为整个数组的第一个和最后一个位置索引
    if low < high:                    # 至少有两个元素
        mid = (low + high) // 2
        merge_sort(arr, low, mid)     # 把左边递归分解
        merge_sort(arr, mid+1, high)  # 把右边递归分解
        merge(arr, low, mid, high)    # 做归并
        print(arr)                    # 每一次归并打印一次


arr = [7, 1, 3, 2, 6, 9, 4]
merge_sort(arr, 0, len(arr)-1)

六、快速排序(Quick Sort)

def partition(arr, left, right):
    # 归位操作,left,right 分别为数组左边和右边的位置索引
    tmp = arr[left]
    while left < right:
        while left < right and arr[right] >= tmp:  # 从右边找比 tmp 小的数,如果比 tmp 大,则移动指针
            right -= 1                             # 将指针左移一个位置
        arr[left] = arr[right]                     # 将右边的值写到左边的空位上
        while left < right and arr[left] <= tmp:   # 从左边找比 tmp 大的数,如果比 tmp 小,则移动指针
            left += 1                              # 将指针右移一个位置
        arr[right] = arr[left]                     # 将左边的值写到右边的空位上
    arr[left] = tmp                                # 把 tmp 归位
    return left                   # 返回 left,right 都可以,目的是便于后面的递归操作对左右两部分进行排序


def quick_sort(arr, left, right):
    if left < right:
        mid = partition(arr, left, right)
        print(arr)                         # 每次归位后打印一次
        quick_sort(arr, left, mid-1)       # 对左半部分进行归位操作
        quick_sort(arr, mid+1, right)      # 对右半部分进行归位操作


arr = [5, 7, 4, 6, 3, 1, 2, 9, 8]
quick_sort(arr, 0, len(arr)-1)

七、堆排序(Heap Sort)

def sift(arr, low, high):
    """
    :param li: 列表
    :param low: 堆的根节点位置
    :param high: 堆的最后一个元素的位置
    """
    i = low                 # i最开始指向根节点
    j = 2 * i + 1           # j开始是左孩子
    tmp = arr[low]          # 把堆顶存起来
    while j <= high:        # 只要j位置有数
        if j + 1 <= high and arr[j+1] > arr[j]:   # 如果右孩子有并且比较大
            j = j + 1       # j指向右孩子
        if arr[j] > tmp:
            arr[i] = arr[j]
            i = j           # 往下看一层
            j = 2 * i + 1
        else:               # tmp更大,把tmp放到i的位置上
            arr[i] = tmp    # 把tmp放到某一级领导位置上
            break
    else:
        arr[i] = tmp        # 把tmp放到叶子节点上


def heap_sort(arr):
    n = len(arr)
    print('建堆过程:')
    print(arr)
    for i in range((n-2)//2, -1, -1):   # i表示建堆的时候调整的部分的根的下标
        sift(arr, i, n-1)
        print(arr)
    # 建堆完成
    print('堆排序过程:')
    print(arr)
    for i in range(n-1, -1, -1):        # i 指向当前堆的最后一个元素
        arr[0], arr[i] = arr[i], arr[0]
        sift(arr, 0, i - 1)             # i-1是新的high
        print(arr)


arr = [2, 7, 26, 25, 19, 17, 1, 90, 3, 36]
heap_sort(arr)

八、计数排序(Counting Sort)

def count_sort(arr):
    if len(arr) < 2:                       # 如果数组长度小于 2 则直接返回
        return arr
    max_num = max(arr)
    count = [0 for _ in range(max_num+1)]  # 开辟一个计数列表
    for val in arr:
        count[val] += 1
    arr.clear()                        # 原数组清空
    for ind, val in enumerate(count):  # 遍历值和下标(值的数量)
        for i in range(val):
            arr.append(ind)
    return arr


arr = [2, 3, 8, 7, 1, 2, 2, 2, 7, 3, 9, 8, 2, 1, 4, 2, 4, 6, 9, 2]
sorted_arr = count_sort(arr)
print(sorted_arr)

九、桶排序(Bucket Sort)

def bucket_sort(arr):
    max_num = max(arr)
    n = len(arr)
    buckets = [[] for _ in range(n)]         # 创建桶
    for var in arr:
        i = min(var // (max_num // n), n-1)  # i 表示 var 放到几号桶里
        buckets[i].append(var)               # 把 var 加到桶里边
        # 保持桶内的顺序
        for j in range(len(buckets[i])-1, 0, -1):
            if buckets[i][j] < buckets[i][j-1]:
                buckets[i][j], buckets[i][j-1] = buckets[i][j-1], buckets[i][j]
            else:
                break
    sorted_arr = []
    for buc in buckets:
        sorted_arr.extend(buc)
    return sorted_arr


arr = [7, 12, 56, 23, 19, 33, 35, 42, 42, 2, 8, 22, 39, 26, 17]
sorted_arr = bucket_sort(arr)
print(sorted_arr)

十、基数排序(Radix Sort)

def radix_sort(li):
    max_num = max(li)      # 最大值 9->1次循环, 99->2次循环, 888->3次循环, 10000->5次循环
    it = 0
    while 10 ** it <= max_num:
        buckets = [[] for _ in range(10)]
        for var in li:
            # var=987, it=1, 987//10->98, 98%10->8; it=2, 987//100->9, 9%10=9
            digit = (var // 10 ** it) % 10   # 依次取一位数
            buckets[digit].append(var)
        # 分桶完成
        li.clear()
        for buc in buckets:
            li.extend(buc)
        it += 1            # 把数重新写回 li
    return arr


arr = [3221, 1, 10, 9680, 577, 9420, 7, 5622, 4793, 2030, 3138, 82, 2599, 743, 4127]
sorted_arr = radix_sort(arr)
print(sorted_arr)

  • 3
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

忘川之水&

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

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

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

打赏作者

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

抵扣说明:

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

余额充值