计数排序算法C语言代码,希尔排序、计数排序、桶排序、基数排序

希尔排序

希尔排序思路:

希尔排序是一种分组插入排序算法。

首先取一个整数d1=n/2, 将元素分为d1个组, 每组相邻量元素之间距离为d1,在各组内进行直接插入排序

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

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

3617c8f02b22ae87f4750f73ee32b7e0.gif

复习一下插入排序:

def insert_sort(li):for i in range(1, len(li)):

j= i - 1# j 为手里最大的牌

tmp=li[i]while j >= 0 and li[j] >tmp: # 只要手里最大的牌比摸回来的牌大就一致往右移动

# j>= 0,说明所有数都比摸到的牌要大,直接退出循环

li[j+1] =li[j] # 右移

j-= 1li[j+1] = tmp # 确定要插入的时候,是必须插到j的前一个位置

再看实现希尔排序代码:

def insert_sort(li, gap):for i inrange(gap, len(li)):

j= i -gap

tmp=li[i] # 摸回来的牌的值while j >= 0 and li[j] >tmp:

# 在有序区里面,摸回来的牌比有序区的牌(从右到左)的值小,有序区的牌就向右移动一个位置

li[j+gap] =li[j]

j-=gap

li[j+gap] =tmp

def shell_sort(li):

d= len(li) //2

while d >= 1:

insert_sort(li, d)

d= d //2

li= list(range(1000))

import random

random.shuffle(li)

shell_sort(li)

print(li)

希尔排序小结:

希尔排序的时间复杂度比较复杂,且和选区的grap序列有关。

计数排序

现在有一个列表,已知列表中的数范围都在0到100之间。设计算法在O(n)时间复杂度内将列表进行排序。

思路:

创建一个列表,用来统计每个数出现的次数。(index存数字大小,value存出现次数)

def count_sort(li, max_num):

# 创建一个max_num长的列表

count= [0 for i in range(max_num + 1)]for num inli:

count[num]+= 1li.clear()for ind, val inenumerate(count):for i inrange(val):

li.append(ind)

import random

li= [random.randint(0,100) for _ in range(1000)]

count_sort(li, len(li))

print(li)

计数排序的缺点:

如果列表只有5个数,数字范围是1到1亿,就需要开一个一亿长度的列表,严重浪费空间和资源不合理使用。

桶排序

在计数排序中,如果元素的范围比较大(比如在1到1亿之间), 如何改造算法?

桶排序(Bucket Sort):首先将元素分在不同的桶中,再对每个桶中元素排序。

5235dfd0ce4109445f1b8287a189b7ea.png

桶排序的表现取决于数据的分布。也就是需要对不同数据排序时采取不同的分桶策略。

平均情况时间复杂度:O(n+k)

最坏情况时间复杂度:O(n2k)

空间复杂度:O(nk)

def bucket_sort(li, n=100, max_num=10000):

buckets= [[] for i inrange(n)] # 创建通for var inli:

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]: # 必须是升序 降序的话[9,8,7,6] [99,87,55,22], 合并之后并不是有序

buckets[i][j], buckets[i][j-1] = buckets[i][j-1], buckets[i][j]else:breaksorted_li=[]for buc inbuckets:

sorted_li.extend(buc)returnsorted_li

import random

li= [random.randint(0,99999) for i in range(100)]

li=bucket_sort(li)

print(li)

基数排序

基数排序是按照低位先排序,然后收集;再按照高位排序,然后再收集;依次类推,直到最高位。

bd60a4bb0019be718237a7b29ef64bb8.gif

def radix_sort(li):

max_num= max(li) # 最大值 9->1, 99->2, 888->3, 10000->5it= 0

while 10 ** it <=max_num:

buckets= [[] for _ in range(10)]for var inli:

#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 inbuckets:

li.extend(buc)

# 把数重新写回li

it+= 1

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值