详解计数排序算法原理与使用方法

yizhihongxing

算法概述

计数排序是一种非比较排序算法,用于将元素排列在特定顺序。计数排序可以用于整数和某些浮点数。它的基本思想是在需要排序的数组中,如果数组中的最小值是k,最大值是j,那么可以创建一个计数器数组来计算原始数组中每个数值的出现次数。依此可以遍历计数器数组并按计数器的计数值直接填充输出数组,从而生成排序后的数组。具体而言,计数排序由以下 3 个实质性部分组成:

  1. 计数数组: 长度为需要排序的数字范围,遍历待排序序列,将序列中所有的数字按次数放入对应下标的计数数组。
  2. 累加数组: 对计数数组进行逐个累和,可以得到每个数字应该排序的下标。
  3. 排序数组: 根据累加数组,将待排序序列中的每个元素按顺序放入这个新的数组里。

算法流程

以整数一维数组排序为例,算法流程如下:

  1. 扫描一遍序列找到最大值和最小值,取区间长度len=max-min+1,为计数数组的长度。
  2. 定义计数数组c,一遍扫描序列,将出现的整数计数记录在相应的计数数组位置上,c[i]-=min,其中c[i]表示i出现的次数,i=min,max。
  3. 接着扫描c数组,依次累加前面的值(累加后c[i]表示i在序列中排名的最大下标),从前向后将序列的数填充到r数组(注意取出时要加上min)上。
  4. 此时r数组即为序列排序后的新序列。

具体代码如下:

void CountingSort(int* arr, int len)
{
    int min = arr[0], max = arr[0];
    for (int i = 1; i < len; i++)  // 找出区间上界和下界
    {
        if (arr[i] < min)
            min = arr[i];
        else if (arr[i] > max)
            max = arr[i];
    }

    int* c = new int[max - min + 1]();  // 计数器数组
    for (int i = 0; i < len; i++)
        c[arr[i] - min]++;  // 统计每个元素出现的次数
    for (int i = min + 1; i <= max; i++)
        c[i - min] += c[i - min - 1];  // 将计数器依次累加

    int* r = new int[len]();  // 结果数组
    for (int i = len - 1; i >= 0; i--)
    {
        r[c[arr[i] - min] - 1] = arr[i];  // 放置第 arr[i] 个元素
        c[arr[i] - min]--;  // 更新其对应于计数器的值
    }

    memmove(arr, r, len * sizeof(int));  // 将结果赋值回原数组中
    delete[] c;
    delete[] r;
}

算法示例

示例一

以序列a,b,c排序为例,不妨设序列为3,1,4,0,0,3,4,3。那么首先需要获取序列最小值、最大值、范围。可知最小值为0,最大值为4,范围就是[0, 4),长度为5。

计数数组就是一个长度为5的数组,记录从0到4一共有多少个数字出现(出现个数即计数器值),第一个数字是零,存在的首位就改成0,第二个数字是一个,存在的首位就改成1,第三个数字是四,存在的首位就改成4,以此类推,数字0出现了两次,计数器中将0的数值设为了2,数字1出现了一次,计数器中将1的数值设为了1,数字2没有出现过,所以计数器中的2还是0,数字3出现了3次,计数器中将3的数值设为3,数字4出现了2次,计数器中将4的数值设为2。计数器数组为2,1,0,3,2。
累加数组就是一个长度为5的数组,记录每个值在排序后的序列中应该排在第几位。其实就是一个前缀和。首先将第一个数字计数累加到计数器的第0个数值里,再将第二个数字计数累加到计数器的第一个计数值里,接着是第三个数字,累加到计数器的第四个计数值里,以此类推,最后得到的数组就是0,2,3,6,8。
排序数组就是将原始数组按照累加数组的下标从后向前填值,得到的序列即是排序结束的序列。如果反过来,先放第一个“3”,一共出现3次,那么放到序列中就要从累加数组的最后一位往前放三个“3”,分别加上min,即放在第3位,第4位和第7位。接着放第二个数字0,一共出现了2次,同样也要从累加数组的最后面往前放两个数字0,放在第0位和第1位,以此类推。就得到了排序结果:0,0,1,3,3,3,4,4。

示例二

假设要给字符串进行排序,如“AACCBDEBBECEA”,可以将每个字符的ascii码进行计数排序:

按照字符出现的次数,可以得到计数器数组:

A的ascii码是65出现了2次
B的ascii码是66出现了3次
C的ascii码是67出现了2次
D的ascii码是68出现了1次
E的ascii码是69出现了2次

因为其中的字母序号是连续的,最小的是65,最大的是69,计数数组长度就是69-65+1=5

计数器数组就是长度为5的数组,记录从This is to inform you处于区间[65, 70)内的每一个数字出现次数(出现次数即为计数数组值)。这些数字是65、66、67、68、69,第65个数字出现了两次,计数数组中该数字下标的数值就是2, 第66个数字出现了三次,计数数组中该数字下标的数值就是3,以此类推。

累加数组同样是一个长度为5的数组,记录每个值在排序后的序列中应该排在第几位。计数数组累加后得到的数组为 2 5 7 8 10,比如最小的数字65,他在计数器中对应的下标是0,而且出现2次,因此累加数组的第一个数是2,同样,累加后的数组中的第二个数字是5,累加后的数组中的第一个数是2,所以累加后的数组中的第三个数字的值就是累加数组中的第二个元素加上计数数组中的第三个元素,即5+2=7,以此类推。

排序数组也是将原始数组按照累加数组的下标从后向前填值,即先从后往前扫描一遍计数器中的每个值,再根据该值在累加数组中得到该值在排序数组中的位置,放入该位置即可。

最终结果就是AACCEBBBDEECB。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:详解计数排序算法原理与使用方法 - Python技术站

(0)
上一篇 2023年3月27日
下一篇 2023年3月27日

相关文章

  • Python深度优先算法生成迷宫

    Python深度优先算法生成迷宫的完整攻略 深度优先算法是一种常用的图遍历算法,它可以用于生成迷宫。在本文中,我们将介绍如何使用Python实现深度优先算法生成迷宫。我们将分为以下几个步骤: 导入必要的库 定义迷宫类 实现深度优先算法 示例说明 步骤1:导入必要的库 在实现深度优先算法之前,我们需要导入必要的库。在这个例子中,我们将使用numpy和rando…

    python 2023年5月14日
    00
  • 详解用Python进行时间序列预测的7种方法

    详解用Python进行时间序列预测的7种方法 时间序列预测是一种重要的数据分析技术,它可以用于预测未来的趋势和变化。本文将介绍Python中实时间列预测的7种方法,并提供两个示例说明。 1. 移动平均法 移动平法是一种简单的时间序列预测方法,它基于过去一段时间的平均值来预测未来的值。具体实现如下: def moving_average(data, windo…

    python 2023年5月14日
    00
  • Python深度学习pyTorch权重衰减与L2范数正则化解析

    以下是关于“Python深度学习pyTorch权重衰减与L2范数正则化解析”的完整攻略: 简介 在深度学习中,权重衰减和L2范数正则化是常用的技术,用于防止过拟合和提高模型泛化能力。在本教程中,我们将介绍Python深度学习pyTorch权重衰减和L2范数正则化的原理和使用方法,并提供两个示例。 原理 权重衰减和L2范数正则化是常用的防止过拟合和提高模型泛化…

    python 2023年5月14日
    00
  • 基于python的七种经典排序算法(推荐)

    下面是关于“基于Python的七种经典排序算法”的完整攻略。 1. 排序算法简介 排序算法是一种将一组数据按照特定顺序排列的算法。在计算机科学中,常见的排序算法包括冒泡排序、选择排序、插入排序、希尔排序、归并排序、快速排序和堆排序等。 2. Python实现七种经典排序算法 2.1泡排序 冒泡排序是一种通过交换相邻元素来排序的算法。在Python中,我们可以…

    python 2023年5月13日
    00
  • 详解python 支持向量机(SVM)算法

    下面是关于“详解Python支持向量机(SVM)算法”的完整攻略。 1. 支持向量机(SVM)算法简介 支持向量机(SVM)是一种二分类模型它的基本模型是定义特征空间上间隔最大的线性分类器,其学习策略便是间隔最大化,终可转化为一个凸二次规划问题的求解。SVM算法具有良好的泛化能力和鲁棒性,被广泛用于分类、回归和异常检测等领域。 2. Python实现支持向量…

    python 2023年5月13日
    00
  • python实现H2O中的随机森林算法介绍及其项目实战

    H2O是一个开源的分布式机器学习平台,它提供了许多强大的机器学习算法,包括随机森林算法。本文将详细介绍如何使用Python实现H2O中的随机森林算法,并提供两个示例说明。 H2O随机森林算法简介 H2O随机森林算法是一种集成学习算法,它通过组合多个决策树来提高预测准确性。H2O随机森林算法的基本思想与传统随机森林算法相似,但它具有以下优点: 可以处理大量数据…

    python 2023年5月14日
    00
  • python opencv 简单阈值算法的实现

    下面是详细讲解“Python OpenCV简单阈值算法的实现”的完整攻略。 简单阈值算法 简单阈值算法是一种基本的图像分割算法,它将图像分成两个部分:黑色和白色。该算法将图像中的每个像素与一个阈值进行比较,如果像素值大于阈值,则将其设置为白色,否则将其设置为黑色。 Python OpenCV实现简单阈值算法 下面是一个Python OpenCV实现简单阈值算…

    python 2023年5月14日
    00
  • Python中22个万用公式的小结

    下面是详细讲解“Python中22个万用公式的小结”的完整攻略。 1. 求和公式 求和公式是Python中最基本的公式之一,用于计算一组数的和。求和公式的数学表示如下: $$\sum_{i=1}^{n} a_i = a_1 + a_2 + … + a_n$$ 其中,$a_i$表示第$i$个数,$n$表示数的个数。 下面是Python实现求和公式的示例: …

    python 2023年5月14日
    00
合作推广
合作推广
分享本页
返回顶部