排序算法-----计数排序

2023-09-17 15:36:30

目录

前言:

计数排序

1.算法描述

2. 基本思想

 3.实现逻辑

4.示例剖析

5.动图演示

代码实现

1.C/C++代码

2.Python代码

算法分析

时间复杂度 

空间复杂度

稳定性

局限性 


前言:

        有没有一种排序时间复杂度为直线正比的排序算法呢?有当然有,那就是计数排序,那为什么时间复杂度如此小的排序算法,然而其排序速度却不如快速排序(nlogn)呢?这里我们就会想到可能会有另一种代价在付出的,是的,那就是要付出空间资源的代价,下面我们就一起来看看吧!

计数排序

1.算法描述

        计数排序是一个非基于比较的排序算法,该算法于1954年由 Harold H. Seward 提出。它的优势在于在对一定范围内的整数排序时,它的复杂度为Ο(n+k)(其中k是整数的范围),快于任何比较排序算法。 [1]  当然这是一种牺牲空间换取时间的做法,而且当O(k)>O(n*log(n))的时候其效率反而不如基于比较的排序(基于比较的排序的时间复杂度在理论上的下限是O(n*log(n)), 如归并排序堆排序

2. 基本思想

计数排序使用一个额外的数组C,其中第i个元素是待排序数组A中值等于i的元素的个数。

计数排序的核心在于将输入的数据值转化为键存储在额外开辟的数组空间中。作为一种线性时间复杂度的排序,计数排序要求输入的数据必须是有确定范围的整数。

用来计数的数组C的长度取决于待排序数组中数据的范围(等于待排序数组的最大值与最小值的差加上1),然后进行分配、收集处理:

①  分配。扫描一遍原始数组,以当前值-minValue作为下标,将该下标的计数器增1。
②  收集。扫描一遍计数器数组,按顺序把值收集起来。

 3.实现逻辑

① 找出待排序的数组中最大和最小的元素
② 统计数组中每个值为i的元素出现的次数,存入数组C的第i项
③ 对所有的计数累加(从C中的第一个元素开始,每一项和前一项相加)
④ 反向填充目标数组:将每个元素i放在新数组的第C(i)项,每放一个元素就将C(i)减去1

4.示例剖析

假设这里有一个数组 [2,1,5,1,3,8,4,5,6,10,7] 如何通过计数排序来去实现排序呢?

第一步,先找到这个数组的最大值max元素,为10,然后创建一个数组count[max+1],即count[11],把count里面的数字都初始化为0,如下所示:

count          [0,0,0,0,0,0,0,0,0,0,0]

第二步,开始遍历原数组,然后统计里面元素的数量,在对应位置count数组里面进行+1操作。比如原数组中1出现了两次,那么就在count[0]加上2,即count[0]=2。count就依次去统计原数组元素出现的次数,统计如下所示:

                 1        2        3        4        5        6        7        8        9        10        

count         2        1        1        1        2        1        1        0        0        1      (这些是统计到出现的次数)

第三步,依次填入覆盖到原数组,最终得到排序后的数组

1        1        2        3        4        5        5        6        7        10

5.动图演示

代码实现

1.C/C++代码

#include<stdio.h>
#include<string.h>
//获取最大值
int get_max(int* n,int length) {
	int max = n[0];
	for (int i = 1; i < length; i++) {
		if (n[i]>max)
			max = n[i];
	}
	return max;
}

//计数排序
void count_sort(int* n, int max, int length) {
	int index=0;
	int range =max+1;
	int* temp_arr = (int*)malloc(sizeof(int) * range);
	memset(temp_arr, 0, sizeof(int) * range); //初始化全部都为0
	for (int j = 0; j < length; j++) { //统计
		temp_arr[n[j]]++;
	}
	
	for (int k = 0; k < range; k++) {
		while (temp_arr[k]) {
			n[index++]=k;//把统计后的数字覆盖给原数组上
			temp_arr[k]--;
		}
	}
	free(temp_arr);//释放空间
}
int main() {
	int array[11] = { 2,1,5,1,3,8,4,5,6,10,7 };
	printf("排序前:");
	for (int i = 0; i < sizeof(array) / sizeof(int); i++) {
		printf("%d ", array[i]);
	}
	printf("\n排序后:");
	count_sort(array, get_max(array, sizeof(array) / sizeof(int)),sizeof(array) / sizeof(int));
	for (int i = 0; i < sizeof(array) / sizeof(int); i++) {
		printf("%d ", array[i]);
	}
}
//排序前:2 1 5 1 3 8 4 5 6 10 7
//排序后:1 1 2 3 4 5 5 6 7 8 10

2.Python代码

import random as r
def count_sort(li,max):
    length=len(li)  #获取长度
    index=0
    new_li=[0 for _ in range(max)] #进入到统计
    for i in li:
        new_li[i-1]+=1
    for j in range(0,len(new_li)): #覆盖原数组
        while new_li[j]:
            li[index]=j+1
            index+=1
            new_li[j]-=1
    return li           

if __name__ == '__main__':
    li=[r.randint(1,10) for _ in range(10)]
    print(li)
    sort_li=count_sort(li,max(li))
    print(sort_li)
    
# [3, 6, 6, 7, 7, 1, 9, 10, 8, 5]
# [1, 3, 5, 6, 6, 7, 7, 8, 9, 10]

算法分析

时间复杂度 

O(n+k) 

空间复杂度

O(k)

稳定性

 稳定

局限性 

 注意:计数排序是需要去开辟一个空间内存的来存放统计数字的,如果当这个要进行排序的数组非常大的时候,这时候需要去申请的空间就会非常大,这很浪费空间的,所以选择的时候要慎用。

以上就是今天的全部内容了,我们下次见!

分享一张壁纸: 

更多推荐

企业电子招投标采购系统——功能模块&功能描述+数字化采购管理 采购招投标

功能描述1、门户管理:所有用户可在门户页面查看所有的公告信息及相关的通知信息。主要板块包含:招标公告、非招标公告、系统通知、政策法规。2、立项管理:企业用户可对需要采购的项目进行立项申请,并提交审批,查看所有的立项信息。主要功能包含:招标立项申请、非招标立项申请、采购立项管理。3、采购项目管理:可对项目采购过程全流程管

共聚焦显微镜在化学机械抛光课题研究中的应用

两个物体表面相互接触即会产生相互作用力,研究具有相对运动的相互作用表面间的摩擦、润滑与磨损及其三者之间关系即为摩擦学,目前摩擦学已涵盖了化学机械抛光、生物摩擦、流体摩擦等多个细分研究方向,其研究的数值量级也涵盖了亚纳米到百微米的区间。摩擦本身是一种能量损耗现象,然而得到合理地利用也能产生巨大的正面效益,因此,准确地测定

【Linux】自动化构建工具:make/Makefile

​👻内容专栏:Linux操作系统基础🐨本文概括:工具使用的背景、理解make/makefile工具、探索工作原理(文件修改时间的对比)、.PHONY伪目标、特性等。🐼本文作者:阿四啊🐸发布时间:2023.9.14背景“make”和“Makefile”是用于自动化构建和编译软件项目的工具和文件。它们通常用于编译源

企业电子招标采购系统源码之从供应商管理到采购招投标、采购合同、采购执行的全过程数字化管理

功能描述1、门户管理:所有用户可在门户页面查看所有的公告信息及相关的通知信息。主要板块包含:招标公告、非招标公告、系统通知、政策法规。2、立项管理:企业用户可对需要采购的项目进行立项申请,并提交审批,查看所有的立项信息。主要功能包含:招标立项申请、非招标立项申请、采购立项管理。3、采购项目管理:可对项目采购过程全流程管

【Linux学习笔记】 - 常用指令学习及其验证(上)

前言:本文主要记录对Linux常用指令的使用验证。环境为阿里云服务器CentOS7.9。关于环境如何搭建等问题,大家可到同平台等各大资源网进行搜索学习,本文不再赘述。由于本人对Linux学习程度尚且较浅,本文仅介绍验证常用指令的常用功能,可能无法展现指令及附带选项的所有功能,大家若想对相关指令内容有更全貌的了解还有劳搜

【Django】掌握models.py模型文件的使用

原文作者:我辈李想版权声明:文章原创,转载时请务必加上原文超链接、作者信息和本声明。文章目录前言一、models类继承(一)创建apps文件夹(二)settings.py文件配置(三)新建BaseModel(四)项目中调用二、时间字段(一)时间字段(二)默认时间(三)时间字段允许为空三、选择字段(枚举)(一)选择的基础

用Python实现链式调用

嗨喽,大家好呀~这里是爱看美女的茜茜呐我们在使用Django的models查询数据库时,可以看到有这种写法:formapp.modelsimportXXXquery=XXX.objects.all()query=query.filter(name=123,age=456).filter(salary=999)在这种写法

RHCE——二十、Ansible及安装与配置

Ansible一、自动化运维的背景运维自动化二、自动化运维的体系结构及组成1、系统预备2、配置管理3、监控报警4、常用工具三、自动化运维的发展概述1、运维工作内容分类2、运维自动化标准化2.1物理设备层面2.2操作系统层面2.3应用服务层面2.4运维操作层面四、Ansible的介绍1、什么是Ansible1.1Ansi

睿趣科技:抖音开店的操作流程有哪些

随着社交媒体的兴起,抖音已经成为了一款备受欢迎的短视频分享平台。许多人看到了在抖音上开店的商机,因此抖音开店也逐渐成为了一种新兴的商业模式。那么,抖音开店的操作流程究竟有哪些呢?下面将为您详细介绍。第一步:选定产品和目标市场在开店之前,您需要先确定您要销售的产品或服务以及目标市场。了解您的受众群体是谁,他们的需求是什么

【微信小程序】最新隐私弹窗组件

程序员何苦为难程序员微信小程序又发布了新一波政策就是获取头像昵称位置啥啥各种用户信息的时候都需要先搞个弹窗让用户确认才行小程序用户隐私保护指引内容介绍必须跟上啊咱公司的大佬马上搞了个组件贴出来学习一下顺便给大家参考<!--components/privacy/privacy.wxml--><!--隐私弹窗--><vie

通过API爬取到的淘宝商品详情数据展示(api测试入口)

API名称:item_get响应数据item:{num_iid:"698291711589",title:"美洋MEIYANG【现货】大嫂的西装内有乾坤率性撞色TR垫肩直筒西服",desc_short:"",price:439.12,total_price:0,suggestive_price:0,orginal_pr

热文推荐