希尔排序、计数排序和桶排序及其时间复杂度

本文介绍了希尔排序的原理和Python实现,展示了如何使用希尔排序对整数列表进行快速部分排序。随后,通过计数排序算法对0-100范围内元素进行排序,并对比了希尔排序与计数排序的优缺点。最后,探讨了桶排序和基数排序,展示如何根据特定场景选择合适的排序算法。
摘要由CSDN通过智能技术生成
import random

# 希尔排序
'''
希尔排序是一种分组插入排序算法
首先取一个整数d1 = n/2,将元素分为d1个组,每组相邻两个元素之间距离为d1,在各组内进行直接插入排序

取第二个整数d2=d1/2,重复上述分组排序过程,直到d1=1,即所有元素在同一组内进行直接插入排序

希尔排序每趟并不使某一些元素有序,而是是整体数据越来越接近有序,最后一趟排序使得所有数据有序

时间复杂度:
由gep决定

'''


def insert_sort_gap(li, gep):
    for i in range(gep, len(li)):  # i表示摸到的牌的下标
        temp = li[i]
        j = i - gep
        while j >= 0 and li[j] > temp:
            li[j + gep] = li[j]
            j -= gep
        li[j + gep] = temp


def shell_sort(li):
    d = len(li) // 2
    while d >= 1:
        insert_sort_gap(li, d)
        d //= 2


li = list(range(1000))

random.shuffle(li)
print(li)
shell_sort(li)
print(li)
print('-------------------------------')

# 计数排序
'''
对列表进行排序,已知列表中的个数范围都在0到100之间。
不适用小数与字符串
消耗大量内存
'''


# 时间复杂度:O(n)

def count_sort(li, max_count=100):
    count = [0 for i in range(max_count + 1)]
    for val in li:
        count[val] += 1
    li.clear()
    # print(count)

    for ind, val in enumerate(count):
        for i in range(val):
            li.append(ind)


def sys_sort(li):
    li.sort()


li = [random.randint(0, 100) for _ in range(1000)]
print(li)
count_sort(li)
print(li)
print('-------------------------')
# 桶排序
'''
通过计数排序改进
首先将元素分在不同的桶中,在对每个桶中的元素排序
桶排序的表现取决于数据的分布,也就是需要对不同数据排序时采取不同的分桶策略
平均时间复杂度 : O(n+k)
最坏时间复杂度:O(n**2*k)

分布不均匀就不快

空间复杂度:o(n*k)

'''


def bucket_sort(li, n=100, max_num=10000):
    buckets = [[] for i in range(n)]  # 创建桶
    for var in li:
        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
        # 0->0
    sorted_li = []
    for buc in buckets:
        sorted_li.extend(buc)
    return sorted_li


li = [32, 13, 94, 52, 17, 54, 93]
# print(li)

li = bucket_sort(li)
print(li)
print('<===============================>')

# 基数排序
# 多关键字排序
'''
先按照年龄进行排序,再按照薪资进行稳定的排序
时间复杂度:
O(kn)
空间复杂度:
O(k+n)
k代表数的位数
线性时间复杂度

'''


# 32 13 94 52 17 54 93
# 个位以及十位判断大小
# 十位作为桶,依次判断桶中的数的大小


def radix_sort(li):
    max_num = max(li)  # 99->2次 888->3次  10000->5次
    it = 0
    while 10 ** it <= max_num:
        buckets = [[] for i in range(10)]
        for var in li:
            # 987 it =1
            digit = (var // (10 ** it)) % 10
            buckets[digit].append(var)
        # 分桶完成
        li.clear()
        for buc in buckets:
            li.extend(buc)
        # 把数重新写回li

        it += 1


li = [32, 13, 94, 52, 17, 54, 93]
# random.shuffle(li)

print(li)
print(',.,.,.,.,.,.,.,.,.,.,.,..')
radix_sort(li)
print(li)

# 习题
# 面试题
'''
给两个字符串s和t,判断t是否为s的重新排列后组成的单词
s='anagram',t='nagaram',return true
s='rat',t='car',return false
'''


'''
给定一个m*n的二维列表,查找一个数是否存在。列表有下列特性:
每行的列表从左到右已经排序好
每一行第一个数比上一行最后一个数大
[
[1,3,5,7],
[10,11,16,20],
[23,30,34,50]
]
'''



'''
给定一个列表和一个整数,设计算法找到两个数的下标,使得两个数之和为给定的数。保证肯定仅有一个结果
例如,列表[1,2,5,4]与目标整数3,1+2=3,结果为(0,1)
'''

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值