一、计数排序-----鸽巢原理
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:高关键码优先