排序算法六(基数排序)

Posted fantianliang

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了排序算法六(基数排序)相关的知识,希望对你有一定的参考价值。

一、原理介绍

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

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

二、实例

  对于这样的一系列数据:

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)

  稳定性:稳定

以上是关于排序算法六(基数排序)的主要内容,如果未能解决你的问题,请参考以下文章

经典排序算法和python详解:归并排序快速排序堆排序计数排序桶排序和基数排序

常用排序算法

算法-java代码实现基数排序

十大经典排序算法总结(基数排序)

数据结构-排序之基数排序(使用java代码实现)

数据结构-排序之基数排序(使用java代码实现)