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

算法概述

计数排序是一种非比较排序算法,用于将元素排列在特定顺序。计数排序可以用于整数和某些浮点数。它的基本思想是在需要排序的数组中,如果数组中的最小值是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中如何实现决策树算法,并提供两个示例,以说明如何使用Python实现决策树算法。 决策树算法的实现 在Python中,我们可以使用scikit-learn库来实现决策树算法。下面是一个使用scikit-learn库实现决策树算…

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

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

    python 2023年5月14日
    00
  • python3 常见解密加密算法实例分析【base64、MD5等】

    下面是详细讲解“Python3常见解密加密算法实例分析【base64、MD5等】”的完整攻略,包括算法原理、Python实现和两个示例说明。 算法原理 Base64 Base64是一种将二进制数据编码为ASCII字符的编码方式,常用于在网络上传输数据。Base64编码的原理是将3个字节的二进制数据分成4组,每组6位,然后将每组6位转换为一个可打的ASCII字…

    python 2023年5月14日
    00
  • 稀疏数组

    引入 当在网页上下棋类游戏时,玩到中途想要离开,但是我们需要保存进度,方便下次继续 我们应该怎么实现 ? 以围棋举例 使用二维数组将棋盘记下 ,如 0 为 没有棋子 ,1 为 黑子 , 2为白子 但是没有棋子的地方都为 0 ,整个二维数组充斥着大量的无效数据 0 我们需要想一个办法来 优化存储的方式 基本介绍 当一个数组中大部分元素是同一个值时,我们可以使用…

    算法与数据结构 2023年4月19日
    00
  • 运用Python3实现Two-Pass算法检测区域连通性

    以下是关于“运用Python3实现Two-Pass算法检测区域连通性”的完整攻略: 简介 Two-Pass算法是一种用于检测区域连通性的图像处理算法,它可以将图像中的像素分为不同的连通区域,并为每个连通区域分配一个唯一的标识符。在本教程中,我们将介绍如何使用Python3实现Two-Pass算法,并提供两个示例说明。 实现Two-Pass算法 以下是使用Py…

    python 2023年5月14日
    00
  • CSP-何以包邮?

    题目描述 新学期伊始,适逢顿顿书城有购书满 x 元包邮的活动,小 P 同学欣然前往准备买些参考书。一番浏览后,小 P 初步筛选出 n 本书加入购物车中,其中第 i 本(1≤i≤n)的价格为 ai 元。考虑到预算有限,在最终付款前小 P 决定再从购物车中删去几本书(也可以不删),使得剩余图书的价格总和 m 在满足包邮条件(m≥x)的前提下最小。 试帮助小 P …

    算法与数据结构 2023年5月11日
    00
  • Python实现的计算马氏距离算法示例

    Python实现的计算马氏距离算法示例 马氏距离是一种常用的距离度量方法,它可以用于计算两个随机向量之间的距离。在Python中,可以使用NumPy库实现计算马氏距离算法。本文将详细讲解Python实现计算马氏距离算法的完整攻略,包括算法原理、Python实现过程和示例。 算法原理 马氏距离是一种常用的距离度量方法,可以用于计算两个随机向量之间的距离。马氏距…

    python 2023年5月14日
    00
  • Python数据结构与算法(几种排序)小结

    下面是关于“Python数据结构与算法(几种排序)小结”的完整攻略。 1. 排序算法简介 排序算法是一种将一组数据按照一定规则排列的算法。在计算机科学中,常见的算法包括冒泡排序、选择排序、插入排序、快速排序、归并排序等。 2. Python实现常见排序算法 2.1 冒泡排序 冒泡排序是一种通过交换相邻元素来排序的算法。Python中,我们可以使用以下代码实现…

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