1. 计数排序
输入:待排序数组 vec
输出:排序结果数组 res
占用额外空间:max_value(vec) 大小的数组
void countSort(vector<int> & vec,vector<int> & result)
{
vector<int> c_vec;
result.resize(vec.size());
for (auto val : vec)
{
if (c_vec.size() <= val + 1) //范围为0~n的数据,共有 n + 1 种取值,包含0
c_vec.resize(val + 1,0);
c_vec[val] += 1;
}
//adjust c_vec
for (int i = 1; i != c_vec.size(); ++i)
c_vec[i] += c_vec[i - 1];
//adjust
for (auto val : vec) //此时从后往前遍历 vec 并放入元素,则计数排序的结果是稳定的。按照当前写法不稳定
{
result[c_vec[val]-1] = val; //当前排名为n 的数据,在vec 中的下标为[n-1],下标从0开始
--c_vec[val];
}
}
2.基数排序
输入:待排序数组
void radixSort(vector<int>& vec)
{
vector<int> tmp(vec.size(), 0);
vector<int> bucket(10, 0); //桶中存放 0 ~ 9
int max_num = INT_MIN; //用来统计最高位,用于终止循环
std::for_each(vec.begin(), vec.end(), [&max_num](int i)mutable{if (i > max_num) max_num = i; });
int bits_count = 1;
while ((max_num / bits_count))
{
//获取位数
for (auto val : vec)
bucket[(val / bits_count) % 10] += 1;
//统计排序
for (size_t i = 1; i != bucket.size(); ++i)
bucket[i] += bucket[i - 1];
//根据统计的排序值,将值放入临时存储区。**特别注意此处必须从后往前找数据,因为根据计数的原理,桶中的排序是从后往前的
for (auto iter = vec.rbegin(); iter != vec.rend(); ++iter)
{
int val = *iter;
tmp[bucket[(val / bits_count) % 10] - 1] = val;
--bucket[(val / bits_count) % 10];
}
//将临时存储区的值转回原存储
for (size_t i = 0; i != tmp.size(); ++i)
vec[i] = tmp[i];
//清空桶
for (auto & val : bucket)
val = 0;
//累计当前值
bits_count *= 10;
}
}
3.桶排序
输入:在[0~1)均匀分布的浮点数
稳定性:稳定
struct Node
{
double fval;
shared_ptr<Node> next;
shared_ptr<Node> prev;
Node(float f) :fval(f), next(nullptr), prev(nullptr){}
};
//对 [0,1) 内均匀分布的小数进行排序
void bucketSort(vector<double> &vec)
{
map<int, shared_ptr<Node>> bucket; //桶,每个桶中放了一个链表,链表中的元素使用插入排序
for (auto fval : vec)
{
int bits = static_cast<int>(fval * 10) % 10; //取出小数点后第一位
shared_ptr<Node> point(new Node(fval)); //构造新节点,用智能指针控制堆内存的释放
shared_ptr<Node> root = bucket[bits]; //取出当前桶的根节点
if (root == NULL) //空桶,放入第一个元素即可
{
bucket[bits] = point;
continue;
}
shared_ptr<Node> prev = NULL,curr = root; //开始插入排序
while (curr != NULL)
{
if (curr->fval <= fval) //迭代器向后移动 备注:使用小于等于保持稳定性
{
prev = curr;
curr = curr->next;
}
else
break;
}
point->prev = prev; //将当前结点接入链表
point->next = curr;
if (prev != NULL) //头节点为空,则当前节点应该为桶中的根节点
prev->next = point;
else
bucket[bits] = point; //替换掉根节点
if (curr != NULL)
curr->prev = point; //接入链表中
}
size_t index = 0;
for (auto iter = bucket.begin(); iter != bucket.end(); ++iter) //map 按关键字 0 ~ 9 自动排序,即是取出按桶的顺序取出
{
shared_ptr<Node> root = iter->second;
while (root != NULL)
{
vec[index++] = root->fval; //获取值
root = root->next;
}
}
}