排序算法六(基数排序)

一、原理介绍

  所谓的基数排序算法,即使对于待排序数据,将其看做数据数位相同的数据。

  随后一次依据每个数字个位大小排序,重新排序之后,再根据每一个数字的十位大小排序,依次进行,最后数据就可以达到一个整体有序的状态。

二、实例

  对于这样的一系列数据:

int arr[15] = { 123, 234, 543, 324, 568, 975, 547, 672, 783, 239,124,567,865,579,532 };

  我们依次检索个位,统计每一个数据的个位数,依次放置在 0-9 九个格子里,代表其个位数据。

  这样经历了一次检索以后:

  0-9的格子里数据如图:

  

  蓝色区域代表每一次重新排序以后数据顺序

  黄色代表检索的0-9格子。

  比如第一行黄色,检索个位数字,然后依次放到每一个格子里面。

  依次如图,最后达到了一个完全有序的状态。

三、算法实现。

  首先设计一个数组,cout[10], 代表0-9个格子,记录每一次的遍历之后,相应个位数字的数据数目。

  然后重新排序数组。

  重复上述的过程。

  这里的重新排序很是巧妙。

  比如对于个位数遍历以后我们得到:

  

  这样我们得到的cout数组内容:

  这个时候我们记录每一个 个位数数据在重新排列之后的初始位置。

  它代表的含义是:个位数为2的数字,重新排列以后的位置位于start[0]位置。

        个位数为4的第一个数字,重新排列以后的位置是在start[4]

  可以看到:count和start数组的每一个关系是:

start[i]=count[i-1]+start[i-1];

  这样重新排列的时候,只需要根据每一个数字的个位数,查询start数组,就可以知道自己的位置。

四、代码实现

#include <iostream>
#include <assert.h>
using namespace std;
int GetMaxDigit(int* arr, size_t n)
{
    assert(arr);
    int digit = 1;
    int base = 10;
    for (size_t i = 0; i < n; i++)
    {
        while (arr[i] >= base)
        {
            ++digit;
            base *= 10;
        }
    }
    return digit;
}

void LSDSort(int* arr, size_t n)
{
    assert(arr);
    int base = 1;
    int digit = GetMaxDigit(arr, n);
    int* tmp = new int[n];
    while (digit--)
    {
        int count[10] = { 0 };
        //统计某一位出现相同数字的个数
        for (size_t i = 0; i < n; i++)
        {
            int index = arr[i] / base % 10;
            count[index]++;
        }
        int start[10] = { 0 };
        //统计个位相同的数在数组arr中出现的位置
        for (size_t i = 1; i < 10; i++)
        {
            start[i] = count[i - 1] + start[i - 1];
        }
        //初始化tmp数组
        memset(tmp, 0, n * sizeof(int));
        //从桶中重新排序数据
        for (size_t i = 0; i < n; ++i)
        {
            int index = arr[i] / base % 10;
            tmp[start[index]++] = arr[i];
        }
        //将tmp数组中的元素拷回原数组
        memcpy(arr, tmp, n * sizeof(int));
        base *= 10;
    }
    delete[] tmp;
}
void Print(int* arr, size_t n)
{
    for (size_t i = 0; i < n; i++)
    {
        cout << arr[i] << " ";
    }
    cout << endl;
}
int  main(void )
{
    int arr[15] = { 123, 234, 543, 324, 568, 975, 547, 672, 783, 239,124,567,865,579,532 };
    LSDSort(arr, sizeof(arr) / sizeof(arr[0]));
    Print(arr, sizeof(arr) / sizeof(arr[0]));
    return 0;
}

五、复杂度

  时间复杂度:O(N*digit) //digit代表数据的位数

  空间复杂度:O(N)

  稳定性:稳定

原文地址:https://www.cnblogs.com/fantianliang/p/11904314.html

时间: 2024-10-10 07:30:28

排序算法六(基数排序)的相关文章

经典排序算法之基数排序(C语言版)

排序算法之基数排序的C语言实现. #include "math.h" #include "stdio.h" /* * 基数排序 2016-04-18 23:43:49 * 基数排序的思想:1.求出数组中最大的元素. *   2.求出最大元素是几位数.设为i位. *   3.对所有的数进行i轮排序.首先排个位,然后在十位,然后百位...... *   4.每一轮的排位都需要分桶,桶是有顺序的,然后在把桶里的数按顺序放入原来的数组中. *   5.直到i轮排序结束后,数

排序算法系列——基数排序

基数排序不同于其他的七种排序算法,它是基于一种分配法,而非比较.基数排序属于"分配式排序"(distribution sort),基数排序法又称"桶子法"(bucket sort)或bin sort,顾名思义,它是透过键值的部份资讯,将要排序的元素分配至某些"桶"中,藉以达到排序的作用.它的灵感来自于队列(Queue),它最独特的地方在于利用了数字的有穷性(阿拉伯数字只有0到9的10个). 基本思想: 我们考虑对整数进行基数排序的过程,对于整数,

排序算法之基数排序

概述 首先从多排序码排序开始介绍基数排序.以扑克牌排序为例.每张扑克牌有两个"排序码":花色和面值.其有序关系为: 花色:?<?<?<? 面值:2<3<4<5<6<7<8<9<10<J<Q<K<A 如果把所有扑克牌排成以下次序: ?2,-,?A,?2,-,?A,?2,-,?A,?2,-,?A 这就是多排序码排序.排序后形成的有序序列叫做字典有序序列. 一般情况下,假定有一个n个元素的序列{V0,V

八大排序算法之基数排序

设计思想 它是根据关键字中各位的值,通过对排序的N个元素进行若干趟"分配"与"收集"来实现排序的.它不要比较关键字的大小. 假设:R {50, 123, 543, 187, 49, 30, 0, 2, 11, 100} 任何一个阿拉伯数,它的各个位数上的基数都是以0~9来表示的.所以我们不妨把0~9视为10个桶. 我们先根据序列的个位数的数字来进行分类,将其分到指定的桶中.例如:R[0] = 50,个位数上是0,将这个数存入编号为0的桶中. 分类后,我们在从各个桶中

常见的五类排序算法图解和实现(多关键字排序:基数排序以及各个排序算法的总结)

基数排序思想 完全不同于以前的排序算法,可以说,基数排序也叫做多关键字排序,基数排序是一种借助“多关键字排序”的思想来实现“单关键字排序”的内部排序算法. 两种方式: 1.最高位优先,先按照最高位排成若干子序列,再对子序列按照次高位排序 2.最低位优先:不必分子序列,每次排序全体元素都参与,不比较,而是通过分配+收集的方式. 多关键字排序 例:将下表所示的学生成绩单按数学成绩的等级由高到低排序,数学成绩相同的学生再按英语成绩的高低等级排序.        第一个关键字是数学成绩,第二个关键字是英

各种排序算法比较

各种常用排序算法 类别 排序方法 时间复杂度 空间复杂度 稳定性 复杂性 特点 最好 平均 最坏 辅助存储 简单 插入 排序 直接插入 Insert O(N) O(N2) O(N2) O(1) 稳定 简单 希尔排序 Shell O(N) O(N1.3) O(N2) O(1) 不稳定 复杂 选择 排序 直接选择 Select O(N) O(N2) O(N2) O(1) 不稳定 按理说平均复杂度和最坏复杂度相同是稳定排序.但是:序列5 8 5 2 9,第一遍选择第1个元素5会和2交换,那么原序列中2

各种排序算法时间复杂度

各种排序算法比较 各种常用排序算法 类别 排序方法 时间复杂度 空间复杂度 稳定性 复杂性 特点 最好 平均 最坏 辅助存储 简单 插入 排序 直接插入 O(N) O(N2) O(N2) O(1) 稳定 简单 希尔排序 O(N) O(N1.3) O(N2) O(1) 不稳定 复杂 选择 排序 直接选择 O(N) O(N2) O(N2) O(1) 不稳定 堆排序 O(N*log2N) O(N*log2N) O(N*log2N) O(1) 不稳定 复杂 交换 排序 冒泡排序 O(N) O(N2) O

排序算法七:选择排序之堆排序

排序算法七:选择排序之堆排序 声明:引用请注明出处http://blog.csdn.net/lg1259156776/ 引言 在我的博文<"主宰世界"的10种算法短评>中给出的首个算法就是高效的排序算法.本文将对排序算法做一个全面的梳理,从最简单的"冒泡"到高效的堆排序等. 上博文讲述了选择排序中的简单排序算法,本文介绍的堆排序是树性选择排序,采用堆这个数据结构来辅助排序. 排序相关的的基本概念 排序:将一组杂乱无章的数据按一定的规律顺次排列起来. 数据

【算法】基数排序

计数排序 学习基数排序之前首先学习计数排序. 计数排序假设每个元素都是在0到k之间的一个整数. 基数排序的基本思想,对于每个元素x,如果我们知道了小于x的元素的个数,就可以确定输出数组中元素x的位置,那么直接将元素x放到输出数组中.比如有3小于x的元素,那在输出数组中,x肯定位于第4个位置. 计数排序的算法用伪代码描述为: COUNTING-SORT(A,k) // 初始化数组C for i=0 to k C[i]=0 // 统计A[j]元素出现的次数,保存到C数组中 for j=0 to A.