一、原理介绍
所谓的基数排序算法,即使对于待排序数据,将其看做数据数位相同的数据。
随后一次依据每个数字个位大小排序,重新排序之后,再根据每一个数字的十位大小排序,依次进行,最后数据就可以达到一个整体有序的状态。
二、实例
对于这样的一系列数据:
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