数据结构与算法之计数排序

目录

前言

计数排序

定义

优缺点

策略

图解

代码实现

结束语


前言

今天是坚持写博客的第20天,时光飞逝,第二个10天即将过去,希望可以继续坚持,光明的未来也在未来等着我们。今天也恰逢高考,祝所有学子一帆风顺,考的全会,蒙的全对!

我们今天来看计数排序,这是数据结构与算法中一种常见的算法,且听我娓娓道来。


计数排序

定义

计数排序的基本思想是对于待排序的数组,首先确定数组中元素的取值范围,然后使用一个计数数组来统计每个元素的出现次数。最后根据计数数组来确定每个元素在排序后数组中的位置。

优缺点

  • 优点:计数排序是一种稳定的排序算法,当输入的元素是整数,且元素的取值范围较小或已知时,计数排序的效率很高
  • 缺点:当待排序的数组中的元素取值范围很大时,计数数组会占用大量的内存空间,容易造成空间的浪费和查找时的效率上复杂化。计数排序也不是原地排序算法,需要额外的内存空间来存储计数数组和排序后的数组。

策略

假设我们有一个打乱顺序的数组:(5,7,2,5,1,6,5,8,6,2),此时我们需要使用计数排序进行排序,我们需要遵循以下步骤:

  1. 首先创建一个最大容量为数组中最大值+1的数组用于计数。比如这个数组当中最大值为8,因此我们创建一个大小为9的数组。(因为需要排0)
  2. 遍历创建好的数组,都赋初值为0。
  3. 根据元素的值对号入座,比如数字5出现1次,5号位置就增加1,7出现1次,7号位置就增加1。
  4. 重复第三步,完成统计。
  5. 输出结果,元素的值为多少,就输出对应下标几次。例如0出现0次,这0不输出,7出现1次,就输出7一次。(需要按照下标从小到大来)

但是需要注意的是,如果是从95开始,有一个未排列的数组(95,97,92,95,91,96,95,98,96,92),此时我们需要有一个初始值,对于这个数组我们可以用90当初始值,用数组内的元素值减掉基准值90,再放入对应位置进行计数。比如95-90=5,那么数字“5”出现1次,5号位置增加1。

同时还是(95,97,92,95,91,96,95,98,96,92)这个栗子,我们用最大值加一的形式创建数组用于计数,那么会造成90以前的空前全部浪费。因此我们需要用最大值-最小值+1作为数组的大小,并以最小值作为基准值。

图解

光看策略可能不一定清晰,我们直接上图:

我们将数字填入对应下标处,并累加。累加完成后进行排序输出:1,2,2,5,5,5,6,6,7,8。

代码实现

下面是大家期待的代码实现,下面是python版本的计数排序,供大家参考:

def counting_sort(arr):  
    # 找出数组中的最大值  
    max_val = max(arr)  
      
    # 初始化计数数组,大小为最大值加1,并全部初始化为0  
    count_arr = [0] * (max_val + 1)  
      
    # 统计每个元素的出现次数  
    for num in arr:  
        count_arr[num] += 1  
      
    # 修改计数数组,将每个元素的值变为小于等于该元素的元素个数  
    for i in range(1, len(count_arr)):  
        count_arr[i] += count_arr[i-1]  
      
    # 从后往前遍历原数组,根据计数数组中的值放置元素到排序后的数组  
    sorted_arr = [0] * len(arr)  
    for i in range(len(arr)-1, -1, -1):  
        sorted_index = count_arr[arr[i]] - 1  # 减1是因为我们需要的是索引,不是计数  
        sorted_arr[sorted_index] = arr[i]  
        count_arr[arr[i]] -= 1  # 放置元素后,对应计数值减1  
      
    return sorted_arr  
  
# 示例用法  
arr = [4, 2, 2, 8, 3, 3, 1]  
print("原始数组:", arr)  
sorted_arr = counting_sort(arr)  
print("排序后的数组:", sorted_arr)

结束语

今天对计数排序的讲解就到这里,希望对大家有帮助,如果对您有帮助,希望您可以留下一个点赞或关注,这对我真的很重要,谢谢!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值