一、计数排序
很好理解,就是对应每个数我们统计每个数字出现的次数,然后用一个直接定址的哈希表来存放数据,在通过遍历这个哈希表,进而就可以排好序了
如下所示:
代码实现如下所示:
void CountSort(int *array, int size)
{
assert(array || size < 0);
int minData = array[0];
int maxData = array[0];
//确定数据元素的范围
for (int i = 1; i < size; ++i)
{
if (array[i] < minData)
minData = array[i];
else if (array[i] > maxData)
maxData = array[i];
}
//开辟辅助空间
int range = maxData - minData + 1;
int *pCount = new int[range];
memset(pCount, 0, range*sizeof(int));
//统计每个字符出现的次数
for (int i = 0; i < size; ++i)
{
pCount[array[i] - minData]++;//在此处开辟的区间,是一段连续的数组,下标从0开始
}
//回收已经统计好的字符
int index = 0;
for (int i = 0; i < range; ++i)
{
while (pCount[i]--)
array[index++] = i + minData;
}
delete[] pCount;
}
二、基数排序
(一)低关键码排序
从个位到最高位(例如:最大的数为12345,那么最高位便为万位),每次由高从低到高进行排序。排完最高为之后,整个序列就变得有序了
如图所示:
代码如下所示:
//获取最大数的比特位的位数
int GetBitCount(int *array, int size)
{
int radix = 10;
int count = 1;
for (int i = 0; i < size; ++i)
{
if (radix < array[i])
{
count++;
radix *= 10;
}
}
return count;
}
//基数排序-----非比较排序2----低关键码排序
void RadixSort_LSD(int*array, int size)
{
assert(array || size < 0);
//获取最大数的比特位
int bitCount = GetBitCount(array, size);
int radix = 1;
int*bucket = new int[size];//辅助空间,
for (int idx = 0; idx < bitCount; ++idx)
{
int bucketCount[10] = { 0 };//存放计数的数组
//统计每个桶中元素的个数
for (int i = 0; i < size; ++i)
{
int index = array[i] / radix % 10;
//如果是负数,将其放在0号桶的位置
if (index < 0)
{
bucketCount[0]++;
}
else
{
bucketCount[index]++;//以每一位的形式将元素统计
}
}
//计算每个桶的起始地址
int startAddr[10] = { 0 };
for (int i = 1; i < 10; ++i)//表示10个桶
{
startAddr[i] = startAddr[i - 1] + bucketCount[i - 1];
}
//将对应元素放置到对应的桶中
for (int i = 0; i < size; ++i)
{
//计算桶号
int bucketNo = array[i] / radix % 10;
if (bucketNo < 0)
{
if (array[i] > array[i + 1])
swap(array[i],array[i + 1]);
bucket[startAddr[0]++] = array[i];
}
else
{
//将对应元素放置到对应的桶中
bucket[startAddr[bucketNo]++] = array[i];
}
}
//回收元素
memcpy(array, bucket, size*sizeof(array[0]));
//下面再来排百位等....
radix *= 10;
}
}
(二)搞关键码排序
代码如下所示:
void _RadixSort_MSD(int*array, int left, int right, int bit, int* bucket)
{
assert(array);
if (bit <= 0)
return;
int radix = (int)pow((double)10, bit - 1);
// 统计每个桶中元素的个数
int bucketCount[10] = { 0 };
for (int i = left; i < right; ++i)
bucketCount[array[i] / radix % 10]++;
// 统计每个桶的起始地址
int startAddr[10] = { left };
for (int i = 1; i < 10; ++i)
startAddr[i] = startAddr[i - 1] + bucketCount[i - 1];
// 将各元素放置到对应的桶中
for (int i = left; i < right; ++i)
{
int bucketNo = array[i] / radix % 10;
bucket[startAddr[bucketNo]++] = array[i];
}
// 回收
memcpy(array + left, bucket + left, (right - left)*sizeof(array[0]));
for (int i = 0; i < 10; ++i)
{
int begin = startAddr[i] - bucketCount[i];
int end = startAddr[i];
if (begin + 1 < end)
_RadixSort_MSD(array, begin, end, bit - 1, bucket);
}
}
void RadixSort_MSD(int *array, int size)
{
int* tmp = new int[size];
int bit = GetBitCount(array, size);
_RadixSort_MSD(array, 0, size, bit, tmp);
delete[] tmp;
}
缺点:对负数不能进行排序,需要进行特殊的处理,因此会比较麻烦。
有关非比较排序就这么多内容,希望大家一起进步!!!
只有不停的奔跑,才能不停留在原地!!!