【四叉树】(boolean矩阵划分树 | 多路树 | RAII | 深拷贝)

  • 一个比较高效和内存友好的四叉树(几何体树、划分树,多道树)
  • 分象限存储boolean矩阵(可扩展为其他数据类型)
  • 可用于图像处理、空间数据索引、2D中的快速碰撞检测、稀疏数据,向量线追踪等场景
  • 由Modern C++ 17/20编写
  • 数据结构本身支持深拷贝,子树创建,查询,插入,批量赋值,控制台输出,遍历等操作
  • 使用智能指针管理,内存安全
#include <functional>
#include <array>
#include <bitset>
#include <memory>
#include <concepts>
#include <cstdint>
#include <cmath>
#include <unordered_map>
#include <stdexcept>
#include <exception>
#include <iostream>

typedef struct {
	std::size_t x1, y1, x2, y2;
} retancgle;
typedef struct {
	std::size_t x, y;
} coordinate;

class BooleanQuad {
		friend std::ostream& operator<<(std::ostream&, const BooleanQuad&);
	public:
		static constexpr std::size_t __CAPACITY__ { 1 << 6 };
		using __value_type__ = bool;
		using __builtin_matrix_type__
		    = std::array<std::bitset<__CAPACITY__>, __CAPACITY__>;
	private:
		__builtin_matrix_type__ matrix {};
		std::size_t dSize {0U};
		struct Node {
			bool __leaf__ {false};
			bool __value__;
			std::shared_ptr<Node> children[4] {nullptr};
		};
		std::shared_ptr<Node> root;
	private:
		void __Hashing__(const std::shared_ptr<Node>& O,
		                 std::unordered_map<std::shared_ptr<Node>, Node *>& hash) {
			if (!O) return;
			hash[O] = new Node{ __leaf__ :
			                    O->__leaf__,
			                    __value__ :
			                    O->__value__ };
			for ( auto i {0U}; i < 4U; ++i)
				__Hashing__(O->children[i], hash);
		}
		void __Rehashing__(const std::shared_ptr<Node>& O,
		                   std::unordered_map<std::shared_ptr<Node>, Node *>& hash) {
			if (!O) return;
			for (auto i {0U}; i < 4U; ++i) {
				hash[O]->children[i]
				    = std::shared_ptr<Node>(hash[O->children[i]]);
				__Rehashing__(O->children[i], hash);
			}
		}
	private:
		std::ostream& output(std::ostream& Os) const {
			Os << std::boolalpha;
			for ( auto i {0U}; i < dSize; ++i) {
				for ( auto j {0U}; j < dSize; ++j)
					Os << '\t' << matrix[i][j];
				Os << '\n';
			}
			return Os;
		}
	public:
		constexpr BooleanQuad(void) noexcept = default;
		BooleanQuad(const BooleanQuad& other)
			: dSize(other.dSize) {
			if (!other.root) return;
			std::unordered_map<std::shared_ptr<Node>, Node *> hash;
			__Hashing__(other.root, hash);
			__Rehashing__(other.root, hash);
			root = std::shared_ptr<Node>(hash[other.root]);
		}
		BooleanQuad& operator=(const BooleanQuad& other) {
			if (this == &other) return *this;
			dSize = other.dSize;
			if (root) root.reset();
			root = BooleanQuad(other).root;
		}

		BooleanQuad& operator=(BooleanQuad&&) noexcept = default;
		template <class Tp, std::size_t N, std::size_t M>
		requires std::convertible_to<Tp, bool>
		constexpr BooleanQuad(Tp (&__matrix)[N][M]) noexcept {
			static_assert(N == M, "dimenssion constraint: rows equals to columns");
			dSize = 1U << static_cast<std::size_t>(std::log2l(N));
			for (auto i {0U}; i < N; ++i) for (auto j {0U}; j < M; ++j)
					matrix[i][j] = static_cast<bool>(__matrix[i][j]);
		}
		BooleanQuad(__builtin_matrix_type__ __matrix)
		noexcept(noexcept(matrix.swap(__matrix)))
			: dSize(1U << static_cast<std::size_t>(std::log2l(__matrix.size()))) {
			matrix.swap(__matrix);
		}
		inline void construct(void) {
			const auto& N { __CAPACITY__ };
			std::array < std::array < uint32_t, __CAPACITY__ + 1 >, __CAPACITY__ + 1 >
			prefix {};
			for (auto i {1U}; i <= N; ++i) for (auto j {1U}; j <= N; ++j)
					prefix[i][j] = prefix[i - 1][j]
					               +  prefix[i][j - 1]
					               -  prefix[i - 1][j - 1]
					               + (int)matrix[i - 1][j - 1];
#define __ARGS__ const coordinate& Os, const coordinate& Ot
#define __COORDINATES__ \
	std::size_t f1 = Os.x;\
	std::size_t e1 = Os.y;\
	std::size_t f2 = Ot.x;\
	std::size_t e2 = Ot.y;
			auto Sum = [&prefix](__ARGS__) {
				__COORDINATES__
				return prefix[f2][e2]
				       - prefix[f2][e1]
				       - prefix[f1][e2]
				       + prefix[f1][e1];
			};
			std::function<std::shared_ptr<Node>(__ARGS__)>
			dfs = [&](__ARGS__) {
				int __Sum = Sum(Os, Ot);
				__COORDINATES__
				return std::shared_ptr<Node>(
				           ! __Sum ?
				           new Node{__leaf__ : true, __value__ : false}
				           : __Sum == (int)((f2 - f1) * (e2 - e1)) ?
				           new Node{__leaf__ : true, __value__ : true}
				: new Node{
						__leaf__ : false,
						__value__ : false,
						children :
					{
						dfs(
						{f1, e1},
						{(f1 + f2) / 2, (e1 + e2) / 2}),
						dfs(
						{f1, (e1 + e2) / 2},
						{(f1 + f2) / 2, e2}),
						dfs(
						{(f1 + f2) / 2, e1},
						{f2, (e1 + e2) / 2}),
						dfs(
						{(f1 + f2) / 2, (e1 + e2) / 2},
						{f2, e2})
					}
				});
			};
			root = dfs({0U, 0U}, {dSize, dSize});
#undef __ARGS__
#undef __COORDINATES__
		}
		BooleanQuad SubQuad(const retancgle& rect) try {
			auto [x1, y1, x2, y2] = rect;
			signed w = x2 - x1;
			signed h = y2 - y1;
			if (!(w >= 0 && h >= 0))
				throw std::invalid_argument("Geometry of rect invalid");
			auto s { 1U << static_cast<std::size_t>(
			             std::log2l(std::max(w, h)) ) };
			BooleanQuad ret;
			ret.dSize = s;
			for ( auto i {0U}; i < s; ++i) for ( auto j {0U}; j < s; ++j)
					ret.matrix[i][j] = matrix[i + x1][j + y1];
			return ret;
		} catch (const std::exception& e) {
			std::cerr << "[trace-back] recently called at BooleanQuad::SubQuad() :\t"
			          << e.what()
			          << '\n';
		}
		constexpr bool
		Query( const coordinate& p) const {
			return matrix.at(p.x)[p.y];
		}
		constexpr std::size_t
		size(void) const noexcept {
			return dSize;
		}
};
inline std::ostream&
operator<<(std::ostream& Os, const BooleanQuad& Q) {
	return Q.output(Os);
}

 

 

  • 14
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为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、付费专栏及课程。

余额充值