这两种排序方法是不需要比较的排序方法。下面我来一个一个介绍
1.基数排序
基本算法:遍历一遍原数组,将其每个元素出现的次数用一个足够容纳其范围的数组来标记,即统计每个元素出现了多少次,然后在遍历这个标记数组来还原原数组,这样就拍好序了
下面给出算法代码:
void CoutSort(int arr[], int size)
{
//统计最大最小的元素
int Maxdata = arr[0];
int Mindata = arr[0];
for (int i = 0; i < size; i++)
{
if (arr[i]>Maxdata)
Maxdata = arr[i];
if (arr[i] < Mindata)
Mindata = arr[i];
}
//开辟新的空间
int _size = Maxdata - Mindata + 1;
int *temp = new int[_size];
memset(temp, 0, _size*4);
//遍历原数组统计每个数字出现的次数
for (int i = 0; i < size; i++)
temp[arr[i] - Mindata]++;
//遍历temp复原给原数组
int index = 0;
for (int i = 0; i < _size; i++)
{
while (temp[i]--)
{
arr[index++] = i + Mindata;
}
}
delete[] temp;
}
很简单,参考给出的步骤去理解。
2.基数排序
’基数排序法又称筒子法,就是先从个位数字比较然后将其放到对应的桶中,然后在将其按顺序拿出放回原数组,这样每个元素的个位数字就已经排好了,然后在将十位放入对应的筒子中,重复上述步骤,直到所有位数比较完,这个时候数组就拍好序了
直接上代码:
void RadixSort_LSD(int *arr, int size)
{
//1.首先需要统计这些数中最大元素的位数,%10取个位,/10少一位
int count = 1;//最起码一位数
int elem = 1;
int radix = 10;
int *temp = new int[size];
for (int i = 0; i < size; i++)
{
while (arr[i]>radix)
{
count++;
radix *= 10;
}
}
//因为有三位数所以整三次就可以了
//第一次比较个位,第二次比较十位,第三次比较百位
for (int index = 0; index < count; index++)
{
//首先统计个位的每个位数出现的次数
int Count[10] = { 0 };//最大0-9
for (int i = 0; i < size; i++)
{
Count[arr[i] / elem % 10]++;
}
//计算每个元素个位数字应该所在的位置即每个元素所在的位置
int Postion[10] = { 0 };
for (int i = 1; i < 10; i++)
{
Postion[i] = Postion[i - 1] + Count[i - 1];
}
//将其放在对应的位置
for (int i = 0; i < size; i++)
{
int ret = arr[i] / elem % 10;
temp[Postion[ret]++] = arr[i];
}
//考回至原数组
memcpy(arr, temp,sizeof(arr[0])*size);
elem *= 10;
}
delete[] temp;
}
从百位到个位
void RadixSort_MSD(int *array, int left,int right,int bit,int *bucket)
{
if (bit <= 0)
return;
int elem = (int)pow(10, bit-1);
//统计每个桶中元素的出现次数数-->计算每个桶的起始地址
int BuckCount[10] = { 0 };
for (int i =left; i < right; ++i)//统计每个桶中元素个数从百位开始
{
BuckCount[array[i] / elem % 10]++;
}
int StartAddr[10] = {left};
for (int i = 1; i < 10; i++)//统计每个桶的起始位置
{
StartAddr[i] = StartAddr[i - 1] + BuckCount[i - 1];
}
//将各个元素放置到对应的桶中
for (int i = left; i < right; ++i)
{
int BuckNo = array[i] / elem % 10;//桶号
bucket[StartAddr[BuckNo]++] = array[i];
}
//回收
memcpy(array+left, bucket+left, sizeof(array[0])*(right-left));
//分别排每个桶中的内容
for (int i = 0; i < 10; ++i)
{
int begin = StartAddr[i]-BuckCount[i];
int end =StartAddr[i] ;
if (begin+1<end)
RadixSort_MSD(array, begin,end ,bit - 1,bucket);
}
}