参考链接:https://blog.csdn.net/qq_19446965/article/details/81517552
桶排序
- 首先求出最大值最小值,把此区间划分为k个区间(即k个桶),再分别对桶内元素进行排序,将桶内元素合并得到排序结果。
- 假设数据均匀分布,每个桶内元素为 n/k 个,并对桶内元素通过快排排序,每次排序复杂度为O(n/k log(n/k)),总的时间复杂度为O(n) + O(k)*O(n/k log(n/k))=O(n) + O(n log(n/k)),当k接近n时,复杂度可以认为是 O(n)
- 桶排序的复杂度与建桶的效果紧密相连,常见的建桶思路为将最大值最小值之间的区间平分,或桶的个数为 2^n,10^n
- 分治思想
基数排序
- 非比较算法
- 将所有待排整数统一为位数相同的整数(常见的为非负整数,对代码稍作修改,负整数也可通过基数排序进行排序)
- 从最低位或最高位开始一次进行稳定排序,完成之后整个序列即为一个有序序列
计数排序
- 以空间换时间
- 遍历数组统计每个数出现的次数,根据统计结果写回数组
- 是一种特殊的桶排序,当桶的个数最大时,桶排序即为计数排序
复杂度比较
//d为k进制下最长的位数
代码实现
代码实现思路与:https://www.cs.usfca.edu/~galles/visualization/Algorithms.html
基本一致
//sort
#include<iostream>
#include<vector>
#include<math.h>
#include<algorithm>
using namespace std;
void bucketSort(vector<int> &arr){
//将min和max等分成n份
int low=999999999;
int high=-999999999;
for(int i=0;i<arr.size();i++){
low=min(low,arr[i]);
high=max(high,arr[i]);
}
int size=(high-low)/10+1; //一个桶的区间大小
vector<int> bucket[10];
for(int i=0;i<arr.size();i++){
int index=(arr[i]-low)/size;
bucket[index].push_back(arr[i]);
}
for(int i=0;i<10;i++){
int bsize=bucket[i].size();
sort(bucket[i].begin(),bucket[i].end());
}
int index=0;
for(int i=0;i<10;i++){
for(int j=0;j<bucket[i].size();j++){
arr[index]=bucket[i][j];
index++;
}
}
}
//基数排序
//从低位开始排序
void redixSort(vector<int> &arr){
int maxx=-999999999;
for(int i=0;i<arr.size();i++){
maxx=max(maxx,arr[i]); //获取最大值
}
int exp=10;
while(maxx/exp!=0){
exp*=10; //获取最大值的位数
}
vector<int> bucket[10];
int exp2=10;
while(exp2<=exp){
for(int i=0;i<arr.size();i++){
bucket[(arr[i]%exp2)/(exp2/10)].push_back(arr[i]); //放到对应的桶中
}
int index=0;
for(int i=0;i<10;i++){
for(int j=0;j<bucket[i].size();j++){
arr[index]=bucket[i][j];
index++;
}
bucket[i].clear(); //因为桶是重复使用的,所以在一轮结束之后注意将桶清空
}
exp2*=10;
}
}
//考虑负数,从低位开始排序
//将桶的大小扩展到20个即可
void redixSortp(vector<int> &arr){
int maxx=-999999999;
for(int i=0;i<arr.size();i++){
maxx=max(maxx,arr[i]); //获取最大值
}
int exp=10;
while(maxx/exp!=0){
exp*=10; //获取最大值的位数
}
vector<int> bucket[20];
int exp2=10;
while(exp2<=exp){
for(int i=0;i<arr.size();i++){
bucket[(arr[i]%exp2)/(exp2/10)+10].push_back(arr[i]); //放到对应的桶中
}
int index=0;
for(int i=0;i<20;i++){
for(int j=0;j<bucket[i].size();j++){
arr[index]=bucket[i][j];
index++;
}
bucket[i].clear(); //因为桶是重复使用的,所以在一轮结束之后注意将桶清空
}
exp2*=10;
}
}
void countSort(vector<int>& arr){
int maxx=-999999999;
int minn=999999999;
for(int i=0;i<arr.size();i++){
maxx=max(maxx,arr[i]);
minn=min(minn,arr[i]);
}
int size=maxx-minn+1;
int count[size]={0};
for(int i=0;i<arr.size();i++){
count[arr[i]-minn]++;
}
int index=0;
for(int i=0;i<size;i++){
for(int j=0;j<count[i];j++){
arr[index]=i+minn;
index++;
}
}
}
int main(){
int a[20]={45,95,23,78,21,2,5,0,-69,5,9,159,87,65,25,-56,56,56,57,100};
vector<int> arr(a,a+20);
// bucketSort(arr);
redixSortp(arr);
// countSort(arr);
for(int i=0;i<20;i++){
cout<<arr[i]<<" ";
}
}