一、计数排序-----鸽巢原理
1、找范围
2、给出辅助空间(空间中记录每条数据出现的次数)
3、整体遍历一遍数据,统计每一个数据出现的次数
4、回收数据(回收到原空间):根据下标,给出存储在该下标下的数据
假设范围为M到n,则:
时间复杂度:O(3n)即O(n)
空间复杂度:借助了一个辅助空间O(n)
场景:数据密集的集中在某一个范围内
1、找范围
2、给出辅助空间(空间中记录每条数据出现的次数)
3、整体遍历一遍数据,统计每一个数据出现的次数
4、回收数据(回收到原空间):根据下标,给出存储在该下标下的数据
假设范围为M到n,则:
时间复杂度:O(3n)即O(n)
空间复杂度:借助了一个辅助空间O(n)
场景:数据密集的集中在某一个范围内
实现代码:
//一个数密集的集中在哪个范围,但是没有给定范围
void CountSort(int *array, int size)
{
//计算范围
int maxValue = array[0];
int minValue = array[0];
int i = 0;
int range = 0;//辅助空间的大小
int index = 0;
int *Count = NULL;//计数空间
for (i = 0; i < size; ++i)
{
if (array[i]>maxValue)
maxValue = array[i];
if (array[i] > minValue)
minValue = array[i];
}
//计算空间的大小
range = maxValue - minValue + 1;
int tmp = (int *)malloc(range*sizeof(int));
if (NULL == tmp)
{
assert(0);
return;
}
memset(Count, 0, range*sizeof(int));//初始化
//排序
for (i = 0; i < size; ++i)
{
Count[array[i-minValue]++];//记录每个下标为i的元素下的数据个数
}
//回收辅助空间中的元素
for (i = 0; i < range; ++i)
{
while (Count[i]--)
{
array[index++] = i + minValue;
}
}
//释放空间
free(tmp);
}
二、基数排序(多关键码排序):按照不同的关键码排序,其结果不一样。
(1)LSD:低关键码优先
将数据放入对应的桶中
回收(先放谁,就先回收谁)可以通过队列的方式实现,但是需要多个队列
(1)LSD:低关键码优先
将数据放入对应的桶中
回收(先放谁,就先回收谁)可以通过队列的方式实现,但是需要多个队列
优化:给出一个辅助空间,空间有n个元素
第一步:统计每个桶中元素的个数
第二步:计算每个桶的起始位置
第三步:将元素放到对应的桶中
第二步:计算每个桶的起始位置
第三步:将元素放到对应的桶中
代码如下:
//计算最大的数据占多少比特位
int GetBitCount(int *array, int size)
{
int count = 1;//数据只要存在,至少有一位
int i = 0;
int radix = 10;//默认从10开始
for (i = 0; i < size; ++i)
{
while (array[i] >= radix)
{
++count;
radix *= 10;
}
}
return count;
}
void _RadixSort(int *array, int size, int *Bucket)
{
int i = 0;
int bitCount = GetBitCount(array, size);
int bitIdx = 0;//统计哪一位(位0统计个位)
int radix = 1;//判断取个位还是取十位
for (bitIdx = 0; bitIdx < bitCount; bitIdx++)//统计的是个位还是十位……
{
//统计每个桶中元素的个数
int Count[10] = { 0 };
int startAddr[10] = { 0 };//起始地址
for (i = 0; i < size; ++i)//
{
Count[array[i]/radix % 10]++;
}
//计算每个桶的起始地址(上一个桶的起始位置加上元素的个数
for (i = 1; i < 10; ++i)
{
startAddr[i] = startAddr[i - 1] + Count[i - 1];
}
//放置元素到辅助空间
for (i = 0; i < size; ++i)
{
int bucketNo = array[i] % 10;//计算桶号
Bucket[startAddr[bucketNo]++] = array[i];
}
//对数据进行回收
memcpy(array, Bucket, size*sizeof(array[0]));
radix *= 10;
}
}
void RadixSort(int *array, int size)
{
//申请辅助空间
int *Bucket = (int *)malloc(size*sizeof(array[0]));
if (NULL == Bucket)
{
assert(0);
return;
}
_RadixSort(array, size, Bucket);
free(Bucket);
}
(2)MSD:高关键码优先