桶排序
基本思想
先扫描得到待排序数组中的最大值maxVal与最小值minVal,假设桶的个数为k,则代表则将[minVal, maxVal]均分为k个范围,每个范围中的元素各自放入对应的桶中。如此桶之间必然是有序的,桶内使用排序算法进行排序,最后按序收集所有桶的元素,即完成桶排序;
复杂度
- 时间复杂度
总的时间复杂度为 O(n)+O(k)O(n/klog(n/k)) = O(n+nlog(n/k))
当 k 接近于 n 时,桶排序的时间复杂度就可以金斯认为是 O(n) 的。即桶越多,时间效率就越高,而桶越多,空间就越大。 - 空间复杂度:O(n+k)
源码
//桶排序
//b表示需要nums.size()/b个桶;
void BucketSort(vector<int>& nums, int b=1) {
if (nums.size() < 2) return;
int maxVal = INT32_MIN;
int minVal = INT32_MAX;
for (int i = 0; i < nums.size(); ++i) {
maxVal = max(maxVal, nums[i]);
minVal = min(minVal, nums[i]);
}
int k = (maxVal - minVal + b) / b;
vector<vector<int>>buckets(k);
//分配
for (int i = 0; i < nums.size(); ++i) {
int index = (nums[i] - minVal) / b;
buckets[index].push_back(nums[i]);
}
int index = 0;
//桶内排序与收集
for (int i = 0; i < buckets.size(); ++i) {
//使用其他排序方法进行桶内排序
sort(buckets[i].begin(), buckets[i].end());
for (auto& val : buckets[i])
nums[index++] = val;
}
}
计数排序
基本思想
先扫描得到待排序数组中的最大值maxVal与最小值minVal,之后分配一个长度为 maxVal-minVal+1 的计数数组,之后扫描待排序元素,将其所在的计数数组的位置加一。最后再扫描一遍计数器数组,按顺序把值收集起来。
注:计数排序实际上是桶排序的一种特例,即k=maxVal-minVal+1;
复杂度
- 时间复杂度:
平均:O(n+k);最好:O(n+k);最坏:O(n+k) - 空间复杂度:O(k)
源码
//计数排序
void CountSort(vector<int>& nums) {
if (nums.size() < 2) return;
int maxVal = INT32_MIN;
int minVal = INT32_MAX;
for (int i = 0; i < nums.size(); ++i) {
maxVal = max(maxVal, nums[i]);
minVal = min(minVal, nums[i]);
}
int k = maxVal - minVal + 1;
vector<int>count(k);
//计数
for (int i = 0; i < nums.size(); ++i)
++count[nums[i] - minVal];
int index = 0;
//收集
for (int i = 0; i < count.size(); ++i) {
while (count[i] > 0) {
nums[index++] = i + minVal;
--count[i];
}
}
}
基数排序
基本思想
从最低位开始,按照该位的大小进行一次稳定排序,再对下一位进行稳定排序,直至最高位结束;
注:一般会开辟一个大小为10的桶,将元素按照个位/十位/…放入对应位置,进行稳定排序;
复杂度
- 时间复杂度:
平均:O(nxk);最好:O(nxk);最坏:O(nxk)
注:k表示待排序元素中最大的位数 - 空间复杂度:O(n+k)
源码
//基数排序
void RadixSort(vector<int>&nums) {
//最大位数
int k = 0;
for (int i = 0; i < nums.size(); ++i)
k = max(int(log(nums[i])) + 1, k);
for (int i = 0; i < k; ++i) {
//十进制
vector<vector<int>>radix(10);
//分配
for (int j = 0; j < nums.size(); ++j) {
int index = int(nums[j] / pow(10, i)) % 10;
radix[index].push_back(nums[j]);
}
int index = 0;
//收集
for (int j = 0; j < radix.size(); ++j) {
for (auto& r : radix[j]) {
nums[index++] = r;
}
}
}
}