【维护中位数的工具类 MedianHolder】(对顶堆 | templateADT | 批处理)

8ecb499ea2c542be9c25abcf986dd70b.png

单元测试

//median返回类型
using result_type
	= typename MedianHolder<int>::return_type;
//自定义矩阵类型
template <std::size_t N>
using integer_matrix
	= std::array<std::initializer_list<int>, N>;

int main(void){
//测试数据组
	integer_matrix<5> test = {{
	    {9, 6, 3, 8, 4, 7, 1, 2, 5, 0},
	    {2, 5, 8, 3, 6, 7, 4, 9, 0, 1},
	    {4, 8, 2, 3, 9, 0, 5, 1, 7, 6},
	    {3, 9, 7, 8, 5, 2, 1, 6, 4, 0},
	    {1, 7, 2, 6, 5, 8, 0, 4, 3, 9}
	}};
	for(auto& row : test){
//先展示数字序列
		std::copy(row.begin(), row.end(), std::ostream_iterator<int>(std::cout, "|"));
		std::endl(std::cout);
//输出中位数(奇数一位,偶数两位)
		std::cout << "Median:\t";
		result_type res = MedianHolder<int>(row);
		if(res.first) std::cout << *res.first << ' ';
		std::cout << res.second << "\n\n";
	}
	return 0;
}
#include <queue>
#include <iterator>
#include <functional>
#include <algorithm>
#include <deque>
#include <concepts>
#include <initializer_list>
#include <iostream>
#include <array>

template <class Ty,
		  class Lesser = std::less<Ty>>
	requires std::strict_weak_order<Lesser, Ty, Ty> //可自定义可调用拟序谓词
class MedianHolder{
static_assert(std::same_as<typename std::decay<Ty>::type, Ty>);
//静态断言:Ty should be non-volatile & non-const
static_assert(std::assignable_from<Ty&, Ty>
|| 			  std::assignable_from<const Ty&, Ty>);
//静态断言:const_assignable自然可赋值
public:
struct Greater
: public std::binary_function<Ty, Ty, bool>{
	constexpr bool
	operator()(const Ty& x, const Ty& y) const
	{ return !Lesser{}(x, y); }
};
//大于等于谓词
protected:
//对顶堆 分别维护左区间和右区间
	std::priority_queue<Ty, std::deque<Ty>, Lesser> Left;
	std::priority_queue<Ty, std::deque<Ty>, Greater> Right;
private:
	std::size_t dSize {0U};
public:
	constexpr MedianHolder(void) noexcept = default;
	MedianHolder& operator=(const MedianHolder&) = default;
	MedianHolder& operator=(MedianHolder&&) noexcept = default;
//宽类型转换构造 初始化列表一次性批量构造
	template <typename Up>
	inline MedianHolder(std::initializer_list<Up> ilist) {
		for(auto& t : ilist) push(t);
	}
//一个元素push,宽类型检查
	template <class Up,
			  class = typename
			  std::enable_if<
			  std::convertible_to<Up, Ty>>::type>
		requires (requires(Ty x, Up y){
			{Lesser{}(x, y)} -> std::convertible_to<bool>;
		})
	void push( const Up& x){
		if(Right.empty() || Greater{}(x, Right.top())){
			Right.push(x);
			if(Left.size() < Right.size() + 1U){
				Left.push(Right.top());
				Right.pop();
			}
		}else{
			Left.push(x);
			if(Left.size() > Right.size()){
				Right.push(Left.top());
				Left.pop();
			}
		}
	}
//形参包展开,批量push接口
	template <class... Args>
	constexpr void batch_push(Args&&... args)
	noexcept((noexcept(push(args))&&...)){
		(((void)push(args)), ...);
	}
//公开返回类型
	using return_type = std::pair<std::optional<Ty>, Ty>;
//返回中位数
	constexpr inline return_type
	median(void) const{
		return {
			Right.size() > Left.size()
			? std::nullopt
			: std::make_optional(Left.top())
			, Right.top()};
	}
//隐式转换,方便输出比较等操作
	constexpr operator return_type() const{
		return std::move(median());
	}
};
//推导指引,构造时可以不指定模板参数
template <class Up>
MedianHolder(std::initializer_list<Up> ilist)
->MedianHolder<Up>;

 

 

  • 16
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

XNB's Not a Beginner

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值