基数排序
这里我们先上原理图
基数排序其实就是对一个数按位进行拆分然后分别排序。具体实现(以三位数为例):我们先排序个位,部分的顺序发生改变。然后我们再对十位进行排列,最后,我们对百位进行排列。
基数排序的实现方法有很多种,在这里我们假设有十个桶,编号分别为0,1,2,3,4,5,6,7,8,9
,如果最大数是三位数,我们就要进行3轮的入桶和出桶操作。排序的顺序从个位开始,逐步到十位,百位。需要我们注意的是,桶实际上类似于队列,就是先进先出。比如我们观察上面gif,出桶时候的顺序都是底部先出的。
我写的基数排序,操作对象是一个顺序表,也就是数组
void RadixSort(int *)
:没有返回值,直接用指针对该地址的变量进行修改。
为了操作更为方便,这里我们需要额外写两个函数来是代码更为简洁。
-
int Kmax(int *)
的功能是,我们传入一个顺序表(数组),我们返回顺序表中最大元素的位数,目的是为了判断我们需要进行多少个回合的入桶、出桶操作。 -
int Knum(int num,int k)
的功能是我们传入一个数num(以234为例),当k为3,返回值为2;当k为1,返回值为4。该函数将在入桶的时候用到
另外,为了方便操作,我们默认被排序的数组A,A[0]
即数组的首元素储存的是元素的个数,例如,当A为空时,A[0]==0
;同理,在桶中,首元素也分别储存着桶中元素的个数。
c++代码如下:
#include <iostream>
using namespace std;
void RadixSort(int *);
int Kmax(int *);
int Knum(int,int);
int main(){
cout<<"请输入数组的大小"<<endl;
int size;
cin>>size;
int *array = new int[size+1];
array[0]=size;
for(int i=0;i<size;i++){
cin>>array[i+1];
}
RadixSort(array);
for(int i=0;i<size;i++){
cout<<array[i+1]<<' ';
}
return 0;
}
//传入一个数组,然后对数组进行修改
//由于在排序的过程中我们需要用到桶,这里我用二维数组来代替桶
void RadixSort(int *array){
//我们创建二维数组A,我们用数组中的首位置来记录该桶中含有元素的个数
int A[10][20];
int size = *(array);//数组元素的个数
//初始化
for(int i=0;i<10;i++){
A[i][0]=0;
}
int max;
//max决定排序的次数
max = Kmax(array);
int n;
int count;
for(int i=1;i<=max;i++){
//入桶
for(int j=1;j<=size;j++){
n = Knum(array[j],i);
count = A[n][0];
A[n][count+1]=*(array+j);
A[n][0]=count+1;
}
//出桶
count = 1;
for(int j=0;j<=9;j++){
int num=1;
if(A[j][0]!=0){
while(A[j][0]!=0){
*(array+count)=A[j][num];
count++;
num++;
A[j][0]--;
}
}
}
}
}
//找出数组中的最大位数
int Kmax(int *array){
int size = array[0];
int max=0;
//赋值
int *copy = new int[size];
for(int i=0;i<size;i++){
*(copy+i)=*(array+i+1);
}
for(int i=0;i<size;i++){
int sum = 0;
while(*(copy+i)!=0){
*(copy+i)/=10;
sum++;
}
if (sum>max)
max = sum;
}
return max;
}
//返回num的第k位数,从右边数
int Knum(int num,int k){
for(int i=1;i<k;i++){
num = num /10;
}
num=num%10;
return num;
}