桶排序:
将数字放在数组对应下标的位置,这样一次遍历即可按照顺序输出所有的元素
但是如果数字范围很大,并且分布非常不均匀的话,这样会造成严重的浪费,并且数组的容量有限这样也可能存不开,根据这些不足,我们将其进行改进,形成基数排序
基数排序:
算法实现步骤:
按照个位数进行一次排序,按照十位数进行一次排序,.....重复m次(m为这些数字中最多的位数,(b为进制))。
例:对110,119,7,911,114,120,122进行排序
m 为3
第一趟分配
第一趟收集:
110, 120, 911,122,114,7, 119
第二趟分配:
第二趟收集:
111, 114, 911,119,120,122,7
第三趟分配:
第三趟收集:
7, 111, 114,119,120,122,911
大功告成!!!
基数排序实在是太神奇了:
空间复杂度不大,时间复杂度是常数阶的,并且还稳定!!!,
但是有些特殊情况还是需要处理一下,比如如果有负数怎么办,我采用的是两次排序的方法,负数特殊处理一下
有负数的情况,用vector实现的基数排序Code:
/*
以十进制为底的基数排序
正负数都可以用
*/
#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<vector>
#include<cmath>
#include<cstdlib>
using namespace std;
const int maxn = 100010;
int num1[maxn];
int num2[maxn];
typedef queue<int> Queue;
vector<Queue> V1;
vector<Queue> V2;
void init()
{
for(int i = 0; i <= 9; i++)
{
queue<int> Q;
V1.push_back(Q);
V2.push_back(Q);
}
return ;
}
int main()
{
int n;
init();
scanf("%d", &n);
int maxx1 = 0; //正数排序
int maxx2 = 0; //负数排序
int n1 = 0, n2 = 0;
for(int i = 0; i < n; i++)
{
int x;
scanf("%d", &x);
if(x >= 0)
{
num1[n1++] = x;
int xx = (int)log10((double)x) + 1;
maxx1 = max(xx, maxx1);
}
else
{
x = abs(x);
num2[n2++] = x;
int xx = (int)log10((double)x) + 1;
maxx2 = max(xx, maxx2);
}
}
// 对负数
for(int i = 0; i < maxx2; i++)
{
for(int j = 0; j < n2; j++)
{
int x = (num2[j]/((int)pow(10, i))) % 10;
V2[x].push(num2[j]);
}
int ans = 0;
for(int k = 0; k <= 9; k++)
{
while(!V2[k].empty())
num2[ans++] = V2[k].front(), V2[k].pop();
}
}
//对正数
for(int i = 0; i < maxx1; i++)
{
for(int j = 0; j < n1; j++)
{
int x = (num1[j]/((int)pow(10, i))) % 10;
V1[x].push(num1[j]);
}
int ans = 0;
for(int k = 0; k <= 9; k++)
{
while(!V1[k].empty())
num1[ans++] = V1[k].front(), V1[k].pop();
}
}
for(int i = n2-1; i >= 0; i--)
if(i == n2-1) cout << -1* num2[i];
else cout << " " << -1*num2[i];
for(int i = 0; i < n1; i++)
if(n2 == 0 && i == 0) cout << num1[i];
else cout << " " << num1[i];
return 0;
}