算法:排序(三)

计数排序与基数排序

利用桶排序的思想可以达到O(N)的时间复杂度,但仅限于特定的情况。

计数排序

已知数据取值在狭小且有限的集合内,则可以使用计数排序。思路是预先准备好表征元素取值的计数桶,遍历元素时,使得表征该元素取值的桶计数值加一。遍历完成后倒出元素即可。

int* countingSort(int* A, int n) {
    //获取最大最小值以便分配桶
    int min=A[0],max=A[0];
    for(int i=1;i<n;++i){
        if(A[i]>max)
            max=A[i];
        if(A[i]<min)
            min=A[i];
    }
    //分配桶:一个计数数组
    int* ss=new int[max-min+1]();
    //对每个元素找到其对应的桶
    for(int i=0;i<n;++i)
        ss[A[i]-min]++;
    //遍历所有的桶,把元素倒回去
    int pos=0;
    for(int i=0;i<max-min+1;++i){
        while(ss[i]--){
            A[pos++]=i+min;
        }
    }
    delete[] ss;
    return A;
}

基数排序

基数排序可以看做是计数排序的扩展。适用于元素有多个键值,键值取值狭小且有限的情况。思路是按照键值优先级从低到高进行排序。
举例:正整数的个位/十位/百位数字就是表征数字大小的各个键值,先按照个位数字放入各个桶内,然后倒出;再按照十位/百位数字继续此操作。

CODE

int* radixSort(int* A, int n) {
    const int M=10;
    //临时存储数据
    int* s=new int[n];
    //计数:每个键值各对应多少元素
    int* c=new int[M]();
    //被除数,用以计算当前位置的数字
    int x=1;
    int number;
    for(int t=0;t<5;++t){  //假设元素不超过五位数
        //清零计数数组
        for(int m=0;m<M;++m)
            c[m]=0;
        //统计数组中各个number的数目
        for(int i=0;i<n;++i){
            number=A[i]/x%10;
            c[number]++;
        }
        //c数组做累加操作
        for(int m=1;m<M;++m)
            c[m]=c[m-1]+c[m];
        //经过累加后,c[m]表示第m号桶的终止位置后一位
        //正是因此,我们放桶的时候从后往前放.
        for(int i=n-1;i>=0;--i){
            number=A[i]/x%10;
            s[--c[number]]=A[i];
        }
        //从桶中倒回数组
        for(int i=0;i<n;++i){
            A[i]=s[i];
        }
        x*=10;
    }
    delete[] s;
    delete[] c;
    return A;
}

注意

  • 以上代码为了节省空间,所有的桶都位于数组s上的某一段,通过计数产生c数组,然后累加得到每个桶的尾后指针位置,以此访问桶。


  • 元素入桶时根据尾后指针进行遍历,所以需要从后向前遍历数组。
  • 如果不考虑空间花费,可以通过指针数组来创建类似于二维数组的结构来构造M个桶;或者使用队列等数据结构来处理。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 196,099评论 5 462
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 82,473评论 2 373
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 143,229评论 0 325
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 52,570评论 1 267
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 61,427评论 5 358
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 46,335评论 1 273
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 36,737评论 3 386
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 35,392评论 0 254
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 39,693评论 1 294
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 34,730评论 2 312
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 36,512评论 1 326
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 32,349评论 3 314
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 37,750评论 3 299
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,017评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 30,290评论 1 251
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 41,706评论 2 342
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 40,904评论 2 335

推荐阅读更多精彩内容