【sort】 基数排序

下面这段问答摘自csdn:

把基数排序说成桶排序应该是没有太大问题的。
总的说来,应该把这一类归为分配排序,由于分配排序的一些缺陷,主要是时间代价很差,改进成为桶式排序(bucket sort),而桶排序的基本思路是将较少的纪录分配到每个桶,然后用较快的“收尾排序”来对每桶中的纪录进行排序。在此基础上,当允许基于分配排序的收尾排序时,为了尽量减少桶的数量并缩短排序时间,发展出了基数排序(Radix Sort)。
基数的选择:如果是数字,最常用的是2和10这两个了,当然是由于二进制和十进制的关系,就如楼上的那种表示方法:8 = 0 * 2 ^ 1 + 0 * 2 ^ 2 + 1 * 2 ^ 3
同样,有:162 = 2 * 10 ^ 0 + 6 * 10 ^ 1 + 1 * 10 ^ 2
还记得基数、基码、位权吧,基数决定桶数,基码决定了桶的位置先后,位权决定分配次数。
如果是字符串,当然是26了(26个字母),呵呵。

至于“在位内进行比较的时候采用什么排序法???”
猜想意思是:把高位比较了一次之后,分到了不同的桶里,在桶内再将所有的数作一次排序。如果是那样的话,就只能叫桶排序了,就不能体现出基数排序的优越性。
在具体实现时,基数排序应该是没有比较大小这一过程的,而只是将待排序的数字什么的做分配的一个过程,只要看位权就可以决定到底做几次分配了(3位数就做3次分配)。
下面是一个例子:
待排序列表:27 91 1 97 17 23 84 28 72 5 67 25
基数是10,基码是0~9,最大的位权是1(决定了分配次数是1+1=2)。
第一趟分配:(先排个位数)
桶的编号 分配到桶内的数字
0
1 -> 91 -> 1
2 -> 72
3 -> 23
4 -> 84
5 -> 5 -> 25
6
7 -> 27 -> 97 -> 17 -> 67
8 -> 28
9
第一趟分配结果是(从0号桶开始,得到这个序列):91 1 72 23 84 5 25 27 97 17 67 28
然后在此基础上作第二次分配:(排十位数)
桶的编号 分配到桶内的数字
0 -> 1 -> 5
1 -> 17
2 -> 23 -> 25 -> 27 -> 28
3
4
5
6 -> 67
7 -> 72
8 -> 84
9 -> 91 -> 97
第二趟分配的结果是(从0号桶开始,得到这个序列):1 5 17 23 25 27 28 67 72 84 91 97
好了,这就是我们所需要的了。由于第一次的结果已经使个位数保持递增,第二次只要在此基础上使十位数递增即可,不用考虑个位数的大小,这样两次分配就可以达到排序目的了。

#include <cstdio>
#include <iostream>
#include <stdlib.h>
using namespace std;
int RadixCountSort(int*index, int maxn, int* nData, int len)
{
    int* cnt= (int*)malloc(sizeof(int)* maxn);
    for (int i=0;i<len;i++)
    {
        cnt[i] = 0;
    }
    for (int i=0;i<len;i++)
    {
        cnt[index[i]]++;
    }
    for (int i=1;i<10;i++)  //确定不大于该位置的个数。
    {
        cnt[i]+=cnt[i-1];
    }
    int *tmp=(int*)malloc(sizeof(int)*len);    //存放临时的排序结果。
    for (int i=len-1;i>=0;i--)
    {
        cnt[index[i]]--;
        tmp[cnt[index[i]]] = nData[i];
    }
    for (int i=0;i<len;i++)
    {
        nData[i] = tmp[i];
    }
    free(tmp);
    free(cnt);
    return 1;
}
int RadixSort(int* nData,int len)
{
    int *Radix=(int*)malloc(sizeof(int)*len);
    int Base = 1;
    bool check = false;
    while (!check)
    {
        check = true;
        Base *= 10;
        for (int i=0;i<len;i++)
        {
            Radix[i] = nData[i] % Base;
            Radix[i] /= Base / 10;
            if (Radix[i]>0)  check=false;
        }
        if (check)break;    //如果所有的基数都为0,认为排序完成,就是已经判断到最高位了。
        RadixCountSort(Radix, 10, nData, len);
    }
    free(Radix);
    return 1;
 }
int main()
{
    int Data[10]={123,5264,9513,854,9639,1985,159,3654,8521,8888};
    RadixSort(Data, 10);
    for (int i=0;i<10;i++) printf("%d ",Data[i]);
    printf("\n");
    system("pause");
    return 0;
}
时间: 2024-10-22 14:53:04

【sort】 基数排序的相关文章

线性排序算法---- 计数排序, 基数排序, 桶排序

排序算法里,除了比较排序算法(堆排序,归并排序,快速排序),还有一类经典的排序算法-------线性时间排序算法.听名字就让人兴奋! 线性时间排序,顾名思义,算法复杂度为线性时间O(n) , 非常快,比快速排序还要快的存在,简直逆天.下面我们来仔细看看三种逆天的线性排序算法, 计数排序,基数排序和桶排序. 1计数排序  counting Sort 计数排序 假设 n个 输入元素中的每一个都是在 0 到 k 区间内的一个整数,当 k= O(N) 时,排序运行的时间为 O(N). 计数排序的基本思想

【POJ3415】Common Substrings 后缀自动机

转载请注明出处:http://blog.csdn.net/vmurder/article/details/42710069 其实我就是觉得原创的访问量比未授权盗版多有点不爽233... 题意: 给两个串,问有多少长度大于等于K的公共子串(位置不同也算一对) 题解: 后缀自动机DP 对第一个串建立后缀自动机,然后做一些预处理, 然后拿第二个串在后缀自动机上跑,到每个节点加一次贡献. 但是这样需要每个点往parent树上跑一遍,会TLE,所以可以加个lazy. 然后代码中有两次运用到拓扑序来从子向父

算法数据结构 sf sjjg

链表 反转链表 链表倒数第k个 最小公共节点 树 红黑 树 二叉树 深度优先, 广度优先 先序,中序,后序遍历 树, 森林,二叉树互转 递归 转循环 队列 两个栈模拟一个队列 排序 简单排序, 归并排序 ,快排, 桶排 冒泡排序(bubble sort) 鸡尾酒排序(Cocktail sort,双向的冒泡排序) - 插入排序(insertion sort)- 桶排序(bucket sort)- 计数排序(counting sort) - 合并排序(merge sort)- 原地合并排序- 二叉排

《数据结构》中的英语名词

data 数据data element 数据元素data item 数据项data object 数据对象data structure 数据结构ADT (Abstruct Date Type) 抽象数据类型alogrithm 算法correctness 正确性readability 可读性robustness 健壮性frequency count 频度asymptotic time complexity 渐进时间复杂度space complexity 空间复杂度storage density 存

[算法]后缀数组

前言 这篇博客真难写,暂定待更 定义 后缀数组[SuffixArray]是一个一维数组,简称SA,它保存1到n的某个排列\(SA[1] ,SA[2],\dots,SA[n]\),并且保证\(Suffix(SA[i])<Suffix(SA[i+1])\),\(1 \leq i < n\) .也就是将s的n个后缀按字典序从小到大进行排序之后把排好序的后缀的编号顺次放入SA中. 我们先从后缀数组的入门题洛咕P3809讲起 名词解释 后缀[suffix]: ? 类似前缀,在字符串处理中意为对于一个初始

JS - 10大排序算法

/** 冒泡排序(Bubble Sort) **/ function bubbleSort(arr) { var len = arr.length; for (var i = 0; i < len; i++) { for (var j = 0; j < len - 1 - i; j++) { if (arr[j] > arr[j+1]) { //相邻元素两两对比 var temp = arr[j+1]; //元素交换 arr[j+1] = arr[j]; arr[j] = temp; }

排序算法七:基数排序(Radix sort)

上一篇提到了计数排序,它在输入序列元素的取值范围较小时,表现不俗.但是,现实生活中不总是满足这个条件,比如最大整形数据可以达到231-1,这样就存在2个问题: 1)因为m的值很大,不再满足m=O(n),计数排序的时间复杂也就不再是线性的: 2)当m很大时,为计数数组申请的内存空间会很大: 为解决这两个问题,本篇讨论基数排序(Radix sort),基数排列的思想是: 1)将先按照某个基数将输入序列的每个元素划分成若干部分,每个部分对排序结果的影响是有优先级的: 2)先按低优先级排序,再按高优先级

非常无聊——STD::sort VS 基数排序

众所周知,Std::sort()是一个非常快速的排序算法,它基于快排,但又有所修改.一般来说用它就挺快的了,代码一行,时间复杂度O(nlogn)(难道不是大叫一声"老子要排序!!"就排好了么...).我们也知道,不基于比较的排序可以达到O(n),比如说基数排序.什么,它是O(n * log(10)( max(n) ) ) 的?NO!!我们可以用sqrt(max(n))来作为进制,这样就是(N*logMax(n))=O(2*n)的了..看起来很不错, 代码量嘛....呵呵 所谓基数排序,

【算法导论学习-015】基数排序(Radix sort)

1.<算法导论>P197页 8.3节Radix sort 2.java实现 这里仅仅对[算法导论学习-014]计数排序 的参数进行了修改,同时仅仅修改了一行代码. /** * 创建时间:2014年8月17日 下午4:05:48 * 项目名称:Test * @author Cao Yanfeng * @since JDK 1.6.0_21 * 类说明: 利用计数排序实现基数排序 * 条件:待排序的所有数位数相同,注意,即便不相同,也可以认为是最多那个位数,如下面的例子可以认为都是3位数 */ p