[排序算法] 计数排序 (C++)

计数排序解释

计数排序思想

计数排序 的思想十分简单,就是统计每个数字出现的次数。它是一种非基于比较的排序算法,其是通过额外的空间换取时间的方式,来实现更加高效的排序。😇😇😇

计数排序步骤

1、假设我们有一个长度为 n 的待排序序列,其所有元素组成的集合为 S,集合的数据范围为 0 - k
我们只需要定义一个大小为 k 的数组 count[] 用来统计每个数字出现的次数;

2、之后按照统计数组 count[] 下标顺序将数字放入原数组中即可完成排序。



计数排序动态演示

统计每个数字个数

放回原数组



计数排序时间复杂度及其局限性

时间复杂度分析

计数排序时间复杂度为 O(n + k),其中 n 为数据元素个数, k 为数据元素范围大小。
当数据范围大小 k 恰好和 n 相等时,时间复杂度为 O(n)

局限性分析

计数排序有几大局限性
1、当我们的数据范围非常大时,我们需要开辟很多的空间。夸张地讲,假如有1000万个数据,数据范围非常大,这个时候用计数排序是十分低效的;
2、当我们的数据之间跨度比较大,比如说出现了数字 1,但是下一个出现的数字是100002-9999中间的数字都没有出现,那么也浪费了很多的空间;
3、当我们的数据范围无法确定时,我们不知道要开辟多少大小的 count[] 数组;
4、计数排序还有一大局限性是,他不可以对小数进行排序,毕竟统计数组的下标都是整数呢。😏



计数排序核心代码

//计数排序实现方法如其名 但是局限性很大。 
//(若最大数很大或者数值范围无法确定时,消耗时间反而很会多,并且空间复杂度也高)
void CountingSort(vector<int> &a){
    vector<int> count(MAX, 0);           //统计每个数字出现的次数
    for(auto &x : a)
	count[x]++;
    
    int k = 0;
    for(int num = 0; num < MAX; num++){
    	while(count[num]){
    	    a[k++] = num;
    	    count[num]--;
    	}
    }

    vector<int>().swap(count);           //相当于用一个空直接换掉
}


完整程序源代码

#include<iostream>
#include<vector>
#include<ctime>
using namespace std;
const int MAX = 101;

//计数排序实现方法如其名 但是局限性很大。 
//(若最大数很大或者数值范围无法确定时,消耗时间反而很会多,并且空间复杂度也高)
void CountingSort(vector<int> &a){
    vector<int> count(MAX, 0);           //统计每个数字出现的次数
    for(auto &x : a)
	count[x]++;
    
    int k = 0;
    for(int num = 0; num < MAX; num++){
    	while(count[num]){
    	    a[k++] = num;
    	    count[num]--;
    	}
    }

    vector<int>().swap(count);           //相当于用一个空直接换掉
}


void show(vector<int> &v){
    for(auto &x : v)
        cout<<x<<" ";
    cout<<endl;
}


main(){
    vector<int> a;
    int n = 100;
    srand((int)time(0));
    while(n--)
        a.push_back(rand() % 100 + 1);
    show(a);
    CountingSort(a);
    cout<<endl<<endl;
    show(a);
}

程序运行结果图

posted @ 2022-11-21 00:35  MarisaMagic  阅读(573)  评论(0编辑  收藏  举报