最通俗易懂的计数排序-Python实现

计数排序

讲解计数排序之前我们先来看一个问题:对列表进行排序,已知列表中的数的范围都在0-500之内,设计一个时间复杂度为O(n)的算法。

这就需要用到计数排序,顾名思义,记录某个元素出现了多少次

从左至右依次遍历列表,当某个元素出现时,将此元素出现次数加1,遍历完列表后根据元素出现次数将元素依次排开。

注:元素值从0开始方便列表索引计算

a = [1, 3, 2, 6, 5, 5, 1, 3, 4, 1]


元素值  出现次数
0  0
1  3
2  1
3  2
4  1
5  2
6  1


排序结果:1 1 1 2 3 3 4 5 5 6


# 元素值1出现3次,排列3个1;元素值2出现1次,排列1次, 以此类推。

Python实现

def count_sort(li, max_count=500):               # li为待排序列表,max_count为最大元素
    count = [0 for _ in range(max_count+1)]  # 列表推导式生成0到500的列表,用来记录元素出现多少次
    for val in li :
        count[val] += 1        # 如果元素出现则对应count列表索引处+1
    li.clear()                         # 直接清除原列表,不在生成新列表,节省内容空间
    for index, val in enumerate(count):        # 获取index下标,val对应的值
    # for循环里, index索引出现了val次
        for i in range(val):
            li.append(index)          # 把index添加到li,次数为val

测试算法

import random 
li = [random.randint(0, 50) for _ in range(100)]
print(li)
count_sort(li)
print("\n")
print(li)

运行结果

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
下面是JS实现计数排序代码及解释: ```javascript function countingSort(arr) { // 找出最大值和最小值 let max = arr[0], min = arr[0]; for (let i = 1; i < arr.length; i++) { if (arr[i] > max) { max = arr[i]; } if (arr[i] < min) { min = arr[i]; } } // 统计每个元素出现的次数 const counts = new Array(max - min + 1).fill(0); for (let i = 0; i < arr.length; i++) { counts[arr[i] - min]++; } // 计算前缀和 for (let i = 1; i < counts.length; i++) { counts[i] += counts[i - 1]; } // 根据前缀和将元素放到有序序列中的正确位置 const result = new Array(arr.length); for (let i = arr.length - 1; i >= 0; i--) { result[counts[arr[i] - min] - 1] = arr[i]; counts[arr[i] - min]--; } return result; } ``` 该算法的主要思想是先找出待排序序列中的最大值和最小值,然后根据最大值和最小值确定统计数组的大小。接着遍历待排序序列,统计每个元素出现的次数,存入统计数组中;然后对于统计数组中的每个元素,计算其前缀和,得到每个元素在有序序列中的起始位置;最后从后往前遍历待排序序列,根据统计数组和前缀和将元素放到有序序列中的正确位置。 具体来说,我们首先遍历一遍待排序序列,找出其中的最大值和最小值,然后根据最大值和最小值确定统计数组的大小。然后我们再遍历一遍待排序序列,统计每个元素出现的次数,存入统计数组中。接着我们计算统计数组的前缀和,得到每个元素在有序序列中的起始位置。最后,从后往前遍历待排序序列,根据统计数组和前缀和将元素放到有序序列中的正确位置。 需要注意的是,在统计数组中存放的是元素出现的次数,而不是元素本身。另外,为了避免负数索引,我们需要将所有元素减去最小值,再进行统计排序。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值