千奇百怪的排序算法
快速排序
采用左闭右开的二分写法
归并排序
插入排序
冒泡排序
选择排序
以上代码的调用方式:
快速选择
在一个未排序的数组中,找到第 k 大的数字
快速选择一般用于求解 k-th Element 问题,可以在 O(n) 时间复杂度,O(1) 空间复杂度完成求 解工作。快速选择的实现和快速排序相似,不过只需要找到第 k 大的枢(pivot)即可,不需要对 其左右再进行排序。与快速排序一样,快速选择一般需要先打乱数组,否则最坏情况下时间复杂 度为 O(n 2 )
第K个数算法-CSDN博客
参考之前写的博客
桶排序
桶排序的意思是为每个值设立一个桶,桶内记录这个值出现的次数(或其它属 性),然后对桶进行排序。针对样例来说,我们先通过桶排序得到四个桶 [1,2,3,4],它们的值分别 为 [4,2,1,1],表示每个数字出现的次数。
紧接着,我们对桶的频次进行排序,前 k 大个桶即是前 k 个频繁的数。这里我们可以使用各种 排序算法,甚至可以再进行一次桶排序,把每个旧桶根据频次放在不同的新桶内。针对样例来说, 因为目前最大的频次是 4,我们建立 [1,2,3,4] 四个新桶,它们分别放入的旧桶为 [[3,4],[2],[],[1]], 表示不同数字出现的频率。最后,我们从后往前遍历,直到找到 k 个旧桶。
priority_queue<pair<int, int>, vector<pair<int, int>>, decltype(&cmp)> q(cmp);
优先队列的定义
template<
class T,
class Container = std::vector<T>,
class Compare = std::less<typename Container::value_type>
> class priority_queue;
static bool cmp(pair<int, int>& m, pair<int, int>& n) {
return m.second > n.second;
}
std::priority_queue 是一个模板类,有三个模板类型参数,分别是:
- 参数1: 优先级队列的元素类型 T ,例如问题里第一个例子,元素类型 T 是 std::pair<int,int> ,后面两个例子,元素类型 T 是 int
- 参数2: 优先级队列内部具体用那种容器(Container) 存储参数1指定的元素类型,例如问题里的 vector< pair<int,int> > 和 vector<int>。实际上,第2个模板参数是有默认类型参数的,默认类型参数是 vector<T> ,T 取决于参数1指定的类型是什么。
- 参数3: 参数3需要指定一个实现了 operator< 操作符的类(叫做仿函数或者函数对象,实际上就是类,只是调用时写起来像函数一样),比较操作符的实现符合 严格弱顺序 strict weak order 语义,请参考资料3。模板参数3也是有默认类型,默认是 std::less<typename Container::value_type> ,其中 Container 指的是参数2,Container::value_type 指的是参数2类内部的声明的其元素值的类型。
- 最后,decltype 用于类型自动推断,传入&cmp函数指针,decltype自动推断出第3个模版参数类型应该是什么。总的来说,如果你的元素类型已经符合严格弱顺序排序,只要自定优先级队列的第1个模版参数即可。
参考博客:
c++优先队列priority_queue(自定义比较函数)_c++优先队列自定义比较_菊头蝙蝠的博客-CSDN博客
c++优先队列(priority_queue)用法详解_吕白_的博客-CSDN博客
练习
排序也可以这样写
sort(vec.begin(), vec.end(), [](const pair<char, int> &a, const pair<char, int> &b) {
return a.second > b.second;
});
一切皆可搜索
深度优先搜索和广度优先搜索是两种最常见的优先搜索方法,它们被广泛地运用在图和树等 结构中进行搜索。