四叉树简单实现

该文章详细介绍了如何使用C++实现一个基于四叉树的数据结构QuadTrie,用于存储和组织矩形区域。它包含插入矩形到正确象限的逻辑,以及在不同象限之间划分和管理子节点的方法。QuadTrie结构优化了空间效率,当容器中矩形数量小于3时,它们会存储在节点的container中,否则将矩形分发给子节点。
摘要由CSDN通过智能技术生成

//待完善

#include<iostream>
#include<vector>
#include <algorithm>
#include <set>
using namespace std;

//象限位置
enum QuadRant
{
	TOPR,
	TOPL,
	BOTTL,
	BOTTR
};

struct QuadRect
{
	double top;
	double left;
	double right;
	double bottom;
	double midH;
	double midV;
	QuadRect() {}
	QuadRect(double _top, double _left, double _right, double _bottom)
	{
		top = _top;
		left = _left;
		right = _right;
		bottom = _bottom;
		midH = (_top + _bottom) / 2;
		midV = (_left + _right) / 2;
	}

	bool operator== (QuadRect& rect)
	{
		return rect.top == top
			&& rect.bottom == bottom
			&& rect.right == right
			&& rect.left == left;
	}
};

struct QuadNode
{
public:
	QuadRect rect;
	vector<QuadRect>* container;
	QuadNode* children[4];
	int childCount;
	QuadNode(QuadRect _rect)
	{
		rect = _rect;
		container = new vector<QuadRect>();
		childCount = 0;
		for (int i = 0; i < 4; ++i)
			children[i] = nullptr;
	}

	~QuadNode()
	{
		if (container)
			delete container;
		container = nullptr;
		for (int i = 0; i < 4; ++i)
		{
			if (children[i])
				delete children[i];
			children[i] = nullptr;
		}
	}
};

struct QuadTrie
{
private:
	QuadNode* root;	
	
	//value 在区间内
	bool isInSection(double start, double end, double value)
	{
		return value >= start && value <= end;
	}
	//获取目标象限Rect
	QuadRect getRect(QuadRect rect, QuadRant target)
	{
		switch (target)
		{
		case TOPR:
			return QuadRect(rect.top, rect.midV, rect.right, rect.midH);
		case TOPL:
			return QuadRect(rect.top, rect.left, rect.midV, rect.midH);
		case BOTTL:
			return QuadRect(rect.midH, rect.left, rect.midV, rect.bottom);
		case BOTTR:
			return QuadRect(rect.midH, rect.midV, rect.right, rect.bottom);
		}
	}
	//向子节点插入
	void insertBranch(QuadNode* node, QuadRect& _rect)
	{
		int section = checkQuad(node->rect, _rect);
		for (int i = 0; i < 4; ++i)
		{
			if ((section >> i) & 1)
			{
				if (node->children[i] == nullptr)
					node->children[i] = new QuadNode(getRect(node->rect, (QuadRant)i));
				insert(node->children[i], _rect);
			}
		}
	}	
	// 1 << 0位是第一象限, 1 << 1位是第二象限, 依次类推
	int checkQuad(QuadRect& target,QuadRect& _rect)
	{
		int ret = 0;
		// 一二象限
		if (isInSection(target.midH, target.top, _rect.bottom)
			|| isInSection(target.midH, target.top, _rect.top))
		{
			//第一象限
			if (isInSection(target.midV, target.right, _rect.right)
				|| isInSection(target.midV, target.right, _rect.left))
				ret |= (1 << 0);
			//第二象限
			if (isInSection(target.left, target.midV, _rect.right)
				|| isInSection(target.left, target.midV, _rect.left))
				ret |= (1 << 1);
		}

		// 三四象限
		if (isInSection(target.bottom, target.midH, _rect.bottom)
			|| isInSection(target.bottom, target.midH, _rect.top))
		{
			//第三象限
			if (isInSection(target.left, target.midV, _rect.right)
				|| isInSection(target.left, target.midV, _rect.left))
				ret |= (1 << 2);
			//第四象限
			if (isInSection(target.midV, target.right, _rect.right)
				|| isInSection(target.midV, target.right, _rect.left))
				ret |= (1 << 3);
		}
		return ret;
	}
public:
	QuadTrie(QuadRect rect)
	{
		root = new QuadNode(rect);
	}

	~QuadTrie()
	{
		delete root;
	}

	void insert(QuadRect rect)
	{
		// 检查是否在范围内
		if (checkQuad(root->rect, rect) == 0) return;

		insert(root, rect);
	}

	void insert(QuadNode* node, QuadRect& _rect)
	{
		++node->childCount;
		//小于三个时 就加入container
		if (node->container && node->container->size() < 3)
		{
			node->container->push_back(_rect);
			return;
		}
		//创建已有分支并销毁container
		if (node->container)
		{
			for (QuadRect& ele : *node->container)
			{
				insertBranch(node, ele);
			}
			delete node->container;
			node->container = nullptr;
		}
		insertBranch(node, _rect);
	}
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

KamikazePilot

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

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

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

打赏作者

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

抵扣说明:

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

余额充值